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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYimingWu <xp8110@outlook.com>2020-05-16 18:08:40 +0300
committerYimingWu <xp8110@outlook.com>2020-05-16 18:08:40 +0300
commitcd54abd2c1316136753f7bbe227bd762a5f9e7d9 (patch)
tree69f2a4a1a5013acc78213bb4f3fe888912380ea4 /source/blender/editors
parentf7770cb97bb9d19d0806f67da9377129fd4d09b0 (diff)
parenteaf7d36d66e551c3262d69f472b4028aeccb7e97 (diff)
Merge remote-tracking branch 'origin/master' into temp-lanpr-review
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c636
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c105
-rw-r--r--source/blender/editors/animation/anim_deps.c38
-rw-r--r--source/blender/editors/animation/anim_draw.c91
-rw-r--r--source/blender/editors/animation/anim_filter.c324
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c5
-rw-r--r--source/blender/editors/animation/anim_markers.c135
-rw-r--r--source/blender/editors/animation/anim_motion_paths.c12
-rw-r--r--source/blender/editors/animation/anim_ops.c47
-rw-r--r--source/blender/editors/animation/drivers.c39
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c58
-rw-r--r--source/blender/editors/animation/keyframes_draw.c41
-rw-r--r--source/blender/editors/animation/keyframes_edit.c34
-rw-r--r--source/blender/editors/animation/keyframes_general.c16
-rw-r--r--source/blender/editors/animation/keyframing.c273
-rw-r--r--source/blender/editors/animation/keyingsets.c108
-rw-r--r--source/blender/editors/animation/time_scrub_ui.c56
-rw-r--r--source/blender/editors/armature/armature_add.c581
-rw-r--r--source/blender/editors/armature/armature_edit.c289
-rw-r--r--source/blender/editors/armature/armature_intern.h52
-rw-r--r--source/blender/editors/armature/armature_naming.c87
-rw-r--r--source/blender/editors/armature/armature_ops.c3
-rw-r--r--source/blender/editors/armature/armature_relations.c41
-rw-r--r--source/blender/editors/armature/armature_select.c730
-rw-r--r--source/blender/editors/armature/armature_skinning.c12
-rw-r--r--source/blender/editors/armature/armature_utils.c40
-rw-r--r--source/blender/editors/armature/editarmature_undo.c11
-rw-r--r--source/blender/editors/armature/meshlaplacian.c14
-rw-r--r--source/blender/editors/armature/pose_edit.c21
-rw-r--r--source/blender/editors/armature/pose_group.c5
-rw-r--r--source/blender/editors/armature/pose_lib.c120
-rw-r--r--source/blender/editors/armature/pose_select.c88
-rw-r--r--source/blender/editors/armature/pose_slide.c117
-rw-r--r--source/blender/editors/armature/pose_transform.c31
-rw-r--r--source/blender/editors/armature/pose_utils.c4
-rw-r--r--source/blender/editors/curve/CMakeLists.txt1
-rw-r--r--source/blender/editors/curve/curve_intern.h19
-rw-r--r--source/blender/editors/curve/curve_ops.c2
-rw-r--r--source/blender/editors/curve/editcurve.c856
-rw-r--r--source/blender/editors/curve/editcurve_add.c4
-rw-r--r--source/blender/editors/curve/editcurve_paint.c63
-rw-r--r--source/blender/editors/curve/editcurve_query.c244
-rw-r--r--source/blender/editors/curve/editcurve_select.c13
-rw-r--r--source/blender/editors/curve/editcurve_undo.c13
-rw-r--r--source/blender/editors/curve/editfont.c18
-rw-r--r--source/blender/editors/curve/editfont_undo.c6
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt13
-rw-r--r--source/blender/editors/gizmo_library/geometry/geom_arrow_gizmo.c2
-rw-r--r--source/blender/editors/gizmo_library/geometry/geom_cube_gizmo.c2
-rw-r--r--source/blender/editors/gizmo_library/geometry/geom_dial_gizmo.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_draw_utils.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_geometry.h4
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_intern.h3
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_presets.c6
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_utils.c12
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c35
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c4
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c44
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c69
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c70
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c75
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c68
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt6
-rw-r--r--source/blender/editors/gpencil/annotate_draw.c641
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c712
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c848
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c72
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c100
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c15
-rw-r--r--source/blender/editors/gpencil/gpencil_armature.c52
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c168
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c851
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c880
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c352
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h122
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c203
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c139
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c343
-rw-r--r--source/blender/editors/gpencil/gpencil_ops_versioning.c34
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c1717
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c317
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c (renamed from source/blender/editors/gpencil/gpencil_brush.c)836
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c343
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c893
-rw-r--r--source/blender/editors/gpencil/gpencil_uv.c590
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_ops.c899
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_paint.c1410
-rw-r--r--source/blender/editors/gpencil/gpencil_weight_paint.c900
-rw-r--r--source/blender/editors/include/BIF_glutil.h8
-rw-r--r--source/blender/editors/include/ED_anim_api.h56
-rw-r--r--source/blender/editors/include/ED_armature.h187
-rw-r--r--source/blender/editors/include/ED_buttons.h8
-rw-r--r--source/blender/editors/include/ED_clip.h26
-rw-r--r--source/blender/editors/include/ED_curve.h8
-rw-r--r--source/blender/editors/include/ED_datafiles.h20
-rw-r--r--source/blender/editors/include/ED_fileselect.h25
-rw-r--r--source/blender/editors/include/ED_gizmo_library.h8
-rw-r--r--source/blender/editors/include/ED_gizmo_utils.h8
-rw-r--r--source/blender/editors/include/ED_gpencil.h110
-rw-r--r--source/blender/editors/include/ED_image.h74
-rw-r--r--source/blender/editors/include/ED_info.h14
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h8
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h20
-rw-r--r--source/blender/editors/include/ED_keyframing.h85
-rw-r--r--source/blender/editors/include/ED_lattice.h8
-rw-r--r--source/blender/editors/include/ED_logic.h8
-rw-r--r--source/blender/editors/include/ED_markers.h8
-rw-r--r--source/blender/editors/include/ED_mask.h46
-rw-r--r--source/blender/editors/include/ED_mball.h8
-rw-r--r--source/blender/editors/include/ED_mesh.h31
-rw-r--r--source/blender/editors/include/ED_node.h27
-rw-r--r--source/blender/editors/include/ED_numinput.h8
-rw-r--r--source/blender/editors/include/ED_object.h83
-rw-r--r--source/blender/editors/include/ED_outliner.h11
-rw-r--r--source/blender/editors/include/ED_paint.h17
-rw-r--r--source/blender/editors/include/ED_particle.h12
-rw-r--r--source/blender/editors/include/ED_physics.h8
-rw-r--r--source/blender/editors/include/ED_render.h12
-rw-r--r--source/blender/editors/include/ED_scene.h8
-rw-r--r--source/blender/editors/include/ED_screen.h186
-rw-r--r--source/blender/editors/include/ED_screen_types.h23
-rw-r--r--source/blender/editors/include/ED_sculpt.h15
-rw-r--r--source/blender/editors/include/ED_select_utils.h15
-rw-r--r--source/blender/editors/include/ED_sequencer.h8
-rw-r--r--source/blender/editors/include/ED_sound.h8
-rw-r--r--source/blender/editors/include/ED_space_api.h12
-rw-r--r--source/blender/editors/include/ED_text.h10
-rw-r--r--source/blender/editors/include/ED_time_scrub_ui.h14
-rw-r--r--source/blender/editors/include/ED_transform.h12
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h18
-rw-r--r--source/blender/editors/include/ED_transverts.h8
-rw-r--r--source/blender/editors/include/ED_types.h8
-rw-r--r--source/blender/editors/include/ED_undo.h13
-rw-r--r--source/blender/editors/include/ED_userpref.h8
-rw-r--r--source/blender/editors/include/ED_util.h10
-rw-r--r--source/blender/editors/include/ED_util_imbuf.h52
-rw-r--r--source/blender/editors/include/ED_uvedit.h12
-rw-r--r--source/blender/editors/include/ED_view3d.h221
-rw-r--r--source/blender/editors/include/ED_view3d_offscreen.h110
-rw-r--r--source/blender/editors/include/UI_icons.h25
-rw-r--r--source/blender/editors/include/UI_interface.h226
-rw-r--r--source/blender/editors/include/UI_interface_icons.h27
-rw-r--r--source/blender/editors/include/UI_resources.h22
-rw-r--r--source/blender/editors/include/UI_view2d.h65
-rw-r--r--source/blender/editors/interface/CMakeLists.txt3
-rw-r--r--source/blender/editors/interface/interface.c404
-rw-r--r--source/blender/editors/interface/interface_align.c4
-rw-r--r--source/blender/editors/interface/interface_anim.c56
-rw-r--r--source/blender/editors/interface/interface_context_menu.c38
-rw-r--r--source/blender/editors/interface/interface_draw.c101
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c24
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c44
-rw-r--r--source/blender/editors/interface/interface_eyedropper_colorband.c2
-rw-r--r--source/blender/editors/interface/interface_eyedropper_datablock.c64
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c46
-rw-r--r--source/blender/editors/interface/interface_eyedropper_driver.c6
-rw-r--r--source/blender/editors/interface/interface_eyedropper_gpencil_color.c121
-rw-r--r--source/blender/editors/interface/interface_eyedropper_intern.h2
-rw-r--r--source/blender/editors/interface/interface_handlers.c1192
-rw-r--r--source/blender/editors/interface/interface_icons.c243
-rw-r--r--source/blender/editors/interface/interface_icons_event.c57
-rw-r--r--source/blender/editors/interface/interface_intern.h222
-rw-r--r--source/blender/editors/interface/interface_layout.c481
-rw-r--r--source/blender/editors/interface/interface_ops.c105
-rw-r--r--source/blender/editors/interface/interface_panel.c904
-rw-r--r--source/blender/editors/interface/interface_query.c136
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c8
-rw-r--r--source/blender/editors/interface/interface_region_hud.c246
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c7
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c75
-rw-r--r--source/blender/editors/interface/interface_region_popover.c37
-rw-r--r--source/blender/editors/interface/interface_region_popup.c127
-rw-r--r--source/blender/editors/interface/interface_region_search.c332
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c66
-rw-r--r--source/blender/editors/interface/interface_regions.c30
-rw-r--r--source/blender/editors/interface/interface_regions_intern.h4
-rw-r--r--source/blender/editors/interface/interface_style.c71
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.c1098
-rw-r--r--source/blender/editors/interface/interface_template_search_operator.c151
-rw-r--r--source/blender/editors/interface/interface_templates.c849
-rw-r--r--source/blender/editors/interface/interface_undo.c139
-rw-r--r--source/blender/editors/interface/interface_utils.c90
-rw-r--r--source/blender/editors/interface/interface_widgets.c340
-rw-r--r--source/blender/editors/interface/resources.c150
-rw-r--r--source/blender/editors/interface/view2d.c205
-rw-r--r--source/blender/editors/interface/view2d_draw.c48
-rw-r--r--source/blender/editors/interface/view2d_gizmo_navigate.c19
-rw-r--r--source/blender/editors/interface/view2d_ops.c280
-rw-r--r--source/blender/editors/io/CMakeLists.txt6
-rw-r--r--source/blender/editors/io/io_alembic.c4
-rw-r--r--source/blender/editors/io/io_alembic.h2
-rw-r--r--source/blender/editors/io/io_cache.c4
-rw-r--r--source/blender/editors/io/io_cache.h2
-rw-r--r--source/blender/editors/io/io_collada.c4
-rw-r--r--source/blender/editors/io/io_usd.c2
-rw-r--r--source/blender/editors/io/io_usd.h2
-rw-r--r--source/blender/editors/lanpr/lanpr_cpu.c64
-rw-r--r--source/blender/editors/lattice/editlattice_select.c8
-rw-r--r--source/blender/editors/lattice/editlattice_undo.c14
-rw-r--r--source/blender/editors/lattice/lattice_ops.c4
-rw-r--r--source/blender/editors/mask/CMakeLists.txt1
-rw-r--r--source/blender/editors/mask/mask_add.c185
-rw-r--r--source/blender/editors/mask/mask_draw.c87
-rw-r--r--source/blender/editors/mask/mask_edit.c371
-rw-r--r--source/blender/editors/mask/mask_editaction.c8
-rw-r--r--source/blender/editors/mask/mask_intern.h71
-rw-r--r--source/blender/editors/mask/mask_ops.c397
-rw-r--r--source/blender/editors/mask/mask_query.c833
-rw-r--r--source/blender/editors/mask/mask_relationships.c11
-rw-r--r--source/blender/editors/mask/mask_select.c104
-rw-r--r--source/blender/editors/mask/mask_shapekey.c20
-rw-r--r--source/blender/editors/mesh/editface.c25
-rw-r--r--source/blender/editors/mesh/editmesh_add.c4
-rw-r--r--source/blender/editors/mesh/editmesh_add_gizmo.c12
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c30
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c16
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c90
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_screw.c2
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin.c4
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c27
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c48
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c20
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c91
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c22
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c63
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c35
-rw-r--r--source/blender/editors/mesh/editmesh_path.c10
-rw-r--r--source/blender/editors/mesh/editmesh_polybuild.c32
-rw-r--r--source/blender/editors/mesh/editmesh_preselect_edgering.c2
-rw-r--r--source/blender/editors/mesh/editmesh_preselect_elem.c4
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c62
-rw-r--r--source/blender/editors/mesh/editmesh_rip_edge.c14
-rw-r--r--source/blender/editors/mesh/editmesh_select.c56
-rw-r--r--source/blender/editors/mesh/editmesh_select_similar.c6
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c659
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c30
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c85
-rw-r--r--source/blender/editors/mesh/mesh_data.c2
-rw-r--r--source/blender/editors/mesh/mesh_intern.h2
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c110
-rw-r--r--source/blender/editors/mesh/mesh_ops.c18
-rw-r--r--source/blender/editors/mesh/meshtools.c179
-rw-r--r--source/blender/editors/metaball/editmball_undo.c14
-rw-r--r--source/blender/editors/metaball/mball_edit.c12
-rw-r--r--source/blender/editors/metaball/mball_ops.c2
-rw-r--r--source/blender/editors/object/CMakeLists.txt7
-rw-r--r--source/blender/editors/object/object_add.c230
-rw-r--r--source/blender/editors/object/object_bake.c22
-rw-r--r--source/blender/editors/object/object_bake_api.c59
-rw-r--r--source/blender/editors/object/object_collection.c22
-rw-r--r--source/blender/editors/object/object_constraint.c311
-rw-r--r--source/blender/editors/object/object_data_transfer.c2
-rw-r--r--source/blender/editors/object/object_data_transform.c115
-rw-r--r--source/blender/editors/object/object_edit.c316
-rw-r--r--source/blender/editors/object/object_facemap_ops.c10
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c31
-rw-r--r--source/blender/editors/object/object_hook.c20
-rw-r--r--source/blender/editors/object/object_intern.h17
-rw-r--r--source/blender/editors/object/object_modes.c9
-rw-r--r--source/blender/editors/object/object_modifier.c476
-rw-r--r--source/blender/editors/object/object_ops.c14
-rw-r--r--source/blender/editors/object/object_random.c4
-rw-r--r--source/blender/editors/object/object_relations.c210
-rw-r--r--source/blender/editors/object/object_remesh.c586
-rw-r--r--source/blender/editors/object/object_select.c27
-rw-r--r--source/blender/editors/object/object_shader_fx.c14
-rw-r--r--source/blender/editors/object/object_shapekey.c6
-rw-r--r--source/blender/editors/object/object_transform.c194
-rw-r--r--source/blender/editors/object/object_utils.c292
-rw-r--r--source/blender/editors/object/object_vgroup.c327
-rw-r--r--source/blender/editors/object/object_volume.c197
-rw-r--r--source/blender/editors/object/object_warp.c2
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c18
-rw-r--r--source/blender/editors/physics/particle_boids.c2
-rw-r--r--source/blender/editors/physics/particle_edit.c202
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c6
-rw-r--r--source/blender/editors/physics/particle_object.c17
-rw-r--r--source/blender/editors/physics/physics_fluid.c58
-rw-r--r--source/blender/editors/physics/physics_intern.h1
-rw-r--r--source/blender/editors/physics/physics_ops.c5
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c2
-rw-r--r--source/blender/editors/physics/rigidbody_object.c2
-rw-r--r--source/blender/editors/render/render_internal.c86
-rw-r--r--source/blender/editors/render/render_opengl.c101
-rw-r--r--source/blender/editors/render/render_preview.c113
-rw-r--r--source/blender/editors/render/render_shading.c117
-rw-r--r--source/blender/editors/render/render_update.c54
-rw-r--r--source/blender/editors/render/render_view.c130
-rw-r--r--source/blender/editors/scene/scene_edit.c8
-rw-r--r--source/blender/editors/screen/area.c1526
-rw-r--r--source/blender/editors/screen/area_query.c116
-rw-r--r--source/blender/editors/screen/area_utils.c15
-rw-r--r--source/blender/editors/screen/glutil.c14
-rw-r--r--source/blender/editors/screen/screen_context.c90
-rw-r--r--source/blender/editors/screen/screen_draw.c180
-rw-r--r--source/blender/editors/screen/screen_edit.c786
-rw-r--r--source/blender/editors/screen/screen_geometry.c87
-rw-r--r--source/blender/editors/screen/screen_intern.h23
-rw-r--r--source/blender/editors/screen/screen_ops.c953
-rw-r--r--source/blender/editors/screen/screen_user_menu.c18
-rw-r--r--source/blender/editors/screen/screendump.c14
-rw-r--r--source/blender/editors/screen/workspace_edit.c18
-rw-r--r--source/blender/editors/screen/workspace_layout_edit.c12
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt12
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c457
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c80
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve_undo.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c95
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c112
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c151
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c287
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h9
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c146
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c339
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c93
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c85
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c349
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_utils.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_proj.c14
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c90
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c10
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c6997
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_automasking.c304
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c689
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_detail.c428
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_dyntopo.c439
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.c961
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mask.c502
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c673
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h576
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_mask_expand.c526
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c464
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_pose.c900
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_smooth.c608
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_transform.c381
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c638
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c34
-rw-r--r--source/blender/editors/sound/sound_ops.c16
-rw-r--r--source/blender/editors/space_action/action_buttons.c6
-rw-r--r--source/blender/editors/space_action/action_data.c68
-rw-r--r--source/blender/editors/space_action/action_draw.c37
-rw-r--r--source/blender/editors/space_action/action_edit.c110
-rw-r--r--source/blender/editors/space_action/action_intern.h7
-rw-r--r--source/blender/editors/space_action/action_ops.c5
-rw-r--r--source/blender/editors/space_action/action_select.c46
-rw-r--r--source/blender/editors/space_action/space_action.c319
-rw-r--r--source/blender/editors/space_api/spacetypes.c30
-rw-r--r--source/blender/editors/space_buttons/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c69
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c10
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c12
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c205
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c24
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c28
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_ops.c21
-rw-r--r--source/blender/editors/space_clip/clip_draw.c155
-rw-r--r--source/blender/editors/space_clip/clip_editor.c93
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c57
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c34
-rw-r--r--source/blender/editors/space_clip/clip_intern.h16
-rw-r--r--source/blender/editors/space_clip/clip_ops.c133
-rw-r--r--source/blender/editors/space_clip/clip_toolbar.c18
-rw-r--r--source/blender/editors/space_clip/clip_utils.c7
-rw-r--r--source/blender/editors/space_clip/space_clip.c609
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c70
-rw-r--r--source/blender/editors/space_clip/tracking_ops_detect.c4
-rw-r--r--source/blender/editors/space_clip/tracking_ops_orient.c14
-rw-r--r--source/blender/editors/space_clip/tracking_ops_plane.c32
-rw-r--r--source/blender/editors/space_clip/tracking_ops_solve.c6
-rw-r--r--source/blender/editors/space_clip/tracking_ops_track.c16
-rw-r--r--source/blender/editors/space_clip/tracking_select.c91
-rw-r--r--source/blender/editors/space_console/console_draw.c120
-rw-r--r--source/blender/editors/space_console/console_intern.h8
-rw-r--r--source/blender/editors/space_console/console_ops.c114
-rw-r--r--source/blender/editors/space_console/space_console.c95
-rw-r--r--source/blender/editors/space_file/file_draw.c81
-rw-r--r--source/blender/editors/space_file/file_intern.h31
-rw-r--r--source/blender/editors/space_file/file_ops.c640
-rw-r--r--source/blender/editors/space_file/file_panels.c18
-rw-r--r--source/blender/editors/space_file/file_utils.c8
-rw-r--r--source/blender/editors/space_file/filelist.c383
-rw-r--r--source/blender/editors/space_file/filelist.h10
-rw-r--r--source/blender/editors/space_file/filesel.c63
-rw-r--r--source/blender/editors/space_file/fsmenu.c408
-rw-r--r--source/blender/editors/space_file/space_file.c257
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c106
-rw-r--r--source/blender/editors/space_graph/graph_draw.c76
-rw-r--r--source/blender/editors/space_graph/graph_edit.c68
-rw-r--r--source/blender/editors/space_graph/graph_intern.h8
-rw-r--r--source/blender/editors/space_graph/graph_ops.c14
-rw-r--r--source/blender/editors/space_graph/graph_select.c42
-rw-r--r--source/blender/editors/space_graph/graph_utils.c54
-rw-r--r--source/blender/editors/space_graph/space_graph.c227
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_image/image_buttons.c22
-rw-r--r--source/blender/editors/space_image/image_draw.c157
-rw-r--r--source/blender/editors/space_image/image_edit.c129
-rw-r--r--source/blender/editors/space_image/image_intern.h4
-rw-r--r--source/blender/editors/space_image/image_ops.c1081
-rw-r--r--source/blender/editors/space_image/image_sequence.c255
-rw-r--r--source/blender/editors/space_image/image_undo.c94
-rw-r--r--source/blender/editors/space_image/space_image.c363
-rw-r--r--source/blender/editors/space_info/info_draw.c140
-rw-r--r--source/blender/editors/space_info/info_intern.h20
-rw-r--r--source/blender/editors/space_info/info_ops.c4
-rw-r--r--source/blender/editors/space_info/info_report.c18
-rw-r--r--source/blender/editors/space_info/info_stats.c323
-rw-r--r--source/blender/editors/space_info/space_info.c105
-rw-r--r--source/blender/editors/space_info/textview.c154
-rw-r--r--source/blender/editors/space_info/textview.h56
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c80
-rw-r--r--source/blender/editors/space_nla/nla_channels.c26
-rw-r--r--source/blender/editors/space_nla/nla_draw.c36
-rw-r--r--source/blender/editors/space_nla/nla_edit.c47
-rw-r--r--source/blender/editors/space_nla/nla_intern.h4
-rw-r--r--source/blender/editors/space_nla/nla_ops.c2
-rw-r--r--source/blender/editors/space_nla/nla_select.c16
-rw-r--r--source/blender/editors/space_nla/space_nla.c239
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_node/drawnode.c1026
-rw-r--r--source/blender/editors/space_node/node_add.c12
-rw-r--r--source/blender/editors/space_node/node_buttons.c12
-rw-r--r--source/blender/editors/space_node/node_draw.c419
-rw-r--r--source/blender/editors/space_node/node_edit.c214
-rw-r--r--source/blender/editors/space_node/node_gizmo.c45
-rw-r--r--source/blender/editors/space_node/node_group.c29
-rw-r--r--source/blender/editors/space_node/node_intern.h28
-rw-r--r--source/blender/editors/space_node/node_relationships.c78
-rw-r--r--source/blender/editors/space_node/node_select.c89
-rw-r--r--source/blender/editors/space_node/node_templates.c124
-rw-r--r--source/blender/editors/space_node/node_view.c94
-rw-r--r--source/blender/editors/space_node/space_node.c261
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c194
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c94
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c260
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c416
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h33
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c123
-rw-r--r--source/blender/editors/space_outliner/outliner_sync.c14
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c349
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c99
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c43
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c140
-rw-r--r--source/blender/editors/space_script/script_edit.c12
-rw-r--r--source/blender/editors/space_script/script_ops.c2
-rw-r--r--source/blender/editors/space_script/space_script.c46
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c282
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c1462
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c1132
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h41
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_preview.c18
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c167
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c211
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c229
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c534
-rw-r--r--source/blender/editors/space_statusbar/space_statusbar.c38
-rw-r--r--source/blender/editors/space_text/space_text.c116
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c42
-rw-r--r--source/blender/editors/space_text/text_draw.c178
-rw-r--r--source/blender/editors/space_text/text_format.c4
-rw-r--r--source/blender/editors/space_text/text_format_lua.c2
-rw-r--r--source/blender/editors/space_text/text_format_osl.c2
-rw-r--r--source/blender/editors/space_text/text_format_pov.c2
-rw-r--r--source/blender/editors/space_text/text_format_pov_ini.c2
-rw-r--r--source/blender/editors/space_text/text_format_py.c4
-rw-r--r--source/blender/editors/space_text/text_header.c32
-rw-r--r--source/blender/editors/space_text/text_intern.h24
-rw-r--r--source/blender/editors/space_text/text_ops.c192
-rw-r--r--source/blender/editors/space_text/text_undo.c8
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c70
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c92
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt5
-rw-r--r--source/blender/editors/space_view3d/drawobject.c17
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c565
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c38
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c934
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c578
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c761
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c37
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_armature.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c30
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_empty.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_forcefield.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_light.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate.c47
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c35
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c16
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c106
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c54
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h33
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c67
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c214
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c328
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c102
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c322
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c288
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c66
-rw-r--r--source/blender/editors/transform/CMakeLists.txt33
-rw-r--r--source/blender/editors/transform/transform.c7460
-rw-r--r--source/blender/editors/transform/transform.h221
-rw-r--r--source/blender/editors/transform/transform_constraints.c52
-rw-r--r--source/blender/editors/transform/transform_constraints.h48
-rw-r--r--source/blender/editors/transform/transform_convert.c599
-rw-r--r--source/blender/editors/transform/transform_convert.h41
-rw-r--r--source/blender/editors/transform/transform_convert_action.c16
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c275
-rw-r--r--source/blender/editors/transform/transform_convert_cursor.c2
-rw-r--r--source/blender/editors/transform/transform_convert_curve.c10
-rw-r--r--source/blender/editors/transform/transform_convert_gpencil.c20
-rw-r--r--source/blender/editors/transform/transform_convert_graph.c18
-rw-r--r--source/blender/editors/transform/transform_convert_lattice.c1
-rw-r--r--source/blender/editors/transform/transform_convert_mask.c6
-rw-r--r--source/blender/editors/transform/transform_convert_mball.c1
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c155
-rw-r--r--source/blender/editors/transform/transform_convert_nla.c12
-rw-r--r--source/blender/editors/transform/transform_convert_node.c4
-rw-r--r--source/blender/editors/transform/transform_convert_object.c166
-rw-r--r--source/blender/editors/transform/transform_convert_paintcurve.c1
-rw-r--r--source/blender/editors/transform/transform_convert_particle.c3
-rw-r--r--source/blender/editors/transform/transform_convert_sculpt.c5
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c98
-rw-r--r--source/blender/editors/transform/transform_convert_tracking.c6
-rw-r--r--source/blender/editors/transform/transform_draw_cursors.c10
-rw-r--r--source/blender/editors/transform/transform_generics.c431
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c102
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c144
-rw-r--r--source/blender/editors/transform/transform_gizmo_extrude_3d.c14
-rw-r--r--source/blender/editors/transform/transform_input.c108
-rw-r--r--source/blender/editors/transform/transform_mode.c1264
-rw-r--r--source/blender/editors/transform/transform_mode.h160
-rw-r--r--source/blender/editors/transform/transform_mode_align.c96
-rw-r--r--source/blender/editors/transform/transform_mode_baketime.c140
-rw-r--r--source/blender/editors/transform/transform_mode_bbone_resize.c184
-rw-r--r--source/blender/editors/transform/transform_mode_bend.c308
-rw-r--r--source/blender/editors/transform/transform_mode_boneenvelope.c121
-rw-r--r--source/blender/editors/transform/transform_mode_boneroll.c115
-rw-r--r--source/blender/editors/transform/transform_mode_curveshrinkfatten.c124
-rw-r--r--source/blender/editors/transform/transform_mode_edge_bevelweight.c130
-rw-r--r--source/blender/editors/transform/transform_mode_edge_crease.c134
-rw-r--r--source/blender/editors/transform/transform_mode_edge_rotate_normal.c156
-rw-r--r--source/blender/editors/transform/transform_mode_edge_seq_slide.c147
-rw-r--r--source/blender/editors/transform/transform_mode_edge_slide.c1498
-rw-r--r--source/blender/editors/transform/transform_mode_gpopacity.c120
-rw-r--r--source/blender/editors/transform/transform_mode_gpshrinkfatten.c122
-rw-r--r--source/blender/editors/transform/transform_mode_maskshrinkfatten.c154
-rw-r--r--source/blender/editors/transform/transform_mode_mirror.c129
-rw-r--r--source/blender/editors/transform/transform_mode_push_pull.c137
-rw-r--r--source/blender/editors/transform/transform_mode_resize.c170
-rw-r--r--source/blender/editors/transform/transform_mode_rotate.c198
-rw-r--r--source/blender/editors/transform/transform_mode_shear.c248
-rw-r--r--source/blender/editors/transform/transform_mode_shrink_fatten.c146
-rw-r--r--source/blender/editors/transform/transform_mode_skin_resize.c141
-rw-r--r--source/blender/editors/transform/transform_mode_tilt.c119
-rw-r--r--source/blender/editors/transform/transform_mode_timescale.c158
-rw-r--r--source/blender/editors/transform/transform_mode_timeslide.c236
-rw-r--r--source/blender/editors/transform/transform_mode_timetranslate.c167
-rw-r--r--source/blender/editors/transform/transform_mode_tosphere.c139
-rw-r--r--source/blender/editors/transform/transform_mode_trackball.c170
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c412
-rw-r--r--source/blender/editors/transform/transform_mode_vert_slide.c666
-rw-r--r--source/blender/editors/transform/transform_ops.c71
-rw-r--r--source/blender/editors/transform/transform_orientations.c80
-rw-r--r--source/blender/editors/transform/transform_snap.c111
-rw-r--r--source/blender/editors/transform/transform_snap.h8
-rw-r--r--source/blender/editors/transform/transform_snap_object.c635
-rw-r--r--source/blender/editors/undo/ed_undo.c169
-rw-r--r--source/blender/editors/undo/memfile_undo.c146
-rw-r--r--source/blender/editors/util/CMakeLists.txt3
-rw-r--r--source/blender/editors/util/ed_transverts.c12
-rw-r--r--source/blender/editors/util/ed_util.c50
-rw-r--r--source/blender/editors/util/ed_util_imbuf.c571
-rw-r--r--source/blender/editors/util/gizmo_utils.c6
-rw-r--r--source/blender/editors/util/numinput.c64
-rw-r--r--source/blender/editors/util/select_utils.c2
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt1
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c6
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c50
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h28
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c3532
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c195
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.h4
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c3415
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c87
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c230
595 files changed, 65738 insertions, 44273 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 2ec1634fa38..cd17a490240 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -35,33 +35,38 @@
#include "DNA_armature_types.h"
#include "DNA_cachefile_types.h"
#include "DNA_camera_types.h"
-#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_space_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_hair_types.h"
#include "DNA_key_types.h"
-#include "DNA_light_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_light_types.h"
#include "DNA_linestyle_types.h"
-#include "DNA_mesh_types.h"
+#include "DNA_mask_types.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_node_types.h"
-#include "DNA_world_types.h"
-#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_pointcloud_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_simulation_types.h"
+#include "DNA_space_types.h"
#include "DNA_speaker_types.h"
-#include "DNA_mask_types.h"
+#include "DNA_volume_types.h"
+#include "DNA_world_types.h"
#include "RNA_access.h"
+#include "BKE_anim_data.h"
#include "BKE_animsys.h"
+#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_gpencil.h"
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_nla.h"
-#include "BKE_context.h"
#include "GPU_immediate.h"
#include "GPU_state.h"
@@ -71,6 +76,7 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
@@ -114,7 +120,7 @@ static void acf_generic_root_backdrop(bAnimContext *ac,
float ymaxc)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
@@ -125,7 +131,7 @@ static void acf_generic_root_backdrop(bAnimContext *ac,
/* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT :
(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- UI_draw_roundbox_3fvAlpha(
+ UI_draw_roundbox_3fv_alpha(
true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
@@ -145,7 +151,7 @@ static void acf_generic_dataexpand_backdrop(bAnimContext *ac,
float ymaxc)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
@@ -253,7 +259,7 @@ static void acf_generic_channel_backdrop(bAnimContext *ac,
float ymaxc)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
@@ -466,7 +472,7 @@ static void acf_summary_color(bAnimContext *UNUSED(ac),
static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
float color[3];
/* set backdrop drawing color */
@@ -477,7 +483,7 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
* - special hack: make the top a bit higher, since we are first...
*/
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
- UI_draw_roundbox_3fvAlpha(
+ UI_draw_roundbox_3fv_alpha(
true, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
@@ -698,6 +704,12 @@ static int acf_object_icon(bAnimListElem *ale)
return ICON_OUTLINER_OB_FONT;
case OB_SURF:
return ICON_OUTLINER_OB_SURFACE;
+ case OB_HAIR:
+ return ICON_OUTLINER_OB_HAIR;
+ case OB_POINTCLOUD:
+ return ICON_OUTLINER_OB_POINTCLOUD;
+ case OB_VOLUME:
+ return ICON_OUTLINER_OB_VOLUME;
case OB_EMPTY:
return ICON_OUTLINER_OB_EMPTY;
case OB_GPENCIL:
@@ -846,7 +858,7 @@ static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[
bool showGroupColors = acf_show_channel_colors(ac);
if (showGroupColors && agrp->customCol) {
- unsigned char cp[3];
+ uchar cp[3];
/* highlight only for active */
if (ale->flag & AGRP_ACTIVE) {
@@ -874,7 +886,7 @@ static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[
static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
@@ -884,7 +896,7 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc
/* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- UI_draw_roundbox_3fvAlpha(
+ UI_draw_roundbox_3fv_alpha(
true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
@@ -916,7 +928,8 @@ static bool acf_group_setting_valid(bAnimContext *ac,
/* for now, all settings are supported, though some are only conditionally */
switch (setting) {
/* unsupported */
- case ACHANNEL_SETTING_SOLO: /* Only available in NLA Editor for tracks */
+ case ACHANNEL_SETTING_SOLO: /* Only available in NLA Editor for tracks */
+ case ACHANNEL_SETTING_PINNED: /* Only for NLA actions */
return false;
/* conditionally supported */
@@ -1147,7 +1160,7 @@ static void acf_nla_controls_backdrop(bAnimContext *ac,
float ymaxc)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
@@ -1157,7 +1170,7 @@ static void acf_nla_controls_backdrop(bAnimContext *ac,
/* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- UI_draw_roundbox_3fvAlpha(
+ UI_draw_roundbox_3fv_alpha(
true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
}
@@ -1963,6 +1976,25 @@ static int acf_dsskey_icon(bAnimListElem *UNUSED(ale))
return ICON_SHAPEKEY_DATA;
}
+/* check if some setting exists for this channel */
+static bool acf_dsskey_setting_valid(bAnimContext *ac,
+ bAnimListElem *UNUSED(ale),
+ eAnimChannel_Settings setting)
+{
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT:
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
+
+ /* mute is only supported for NLA */
+ case ACHANNEL_SETTING_MUTE:
+ return ((ac) && (ac->spacetype == SPACE_NLA));
+
+ default:
+ return false;
+ }
+}
+
/* get the appropriate flag(s) for the setting when it is valid */
static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac),
eAnimChannel_Settings setting,
@@ -2029,9 +2061,9 @@ static bAnimChannelType ACF_DSSKEY = {
acf_generic_idblock_name_prop, /* name prop */
acf_dsskey_icon, /* icon */
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dsskey_setting_flag, /* flag for setting */
- acf_dsskey_setting_ptr, /* pointer for setting */
+ acf_dsskey_setting_valid, /* has setting */
+ acf_dsskey_setting_flag, /* flag for setting */
+ acf_dsskey_setting_ptr, /* pointer for setting */
};
/* World Expander ------------------------------------------- */
@@ -2764,6 +2796,321 @@ static bAnimChannelType ACF_DSSPK = {
acf_dsspk_setting_ptr, /* pointer for setting */
};
+/* Hair Expander ------------------------------------------- */
+
+// TODO: just get this from RNA?
+static int acf_dshair_icon(bAnimListElem *UNUSED(ale))
+{
+ return ICON_HAIR_DATA;
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_dshair_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return VO_DS_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+/* get pointer to the setting */
+static void *acf_dshair_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+{
+ Hair *hair = (Hair *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(hair->flag, type);
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (hair->adt)
+ return GET_ACF_FLAG_PTR(hair->adt->flag, type);
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* hair expander type define */
+static bAnimChannelType ACF_DSHAIR = {
+ "Hair Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dshair_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dshair_setting_flag, /* flag for setting */
+ acf_dshair_setting_ptr /* pointer for setting */
+};
+
+/* PointCloud Expander ------------------------------------------- */
+
+// TODO: just get this from RNA?
+static int acf_dspointcloud_icon(bAnimListElem *UNUSED(ale))
+{
+ return ICON_POINTCLOUD_DATA;
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_dspointcloud_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return VO_DS_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+/* get pointer to the setting */
+static void *acf_dspointcloud_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
+{
+ PointCloud *pointcloud = (PointCloud *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(pointcloud->flag, type);
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (pointcloud->adt)
+ return GET_ACF_FLAG_PTR(pointcloud->adt->flag, type);
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* pointcloud expander type define */
+static bAnimChannelType ACF_DSPOINTCLOUD = {
+ "PointCloud Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dspointcloud_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dspointcloud_setting_flag, /* flag for setting */
+ acf_dspointcloud_setting_ptr /* pointer for setting */
+};
+
+/* Volume Expander ------------------------------------------- */
+
+// TODO: just get this from RNA?
+static int acf_dsvolume_icon(bAnimListElem *UNUSED(ale))
+{
+ return ICON_VOLUME_DATA;
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_dsvolume_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return VO_DS_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+/* get pointer to the setting */
+static void *acf_dsvolume_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
+{
+ Volume *volume = (Volume *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(volume->flag, type);
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (volume->adt)
+ return GET_ACF_FLAG_PTR(volume->adt->flag, type);
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* volume expander type define */
+static bAnimChannelType ACF_DSVOLUME = {
+ "Volume Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dsvolume_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dsvolume_setting_flag, /* flag for setting */
+ acf_dsvolume_setting_ptr /* pointer for setting */
+};
+
+/* Simulation Expander ----------------------------------------- */
+
+static int acf_dssimulation_icon(bAnimListElem *UNUSED(ale))
+{
+ /* TODO: Use correct icon. */
+ return ICON_PHYSICS;
+}
+
+static int acf_dssimulation_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return SIM_DS_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+static void *acf_dssimulation_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
+{
+ Simulation *simulation = (Simulation *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(simulation->flag, type);
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (simulation->adt)
+ return GET_ACF_FLAG_PTR(simulation->adt->flag, type);
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+static bAnimChannelType ACF_DSSIMULATION = {
+ "Simulation Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dssimulation_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dssimulation_setting_flag, /* flag for setting */
+ acf_dssimulation_setting_ptr /* pointer for setting */
+};
+
/* GPencil Expander ------------------------------------------- */
// TODO: just get this from RNA?
@@ -3155,6 +3502,8 @@ static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac),
/* unsupported */
case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */
case ACHANNEL_SETTING_SOLO: /* nla editor only */
+ case ACHANNEL_SETTING_MOD_OFF:
+ case ACHANNEL_SETTING_PINNED: /* nla actions only */
return false;
/* always available */
@@ -3335,6 +3684,9 @@ static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac),
case ACHANNEL_SETTING_EXPAND: /* mask layers are more like F-Curves than groups */
case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
case ACHANNEL_SETTING_SOLO: /* nla editor only */
+ case ACHANNEL_SETTING_MOD_OFF:
+ case ACHANNEL_SETTING_PINNED: /* nla actions only */
+ case ACHANNEL_SETTING_MUTE:
return false;
/* always available */
@@ -3580,7 +3932,7 @@ static void acf_nlaaction_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, fl
static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
AnimData *adt = ale->adt;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[4];
@@ -3754,24 +4106,28 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */
animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */
- animchannelTypeInfo[type++] = &ACF_DSMAT; /* Material Channel */
- animchannelTypeInfo[type++] = &ACF_DSLIGHT; /* Light Channel */
- animchannelTypeInfo[type++] = &ACF_DSCAM; /* Camera Channel */
- animchannelTypeInfo[type++] = &ACF_DSCACHEFILE; /* CacheFile Channel */
- animchannelTypeInfo[type++] = &ACF_DSCUR; /* Curve Channel */
- animchannelTypeInfo[type++] = &ACF_DSSKEY; /* ShapeKey Channel */
- animchannelTypeInfo[type++] = &ACF_DSWOR; /* World Channel */
- animchannelTypeInfo[type++] = &ACF_DSNTREE; /* NodeTree Channel */
- animchannelTypeInfo[type++] = &ACF_DSPART; /* Particle Channel */
- animchannelTypeInfo[type++] = &ACF_DSMBALL; /* MetaBall Channel */
- animchannelTypeInfo[type++] = &ACF_DSARM; /* Armature Channel */
- animchannelTypeInfo[type++] = &ACF_DSMESH; /* Mesh Channel */
- animchannelTypeInfo[type++] = &ACF_DSTEX; /* Texture Channel */
- animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */
- animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */
- animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
- animchannelTypeInfo[type++] = &ACF_DSGPENCIL; /* GreasePencil Channel */
- animchannelTypeInfo[type++] = &ACF_DSMCLIP; /* MovieClip Channel */
+ animchannelTypeInfo[type++] = &ACF_DSMAT; /* Material Channel */
+ animchannelTypeInfo[type++] = &ACF_DSLIGHT; /* Light Channel */
+ animchannelTypeInfo[type++] = &ACF_DSCAM; /* Camera Channel */
+ animchannelTypeInfo[type++] = &ACF_DSCACHEFILE; /* CacheFile Channel */
+ animchannelTypeInfo[type++] = &ACF_DSCUR; /* Curve Channel */
+ animchannelTypeInfo[type++] = &ACF_DSSKEY; /* ShapeKey Channel */
+ animchannelTypeInfo[type++] = &ACF_DSWOR; /* World Channel */
+ animchannelTypeInfo[type++] = &ACF_DSNTREE; /* NodeTree Channel */
+ animchannelTypeInfo[type++] = &ACF_DSPART; /* Particle Channel */
+ animchannelTypeInfo[type++] = &ACF_DSMBALL; /* MetaBall Channel */
+ animchannelTypeInfo[type++] = &ACF_DSARM; /* Armature Channel */
+ animchannelTypeInfo[type++] = &ACF_DSMESH; /* Mesh Channel */
+ animchannelTypeInfo[type++] = &ACF_DSTEX; /* Texture Channel */
+ animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */
+ animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */
+ animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
+ animchannelTypeInfo[type++] = &ACF_DSGPENCIL; /* GreasePencil Channel */
+ animchannelTypeInfo[type++] = &ACF_DSMCLIP; /* MovieClip Channel */
+ animchannelTypeInfo[type++] = &ACF_DSHAIR; /* Hair Channel */
+ animchannelTypeInfo[type++] = &ACF_DSPOINTCLOUD; /* PointCloud Channel */
+ animchannelTypeInfo[type++] = &ACF_DSVOLUME; /* Volume Channel */
+ animchannelTypeInfo[type++] = &ACF_DSSIMULATION; /* Simulation Channel */
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
@@ -3984,6 +4340,10 @@ void ANIM_channel_setting_set(bAnimContext *ac,
#define SLIDER_WIDTH (4 * U.widget_unit)
// min-width of rename textboxes
#define RENAME_TEXT_MIN_WIDTH (U.widget_unit)
+// width of graph editor color bands
+#define GRAPH_COLOR_BAND_WIDTH (0.3f * U.widget_unit)
+// extra offset for the visibility icons in the graph editor
+#define GRAPH_ICON_VISIBILITY_OFFSET (GRAPH_COLOR_BAND_WIDTH * 1.5f)
/* Helper - Check if a channel needs renaming */
static bool achannel_is_being_renamed(const bAnimContext *ac,
@@ -4006,7 +4366,7 @@ void ANIM_channel_draw(
bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
short selected, offset;
float y, ymid, ytext;
@@ -4059,9 +4419,6 @@ void ANIM_channel_draw(
offset += ICON_WIDTH;
}
- /* turn off blending, since not needed anymore... */
- GPU_blend(false);
-
/* step 4) draw special toggles .................................
* - in Graph Editor, checkboxes for visibility in curves area
* - in NLA Editor, glowing dots for solo/not solo...
@@ -4071,7 +4428,7 @@ void ANIM_channel_draw(
if ((ac->spacetype == SPACE_GRAPH) &&
(acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE))) {
- /* for F-Curves, draw color-preview of curve behind checkbox */
+ /* for F-Curves, draw color-preview of curve left to the visibility icon */
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
FCurve *fcu = (FCurve *)ale->data;
uint pos = GPU_vertformat_attr_add(
@@ -4082,17 +4439,26 @@ void ANIM_channel_draw(
/* F-Curve channels need to have a special 'color code' box drawn,
* which is colored with whatever color the curve has stored.
*/
- immUniformColor3fv(fcu->color);
- /* just a solid color rect
- */
- immRectf(pos, offset, yminc, offset + ICON_WIDTH, ymaxc);
+ /* If the curve is hidden, make the rect less opaque. */
+ float rect_alpha = (fcu->flag & FCURVE_VISIBLE) ? 1 : 0.3f;
+ immUniformColor3fvAlpha(fcu->color, rect_alpha);
+ immRectf(pos, offset, yminc, offset + GRAPH_COLOR_BAND_WIDTH, ymaxc);
immUnbindProgram();
}
+
+ /* turn off blending, since not needed anymore... */
+ GPU_blend(false);
+
/* icon is drawn as widget now... */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
- offset += ICON_WIDTH;
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
+ offset += ICON_WIDTH + GRAPH_ICON_VISIBILITY_OFFSET;
+ }
+ else {
+ offset += ICON_WIDTH;
+ }
}
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) {
offset += ICON_WIDTH;
@@ -4102,10 +4468,6 @@ void ANIM_channel_draw(
/* just skip - drawn as widget now */
offset += ICON_WIDTH;
}
- else if (ale->type == ANIMTYPE_GPLAYER) {
- /* just skip - drawn as a widget */
- offset += ICON_WIDTH;
- }
}
/* step 5) draw name ............................................... */
@@ -4113,7 +4475,7 @@ void ANIM_channel_draw(
if (acf->name && !achannel_is_being_renamed(ac, acf, channel_index)) {
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
- unsigned char col[4];
+ uchar col[4];
/* set text color */
/* XXX: if active, highlight differently? */
@@ -4153,8 +4515,16 @@ void ANIM_channel_draw(
}
/* step 6) draw backdrops behind mute+protection toggles + (sliders) ....................... */
- /* reset offset - now goes from RHS of panel */
- offset = 0;
+ /* - Reset offset - now goes from RHS of panel.
+ * - Exception for graph editor, which needs extra space for the scroll bar.
+ */
+ if (ac->spacetype == SPACE_GRAPH &&
+ ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_GROUP)) {
+ offset = V2D_SCROLL_WIDTH;
+ }
+ else {
+ offset = 0;
+ }
/* TODO: when drawing sliders, make those draw instead of these toggles if not enough space */
@@ -4197,10 +4567,17 @@ void ANIM_channel_draw(
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
offset += ICON_WIDTH;
}
+
+ /* grease pencil visibility... */
if (ale->type == ANIMTYPE_GPLAYER) {
offset += ICON_WIDTH;
}
+ /* modifiers toggle... */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MOD_OFF)) {
+ offset += ICON_WIDTH;
+ }
+
/* pinned... */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PINNED)) {
offset += ICON_WIDTH;
@@ -4347,7 +4724,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
ListBase nla_cache = {NULL, NULL};
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
- short flag = 0;
+ eInsertKeyFlags flag = 0;
bool done = false;
float cfra;
@@ -4361,8 +4738,8 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
/* get current frame and apply NLA-mapping to it (if applicable) */
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- /* get flags for keyframing */
- flag = ANIM_get_keyframing_flags(scene, 1);
+ /* Get flags for keyframing. */
+ flag = ANIM_get_keyframing_flags(scene, true);
/* try to resolve the path stored in the F-Curve */
if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
@@ -4401,7 +4778,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
ListBase nla_cache = {NULL, NULL};
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
- short flag = 0;
+ eInsertKeyFlags flag = 0;
bool done = false;
float cfra;
@@ -4416,14 +4793,14 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
cfra = BKE_nla_tweakedit_remap(key->adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
/* get flags for keyframing */
- flag = ANIM_get_keyframing_flags(scene, 1);
+ flag = ANIM_get_keyframing_flags(scene, true);
/* try to resolve the path stored in the F-Curve */
if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop)) {
/* find or create new F-Curve */
// XXX is the group name for this ok?
- bAction *act = verify_adt_action(bmain, (ID *)key, 1);
- FCurve *fcu = verify_fcurve(bmain, act, NULL, &ptr, rna_path, 0, 1);
+ bAction *act = ED_id_action_ensure(bmain, (ID *)key);
+ FCurve *fcu = ED_action_fcurve_ensure(bmain, act, NULL, &ptr, rna_path, 0);
/* set the special 'replace' flag if on a keyframe */
if (fcurve_frame_has_keyframe(fcu, cfra, 0)) {
@@ -4462,7 +4839,7 @@ static void achannel_setting_slider_nla_curve_cb(bContext *C,
ReportList *reports = CTX_wm_reports(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
- short flag = 0;
+ eInsertKeyFlags flag = 0;
bool done = false;
float cfra;
@@ -4470,7 +4847,7 @@ static void achannel_setting_slider_nla_curve_cb(bContext *C,
cfra = (float)CFRA;
/* get flags for keyframing */
- flag = ANIM_get_keyframing_flags(scene, 1);
+ flag = ANIM_get_keyframing_flags(scene, true);
/* Get pointer and property from the slider -
* this should all match up with the NlaStrip required. */
@@ -4521,7 +4898,7 @@ static void draw_setting_widget(bAnimContext *ac,
icon = ICON_HIDE_ON;
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
- tooltip = TIP_("F-Curve is visible in Graph Editor for editing");
+ tooltip = TIP_("F-Curve visibility in Graph Editor");
}
else if (ale->type == ANIMTYPE_GPLAYER) {
tooltip = TIP_("Grease Pencil layer is visible in the viewport");
@@ -4538,7 +4915,7 @@ static void draw_setting_widget(bAnimContext *ac,
case ACHANNEL_SETTING_MOD_OFF: /* modifiers disabled */
icon = ICON_MODIFIER_OFF;
- tooltip = TIP_("F-Curve modifiers are disabled");
+ tooltip = TIP_("Enable F-Curve modifiers");
break;
case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
@@ -4731,7 +5108,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
size_t channel_index)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
float ymid;
const short channel_height = round_fl_to_int(BLI_rctf_size_y(rect));
const bool is_being_renamed = achannel_is_being_renamed(ac, acf, channel_index);
@@ -4781,6 +5158,10 @@ void ANIM_channel_draw_widgets(const bContext *C,
}
/* visibility toggle */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
+ /* For F-curves, add the extra space for the color bands. */
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
+ offset += GRAPH_ICON_VISIBILITY_OFFSET;
+ }
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
offset += ICON_WIDTH;
}
@@ -4790,60 +5171,6 @@ void ANIM_channel_draw_widgets(const bContext *C,
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
offset += ICON_WIDTH;
}
- else if (ale->type == ANIMTYPE_GPLAYER) {
-#if 0
- /* XXX: Maybe need a better design */
- /* color swatch for layer color */
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
- PointerRNA ptr;
- float w = ICON_WIDTH / 2.0f;
-
- RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, &ptr);
-
- UI_block_align_begin(block);
- UI_block_emboss_set(block,
- RNA_boolean_get(&ptr, "is_stroke_visible") ? UI_EMBOSS : UI_EMBOSS_NONE);
- uiDefButR(block,
- UI_BTYPE_COLOR,
- 1,
- "",
- offset,
- yminc,
- w,
- ICON_WIDTH,
- &ptr,
- "color",
- -1,
- 0,
- 0,
- 0,
- 0,
- gpl->info);
-
- UI_block_emboss_set(block,
- RNA_boolean_get(&ptr, "is_fill_visible") ? UI_EMBOSS : UI_EMBOSS_NONE);
- uiDefButR(block,
- UI_BTYPE_COLOR,
- 1,
- "",
- offset + w,
- yminc,
- w,
- ICON_WIDTH,
- &ptr,
- "fill_color",
- -1,
- 0,
- 0,
- 0,
- 0,
- gpl->info);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- UI_block_align_end(block);
-
- offset += ICON_WIDTH;
-#endif
- }
}
/* step 4) draw text - check if renaming widget is in use... */
@@ -4857,7 +5184,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
*/
if (acf->name_prop(ale, &ptr, &prop)) {
const short margin_x = 3 * round_fl_to_int(UI_DPI_FAC);
- const short width = ac->ar->winx - offset - (margin_x * 2);
+ const short width = ac->region->winx - offset - (margin_x * 2);
uiBut *but;
UI_block_emboss_set(block, UI_EMBOSS);
@@ -4880,7 +5207,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
NULL);
/* copy what outliner does here, see outliner_buttons */
- if (UI_but_active_only(C, ac->ar, block, but) == false) {
+ if (UI_but_active_only(C, ac->region, block, but) == false) {
ac->ads->renameIndex = 0;
/* send notifiers */
@@ -4943,8 +5270,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
/* modifiers disable */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MOD_OFF)) {
- /* hack: extra spacing, to avoid touching the mute toggle */
- offset -= ICON_WIDTH * 1.2f;
+ offset -= ICON_WIDTH;
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_MOD_OFF);
}
@@ -5059,68 +5385,78 @@ void ANIM_channel_draw_widgets(const bContext *C,
else if (ale->type == ANIMTYPE_GPLAYER) {
bGPdata *gpd = (bGPdata *)ale->id;
if ((gpd != NULL) && ((gpd->flag & GP_DATA_ANNOTATIONS) == 0)) {
- /* Add some offset to make it more pleasing to the eye. */
- offset += SLIDER_WIDTH / 2.1f;
+ /* Reset slider offset, in order to add special gp icons. */
+ offset += SLIDER_WIDTH;
char *gp_rna_path = NULL;
bGPDlayer *gpl = (bGPDlayer *)ale->data;
- const short width = SLIDER_WIDTH / 5;
/* Create the RNA pointers. */
RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, &ptr);
RNA_id_pointer_create(ale->id, &id_ptr);
int icon;
- /* Layer opacity. */
- UI_block_emboss_set(block, UI_EMBOSS);
- prop = RNA_struct_find_property(&ptr, "opacity");
+ /* Layer onion skinning switch. */
+ offset -= ICON_WIDTH;
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ prop = RNA_struct_find_property(&ptr, "use_onion_skinning");
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
+ icon = (gpl->onion_flag & GP_LAYER_ONIONSKIN) ? ICON_ONIONSKIN_ON :
+ ICON_ONIONSKIN_OFF;
uiDefAutoButR(block,
&ptr,
prop,
array_index,
"",
- ICON_NONE,
+ icon,
offset,
ymid,
- width * 3,
+ ICON_WIDTH,
channel_height);
}
MEM_freeN(gp_rna_path);
/* Mask Layer. */
+ offset -= ICON_WIDTH;
UI_block_emboss_set(block, UI_EMBOSS_NONE);
- prop = RNA_struct_find_property(&ptr, "mask_layer");
+ prop = RNA_struct_find_property(&ptr, "use_mask_layer");
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
- icon = (gpl->flag & GP_LAYER_USE_MASK) ? ICON_MOD_MASK : ICON_LAYER_ACTIVE;
+ icon = ICON_LAYER_ACTIVE;
+ if (gpl->flag & GP_LAYER_USE_MASK) {
+ icon = ICON_MOD_MASK;
+ }
+ else {
+ icon = ICON_LAYER_ACTIVE;
+ }
uiDefAutoButR(block,
&ptr,
prop,
array_index,
"",
icon,
- offset + (width * 3),
+ offset,
ymid,
- width,
+ ICON_WIDTH,
channel_height);
}
MEM_freeN(gp_rna_path);
- /* Layer onion skinning switch. */
- prop = RNA_struct_find_property(&ptr, "use_onion_skinning");
+ /* Layer opacity. */
+ const short width = SLIDER_WIDTH * 0.6;
+ offset -= width;
+ UI_block_emboss_set(block, UI_EMBOSS);
+ prop = RNA_struct_find_property(&ptr, "opacity");
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
- icon = (gpl->onion_flag & GP_LAYER_ONIONSKIN) ? ICON_ONIONSKIN_ON :
- ICON_ONIONSKIN_OFF;
uiDefAutoButR(block,
&ptr,
prop,
array_index,
"",
- icon,
- offset + (width * 4),
+ ICON_NONE,
+ offset,
ymid,
width,
channel_height);
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index e90289de963..a7ca84eb6c6 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -28,34 +28,34 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_key_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_key_types.h"
#include "DNA_mask_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_anim_data.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
+#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mask.h"
-#include "BKE_global.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#include "UI_view2d.h"
#include "UI_interface.h"
+#include "UI_view2d.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -135,7 +135,11 @@ void ANIM_set_active_channel(bAnimContext *ac,
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP: {
+ case ANIMTYPE_DSMCLIP:
+ case ANIMTYPE_DSHAIR:
+ case ANIMTYPE_DSPOINTCLOUD:
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* need to verify that this data is valid for now */
if (ale->adt) {
ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE);
@@ -188,7 +192,11 @@ void ANIM_set_active_channel(bAnimContext *ac,
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP: {
+ case ANIMTYPE_DSMCLIP:
+ case ANIMTYPE_DSHAIR:
+ case ANIMTYPE_DSPOINTCLOUD:
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* need to verify that this data is valid for now */
if (ale && ale->adt) {
ale->adt->flag |= ADT_UI_ACTIVE;
@@ -323,7 +331,11 @@ void ANIM_deselect_anim_channels(
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP: {
+ case ANIMTYPE_DSMCLIP:
+ case ANIMTYPE_DSHAIR:
+ case ANIMTYPE_DSPOINTCLOUD:
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) {
sel = ACHANNEL_SETFLAG_CLEAR;
}
@@ -416,7 +428,11 @@ void ANIM_deselect_anim_channels(
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP: {
+ case ANIMTYPE_DSMCLIP:
+ case ANIMTYPE_DSHAIR:
+ case ANIMTYPE_DSPOINTCLOUD:
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* need to verify that this data is valid for now */
if (ale->adt) {
ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED);
@@ -683,15 +699,15 @@ bool ANIM_remove_empty_action_from_animdata(struct AnimData *adt)
/* poll callback for being in an Animation Editor channels list region */
static bool animedit_poll_channels_active(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* channels region test */
/* TODO: could enhance with actually testing if channels region? */
- if (ELEM(NULL, sa, CTX_wm_region(C))) {
+ if (ELEM(NULL, area, CTX_wm_region(C))) {
return 0;
}
/* animation editor test */
- if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0) {
+ if (ELEM(area->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0) {
return 0;
}
@@ -701,21 +717,21 @@ static bool animedit_poll_channels_active(bContext *C)
/* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */
static bool animedit_poll_channels_nla_tweakmode_off(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Scene *scene = CTX_data_scene(C);
/* channels region test */
/* TODO: could enhance with actually testing if channels region? */
- if (ELEM(NULL, sa, CTX_wm_region(C))) {
+ if (ELEM(NULL, area, CTX_wm_region(C))) {
return 0;
}
/* animation editor test */
- if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0) {
+ if (ELEM(area->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0) {
return 0;
}
/* NLA TweakMode test */
- if (sa->spacetype == SPACE_NLA) {
+ if (area->spacetype == SPACE_NLA) {
if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) {
return 0;
}
@@ -1506,19 +1522,19 @@ static void ANIM_OT_channels_move(wmOperatorType *ot)
static bool animchannels_grouping_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceLink *sl;
/* channels region test */
/* TODO: could enhance with actually testing if channels region? */
- if (ELEM(NULL, sa, CTX_wm_region(C))) {
+ if (ELEM(NULL, area, CTX_wm_region(C))) {
return 0;
}
/* animation editor test - must be suitable modes only */
sl = CTX_wm_space_data(C);
- switch (sa->spacetype) {
+ switch (area->spacetype) {
/* supported... */
case SPACE_ACTION: {
SpaceAction *saction = (SpaceAction *)sl;
@@ -1870,7 +1886,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- /* cleanup */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* send notifier that things have changed */
@@ -2256,7 +2272,8 @@ static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op))
}
/* get animdata blocks */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA |
+ ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -2341,16 +2358,16 @@ static void ANIM_OT_channels_clean_empty(wmOperatorType *ot)
static bool animchannels_enable_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* channels region test */
/* TODO: could enhance with actually testing if channels region? */
- if (ELEM(NULL, sa, CTX_wm_region(C))) {
+ if (ELEM(NULL, area, CTX_wm_region(C))) {
return 0;
}
/* animation editor test - Action/Dopesheet/etc. and Graph only */
- if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH) == 0) {
+ if (ELEM(area->spacetype, SPACE_ACTION, SPACE_GRAPH) == 0) {
return 0;
}
@@ -2419,14 +2436,14 @@ static void ANIM_OT_channels_fcurves_enable(wmOperatorType *ot)
/* XXX: make this generic? */
static bool animchannels_find_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- if (sa == NULL) {
+ if (area == NULL) {
return 0;
}
/* animation editor with dopesheet */
- return ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA);
+ return ELEM(area->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA);
}
/* find_invoke() - Get initial channels */
@@ -2553,7 +2570,7 @@ static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectm
int filter;
SpaceNla *snla = (SpaceNla *)ac->sl;
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
rctf rectf;
/* convert border-region to view coordinates */
@@ -2736,20 +2753,20 @@ static bool rename_anim_channels(bAnimContext *ac, int channel_index)
/* free temp data and tag for refresh */
ANIM_animdata_freelist(&anim_data);
- ED_region_tag_redraw(ac->ar);
+ ED_region_tag_redraw(ac->region);
return success;
}
static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
{
- ARegion *ar;
+ ARegion *region;
View2D *v2d;
int channel_index;
float x, y;
/* get useful pointers from animation context data */
- ar = ac->ar;
- v2d = &ar->v2d;
+ region = ac->region;
+ v2d = &region->v2d;
/* Figure out which channel user clicked in. */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
@@ -2949,7 +2966,11 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_DSMCLIP: {
+ case ANIMTYPE_DSMCLIP:
+ case ANIMTYPE_DSHAIR:
+ case ANIMTYPE_DSPOINTCLOUD:
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* sanity checking... */
if (ale->adt) {
/* select/deselect */
@@ -3135,7 +3156,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
if (gpl->flag & GP_LAYER_SELECT) {
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER);
/* update other layer status */
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
BKE_gpencil_layer_autolock_set(gpd, false);
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
}
@@ -3194,7 +3215,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
- ARegion *ar;
+ ARegion *region;
View2D *v2d;
int channel_index;
int notifierFlags = 0;
@@ -3207,8 +3228,8 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
}
/* get useful pointers from animation context data */
- ar = ac.ar;
- v2d = &ar->v2d;
+ region = ac.region;
+ v2d = &region->v2d;
/* select mode is either replace (deselect all, then add) or add/extend */
if (RNA_boolean_get(op->ptr, "extend")) {
@@ -3327,7 +3348,7 @@ static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool e
}
/* free temp data and tag for refresh */
- ED_region_tag_redraw(ac->ar);
+ ED_region_tag_redraw(ac->region);
return success;
}
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index 5c9f0707aa9..4fb68b614ff 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -28,16 +28,17 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_gpencil_types.h"
-#include "DNA_object_types.h"
+#include "DNA_mask_types.h"
#include "DNA_node_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_anim_data.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
@@ -360,16 +361,6 @@ void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
{
bAnimListElem *ale;
- if (ELEM(ac->datatype, ANIMCONT_MASK)) {
-#ifdef DEBUG
- /* quiet assert */
- for (ale = anim_data->first; ale; ale = ale->next) {
- ale->update = 0;
- }
-#endif
- return;
- }
-
for (ale = anim_data->first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_GPLAYER) {
bGPDlayer *gpl = ale->data;
@@ -377,7 +368,7 @@ void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
if (ale->update & ANIM_UPDATE_ORDER) {
ale->update &= ~ANIM_UPDATE_ORDER;
if (gpl) {
- // gpencil_sort_frames(gpl);
+ BKE_gpencil_layer_frames_sort(gpl, NULL);
}
}
@@ -390,6 +381,27 @@ void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
ale->update &= ~ANIM_UPDATE_HANDLES;
}
}
+ else if (ale->datatype == ALE_MASKLAY) {
+ MaskLayer *masklay = ale->data;
+
+ if (ale->update & ANIM_UPDATE_ORDER) {
+ ale->update &= ~ANIM_UPDATE_ORDER;
+ if (masklay) {
+ /* While correct & we could enable it: 'posttrans_mask_clean' currently
+ * both sorts and removes doubles, so this is not necessary here. */
+ // BKE_mask_layer_shape_sort(masklay);
+ }
+ }
+
+ if (ale->update & ANIM_UPDATE_DEPS) {
+ ale->update &= ~ANIM_UPDATE_DEPS;
+ ANIM_list_elem_update(ac->bmain, ac->scene, ale);
+ }
+ /* Disable handles to avoid assert. */
+ if (ale->update & ANIM_UPDATE_HANDLES) {
+ ale->update &= ~ANIM_UPDATE_HANDLES;
+ }
+ }
else if (ale->datatype == ALE_FCURVE) {
FCurve *fcu = ale->key_data;
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 40b2706cc75..4203c2677b7 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -24,30 +24,30 @@
#include "BLI_sys_types.h"
#include "DNA_anim_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_mask_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_object_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_mask_types.h"
+#include "BLI_dlrbTree.h"
#include "BLI_math.h"
+#include "BLI_rect.h"
#include "BLI_timecode.h"
#include "BLI_utildefines.h"
-#include "BLI_rect.h"
-#include "BLI_dlrbTree.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
-#include "BKE_nla.h"
#include "BKE_mask.h"
+#include "BKE_nla.h"
#include "ED_anim_api.h"
-#include "ED_keyframes_edit.h"
#include "ED_keyframes_draw.h"
+#include "ED_keyframes_edit.h"
#include "RNA_access.h"
@@ -71,7 +71,7 @@ void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
const bool show_time = (flag & DRAWCFRA_UNIT_SECONDS) != 0;
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- unsigned char col[4];
+ uchar col[4];
float color[4];
float xscale, x, y;
char numstr[32] = " t "; /* t is the character to start replacing from */
@@ -441,12 +441,45 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo
min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
}
else {
- float step_size = (bezt->vec[1][0] - prev_bezt->vec[1][0]) / resol;
- for (int j = 0; j <= resol; j++) {
- float eval_time = prev_bezt->vec[1][0] + step_size * j;
- float eval_value = evaluate_fcurve_only_curve(fcu, eval_time);
- max_coord = max_ff(max_coord, eval_value);
- min_coord = min_ff(min_coord, eval_value);
+ if (!ELEM(prev_bezt->ipo, BEZT_IPO_BACK, BEZT_IPO_ELASTIC)) {
+ /* Calculate min/max using bezier forward differencing. */
+ float data[120];
+ float v1[2], v2[2], v3[2], v4[2];
+
+ v1[0] = prev_bezt->vec[1][0];
+ v1[1] = prev_bezt->vec[1][1];
+ v2[0] = prev_bezt->vec[2][0];
+ v2[1] = prev_bezt->vec[2][1];
+
+ v3[0] = bezt->vec[0][0];
+ v3[1] = bezt->vec[0][1];
+ v4[0] = bezt->vec[1][0];
+ v4[1] = bezt->vec[1][1];
+
+ correct_bezpart(v1, v2, v3, v4);
+
+ BKE_curve_forward_diff_bezier(
+ v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3);
+ BKE_curve_forward_diff_bezier(
+ v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3);
+
+ for (int j = 0; j <= resol; ++j) {
+ const float *fp = &data[j * 3];
+ max_coord = max_ff(max_coord, fp[1]);
+ min_coord = min_ff(min_coord, fp[1]);
+ }
+ }
+ else {
+ /* Calculate min/max using full fcurve evaluation.
+ * [slower than bezier forward differencing but evaluates Back/Elastic interpolation
+ * as well].*/
+ float step_size = (bezt->vec[1][0] - prev_bezt->vec[1][0]) / resol;
+ for (int j = 0; j <= resol; j++) {
+ float eval_time = prev_bezt->vec[1][0] + step_size * j;
+ float eval_value = evaluate_fcurve_only_curve(fcu, eval_time);
+ max_coord = max_ff(max_coord, eval_value);
+ min_coord = min_ff(min_coord, eval_value);
+ }
}
}
}
@@ -515,7 +548,7 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag
return 1.0f;
}
-static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra)
+static bool find_prev_next_keyframes(struct bContext *C, int *r_nextfra, int *r_prevfra)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
@@ -594,17 +627,17 @@ static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prev
/* any success? */
if (doneprev || donenext) {
if (doneprev) {
- *prevfra = cfraprev;
+ *r_prevfra = cfraprev;
}
else {
- *prevfra = CFRA - (cfranext - CFRA);
+ *r_prevfra = CFRA - (cfranext - CFRA);
}
if (donenext) {
- *nextfra = cfranext;
+ *r_nextfra = cfranext;
}
else {
- *nextfra = CFRA + (CFRA - cfraprev);
+ *r_nextfra = CFRA + (CFRA - cfraprev);
}
return true;
@@ -615,9 +648,9 @@ static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prev
void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
- float w = BLI_rctf_size_x(&ar->v2d.cur);
+ float w = BLI_rctf_size_x(&region->v2d.cur);
rctf newrct;
int nextfra, prevfra;
@@ -626,8 +659,8 @@ void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
const float fps = FPS;
newrct.xmax = scene->r.cfra + U.view_frame_seconds * fps + 1;
newrct.xmin = scene->r.cfra - U.view_frame_seconds * fps - 1;
- newrct.ymax = ar->v2d.cur.ymax;
- newrct.ymin = ar->v2d.cur.ymin;
+ newrct.ymax = region->v2d.cur.ymax;
+ newrct.ymin = region->v2d.cur.ymin;
break;
}
@@ -636,8 +669,8 @@ void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
if (find_prev_next_keyframes(C, &nextfra, &prevfra)) {
newrct.xmax = nextfra;
newrct.xmin = prevfra;
- newrct.ymax = ar->v2d.cur.ymax;
- newrct.ymin = ar->v2d.cur.ymin;
+ newrct.ymax = region->v2d.cur.ymax;
+ newrct.ymin = region->v2d.cur.ymin;
break;
}
/* else drop through, keep range instead */
@@ -647,11 +680,11 @@ void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
default:
newrct.xmax = scene->r.cfra + (w / 2);
newrct.xmin = scene->r.cfra - (w / 2);
- newrct.ymax = ar->v2d.cur.ymax;
- newrct.ymin = ar->v2d.cur.ymin;
+ newrct.ymax = region->v2d.cur.ymax;
+ newrct.ymin = region->v2d.cur.ymin;
break;
}
- UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx);
+ UI_view2d_smooth_view(C, region, &newrct, smooth_viewtx);
}
/* *************************************************** */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 4c81df8b71d..2b9dfe105bc 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -44,12 +44,16 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
-#include "DNA_camera_types.h"
+#include "DNA_brush_types.h"
#include "DNA_cachefile_types.h"
-#include "DNA_light_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_hair_types.h"
+#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_layer_types.h"
+#include "DNA_light_types.h"
#include "DNA_linestyle_types.h"
-#include "DNA_key_types.h"
#include "DNA_mask_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
@@ -57,40 +61,41 @@
#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
#include "DNA_object_force_types.h"
+#include "DNA_object_types.h"
#include "DNA_particle_types.h"
-#include "DNA_space_types.h"
-#include "DNA_sequence_types.h"
+#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
+#include "DNA_space_types.h"
#include "DNA_speaker_types.h"
-#include "DNA_world_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_object_types.h"
#include "DNA_userdef_types.h"
-#include "DNA_layer_types.h"
+#include "DNA_volume_types.h"
+#include "DNA_world_types.h"
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_alloca.h"
+#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BKE_action.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
+#include "BKE_fcurve_driver.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_mask.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
-#include "BKE_mask.h"
#include "BKE_sequencer.h"
#include "ED_anim_api.h"
@@ -396,8 +401,8 @@ bool ANIM_animdata_context_getdata(bAnimContext *ac)
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
{
Main *bmain = CTX_data_main(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
SpaceLink *sl = CTX_wm_space_data(C);
Scene *scene = CTX_data_scene(C);
@@ -415,11 +420,11 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
}
ac->view_layer = CTX_data_view_layer(C);
ac->obact = (ac->view_layer->basact) ? ac->view_layer->basact->object : NULL;
- ac->sa = sa;
- ac->ar = ar;
+ ac->area = area;
+ ac->region = region;
ac->sl = sl;
- ac->spacetype = (sa) ? sa->spacetype : 0;
- ac->regiontype = (ar) ? ar->regiontype : 0;
+ ac->spacetype = (area) ? area->spacetype : 0;
+ ac->regiontype = (region) ? region->regiontype : 0;
/* initialise default y-scale factor */
animedit_get_yscale_factor(ac);
@@ -787,6 +792,54 @@ static bAnimListElem *make_new_animlistelem(void *data,
ale->adt = BKE_animdata_from_id(data);
break;
}
+ case ANIMTYPE_DSHAIR: {
+ Hair *hair = (Hair *)data;
+ AnimData *adt = hair->adt;
+
+ ale->flag = FILTER_HAIR_OBJD(hair);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSPOINTCLOUD: {
+ PointCloud *pointcloud = (PointCloud *)data;
+ AnimData *adt = pointcloud->adt;
+
+ ale->flag = FILTER_POINTS_OBJD(pointcloud);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSVOLUME: {
+ Volume *volume = (Volume *)data;
+ AnimData *adt = volume->adt;
+
+ ale->flag = FILTER_VOLUME_OBJD(volume);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
+ case ANIMTYPE_DSSIMULATION: {
+ Simulation *simulation = (Simulation *)data;
+ AnimData *adt = simulation->adt;
+
+ ale->flag = FILTER_SIMULATION_OBJD(simulation);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
case ANIMTYPE_DSSKEY: {
Key *key = (Key *)data;
AnimData *adt = key->adt;
@@ -1715,22 +1768,33 @@ static size_t animdata_filter_gpencil_layers_data(ListBase *anim_data,
/* loop over layers as the conditions are acceptable (top-Down order) */
for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
/* only if selected */
- if (ANIMCHANNEL_SELOK(SEL_GPL(gpl))) {
- /* only if editable */
- if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
- /* active... */
- if (!(filter_mode & ANIMFILTER_ACTIVE) || (gpl->flag & GP_LAYER_ACTIVE)) {
- /* skip layer if the name doesn't match the filter string */
- if ((ads) && (ads->searchstr[0] != '\0')) {
- if (name_matches_dopesheet_filter(ads, gpl->info) == false) {
- continue;
- }
- }
- /* add to list */
- ANIMCHANNEL_NEW_CHANNEL(gpl, ANIMTYPE_GPLAYER, gpd, NULL);
- }
- }
+ if (!ANIMCHANNEL_SELOK(SEL_GPL(gpl))) {
+ continue;
}
+
+ /* only if editable */
+ if ((filter_mode & ANIMFILTER_FOREDIT) && !EDITABLE_GPL(gpl)) {
+ continue;
+ }
+
+ /* active... */
+ if ((filter_mode & ANIMFILTER_ACTIVE) && (gpl->flag & GP_LAYER_ACTIVE) == 0) {
+ continue;
+ }
+
+ /* skip layer if the name doesn't match the filter string */
+ if (ads != NULL && ads->searchstr[0] != '\0' &&
+ name_matches_dopesheet_filter(ads, gpl->info) == false) {
+ continue;
+ }
+
+ /* Skip empty layers. */
+ if (BLI_listbase_is_empty(&gpl->frames)) {
+ continue;
+ }
+
+ /* add to list */
+ ANIMCHANNEL_NEW_CHANNEL(gpl, ANIMTYPE_GPLAYER, gpd, NULL);
}
return items;
@@ -1790,81 +1854,65 @@ static size_t animdata_filter_gpencil(bAnimContext *ac,
bDopeSheet *ads = ac->ads;
size_t items = 0;
- if (ads->filterflag & ADS_FILTER_GP_3DONLY) {
- Scene *scene = (Scene *)ads->source;
- ViewLayer *view_layer = (ViewLayer *)ac->view_layer;
- Base *base;
-
- /* Active scene's GPencil block first - No parent item needed... */
- if (scene->gpd) {
- items += animdata_filter_gpencil_data(anim_data, ads, scene->gpd, filter_mode);
- }
-
- /* Objects in the scene */
- for (base = view_layer->object_bases.first; base; base = base->next) {
- /* Only consider this object if it has got some GP data (saving on all the other tests) */
- if (base->object && (base->object->type == OB_GPENCIL)) {
- Object *ob = base->object;
-
- /* firstly, check if object can be included, by the following factors:
- * - if only visible, must check for layer and also viewport visibility
- * --> while tools may demand only visible, user setting takes priority
- * as user option controls whether sets of channels get included while
- * tool-flag takes into account collapsed/open channels too
- * - if only selected, must check if object is selected
- * - there must be animation data to edit (this is done recursively as we
- * try to add the channels)
- */
- if ((filter_mode & ANIMFILTER_DATA_VISIBLE) &&
- !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
- /* Layer visibility - we check both object and base,
- * since these may not be in sync yet. */
- if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
- continue;
- }
-
- /* outliner restrict-flag */
- if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
- continue;
- }
+ ViewLayer *view_layer = (ViewLayer *)ac->view_layer;
+ Base *base;
+
+ /* Include all annotation datablocks. */
+ if (((ads->filterflag & ADS_FILTER_ONLYSEL) == 0) ||
+ (ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
+ LISTBASE_FOREACH (bGPdata *, gpd, &ac->bmain->gpencils) {
+ if (gpd->flag & GP_DATA_ANNOTATIONS) {
+ items += animdata_filter_gpencil_data(anim_data, ads, gpd, filter_mode);
+ }
+ }
+ }
+ /* Objects in the scene */
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ /* Only consider this object if it has got some GP data (saving on all the other tests) */
+ if (base->object && (base->object->type == OB_GPENCIL)) {
+ Object *ob = base->object;
+
+ /* firstly, check if object can be included, by the following factors:
+ * - if only visible, must check for layer and also viewport visibility
+ * --> while tools may demand only visible, user setting takes priority
+ * as user option controls whether sets of channels get included while
+ * tool-flag takes into account collapsed/open channels too
+ * - if only selected, must check if object is selected
+ * - there must be animation data to edit (this is done recursively as we
+ * try to add the channels)
+ */
+ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
+ /* Layer visibility - we check both object and base,
+ * since these may not be in sync yet. */
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
+ continue;
}
- /* check selection and object type filters only for Object mode */
- if (ob->mode == OB_MODE_OBJECT) {
- if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED))) {
- /* only selected should be shown */
- continue;
- }
- }
- /* check if object belongs to the filtering group if option to filter
- * objects by the grouped status is on
- * - used to ease the process of doing multiple-character choreographies
- */
- if (ads->filter_grp != NULL) {
- if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0) {
- continue;
- }
+ /* outliner restrict-flag */
+ if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
+ continue;
}
-
- /* finally, include this object's grease pencil data-block. */
- /* XXX: Should we store these under expanders per item? */
- items += animdata_filter_gpencil_data(anim_data, ads, ob->data, filter_mode);
}
- }
- }
- else {
- bGPdata *gpd;
- /* Grab all Grease Pencil data-blocks directly from main,
- * but only those that seem to be useful somewhere */
- for (gpd = ac->bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- /* only show if gpd is used by something... */
- if (ID_REAL_USERS(gpd) < 1) {
+ /* check selection and object type filters */
+ if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED))) {
+ /* only selected should be shown */
continue;
}
- /* add GP frames from this data-block. */
- items += animdata_filter_gpencil_data(anim_data, ads, gpd, filter_mode);
+ /* check if object belongs to the filtering group if option to filter
+ * objects by the grouped status is on
+ * - used to ease the process of doing multiple-character choreographies
+ */
+ if (ads->filter_grp != NULL) {
+ if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0) {
+ continue;
+ }
+ }
+
+ /* finally, include this object's grease pencil data-block. */
+ /* XXX: Should we store these under expanders per item? */
+ items += animdata_filter_gpencil_data(anim_data, ads, ob->data, filter_mode);
}
}
@@ -2290,46 +2338,17 @@ static size_t animdata_filter_ds_material(
static size_t animdata_filter_ds_materials(
bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
- bool has_nested = false;
size_t items = 0;
int a = 0;
/* First pass: take the materials referenced via the Material slots of the object. */
for (a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
+ Material *ma = BKE_object_material_get(ob, a);
/* if material is valid, try to add relevant contents from here */
if (ma) {
/* add channels */
items += animdata_filter_ds_material(ac, anim_data, ads, ma, filter_mode);
-
- /* for optimising second pass - check if there's a nested material here to come back for */
- if (has_nested == false) {
- has_nested = (give_node_material(ma) != NULL);
- }
- }
- }
-
- /* Second pass: go through a second time looking for "nested" materials
- * (material.material references).
- *
- * NOTE: here we ignore the expanded status of the parent, as it could be too confusing as to
- * why these are disappearing/not available,
- * since the relationships between these is not that clear.
- */
- if (has_nested) {
- for (a = 1; a <= ob->totcol; a++) {
- Material *base = give_current_material(ob, a);
- Material *ma = give_node_material(base);
-
- /* add channels from the nested material if it exists
- * - skip if the same material is referenced in its node tree
- * (which is common for BI materials) as that results in
- * confusing duplicates
- */
- if ((ma) && (ma != base)) {
- items += animdata_filter_ds_material(ac, anim_data, ads, ma, filter_mode);
- }
}
}
@@ -2409,7 +2428,7 @@ static size_t animdata_filter_ds_modifiers(
afm.filter_mode = filter_mode;
/* 2) walk over dependencies */
- modifiers_foreachIDLink(ob, animfilter_modifier_idpoin_cb, &afm);
+ BKE_modifiers_foreach_ID_link(ob, animfilter_modifier_idpoin_cb, &afm);
/* 3) extract data from the context, merging it back into the standard list */
if (afm.items) {
@@ -2580,6 +2599,39 @@ static size_t animdata_filter_ds_obdata(
expanded = FILTER_SPK_OBJD(spk);
break;
}
+ case OB_HAIR: /* ---------- Hair ----------- */
+ {
+ Hair *hair = (Hair *)ob->data;
+
+ if (ads->filterflag2 & ADS_FILTER_NOHAIR)
+ return 0;
+
+ type = ANIMTYPE_DSHAIR;
+ expanded = FILTER_HAIR_OBJD(hair);
+ break;
+ }
+ case OB_POINTCLOUD: /* ---------- PointCloud ----------- */
+ {
+ PointCloud *pointcloud = (PointCloud *)ob->data;
+
+ if (ads->filterflag2 & ADS_FILTER_NOPOINTCLOUD)
+ return 0;
+
+ type = ANIMTYPE_DSPOINTCLOUD;
+ expanded = FILTER_POINTS_OBJD(pointcloud);
+ break;
+ }
+ case OB_VOLUME: /* ---------- Volume ----------- */
+ {
+ Volume *volume = (Volume *)ob->data;
+
+ if (ads->filterflag2 & ADS_FILTER_NOVOLUME)
+ return 0;
+
+ type = ANIMTYPE_DSVOLUME;
+ expanded = FILTER_VOLUME_OBJD(volume);
+ break;
+ }
}
/* add object data animation channels */
@@ -3025,7 +3077,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m
*/
if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* layer visibility - we check both object and base, since these may not be in sync yet */
- if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0 || (base->flag & BASE_VISIBLE_VIEWLAYER) == 0) {
return false;
}
@@ -3103,7 +3155,7 @@ static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads,
size_t num_bases = 0;
Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases");
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (animdata_filter_base_is_ok(ads, base, filter_mode)) {
sorted_bases[num_bases++] = base;
}
@@ -3197,7 +3249,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac,
/* Filter and add contents of each base (i.e. object) without them sorting first
* NOTE: This saves performance in cases where order doesn't matter
*/
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (animdata_filter_base_is_ok(ads, base, filter_mode)) {
/* since we're still here, this object should be usable */
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index 5b729c856c0..3613ca9eeda 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -177,8 +177,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
icon = RNA_struct_ui_icon(ptr.type);
/* valid path - remove the invalid tag since we now know how to use it saving
- * users manual effort to reenable using "Revive Disabled FCurves" [#29629]
- */
+ * users manual effort to re-enable using "Revive Disabled FCurves" T29629. */
fcu->flag &= ~FCURVE_DISABLED;
}
else {
@@ -204,7 +203,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
#define HSV_BANDWIDTH 0.3f
/* used to determine the color of F-Curves with FCURVE_COLOR_AUTO_RAINBOW set */
-// void fcurve_rainbow(unsigned int cur, unsigned int tot, float *out)
+// void fcurve_rainbow(uint cur, uint tot, float *out)
void getcolor_fcurve_rainbow(int cur, int tot, float out[3])
{
float hsv[3], fac;
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index e0d72ab5198..46566feea91 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -25,8 +25,8 @@
#include "MEM_guardedalloc.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
@@ -56,30 +56,30 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
-#include "UI_view2d.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
-#include "ED_screen.h"
-#include "ED_select_utils.h"
-#include "ED_util.h"
#include "ED_numinput.h"
#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_select_utils.h"
#include "ED_transform.h"
#include "ED_types.h"
+#include "ED_util.h"
#include "DEG_depsgraph.h"
/* ************* Marker API **************** */
/* helper function for getting the list of markers to work on */
-static ListBase *context_get_markers(Scene *scene, ScrArea *sa)
+static ListBase *context_get_markers(Scene *scene, ScrArea *area)
{
/* local marker sets... */
- if (sa) {
- if (sa->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+ if (area) {
+ if (area->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)area->spacedata.first;
/* local markers can only be shown when there's only a single active action to grab them from
* - flag only takes effect when there's an action, otherwise it can get too confusing?
@@ -108,7 +108,7 @@ ListBase *ED_context_get_markers(const bContext *C)
ListBase *ED_animcontext_get_markers(const bAnimContext *ac)
{
if (ac) {
- return context_get_markers(ac->scene, ac->sa);
+ return context_get_markers(ac->scene, ac->area);
}
else {
return NULL;
@@ -197,7 +197,7 @@ int ED_markers_find_nearest_marker_time(ListBase *markers, float x)
return (nearest) ? (nearest->frame) : round_fl_to_int(x);
}
-void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *last)
+void ED_markers_get_minmax(ListBase *markers, short sel, float *r_first, float *r_last)
{
TimeMarker *marker;
float min, max;
@@ -205,8 +205,8 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la
/* sanity check */
// printf("markers = %p - %p, %p\n", markers, markers->first, markers->last);
if (ELEM(NULL, markers, markers->first, markers->last)) {
- *first = 0.0f;
- *last = 0.0f;
+ *r_first = 0.0f;
+ *r_last = 0.0f;
return;
}
@@ -224,8 +224,8 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la
}
/* set the min/max values */
- *first = min;
- *last = max;
+ *r_first = min;
+ *r_last = max;
}
/**
@@ -234,32 +234,35 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la
*/
static bool ED_operator_markers_region_active(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
+ if (area == NULL) {
+ return false;
+ }
- switch (sa->spacetype) {
+ switch (area->spacetype) {
case SPACE_ACTION: {
- SpaceAction *saction = sa->spacedata.first;
+ SpaceAction *saction = area->spacedata.first;
if (saction->flag & SACTION_SHOW_MARKERS) {
return true;
}
break;
}
case SPACE_GRAPH: {
- SpaceGraph *sipo = sa->spacedata.first;
+ SpaceGraph *sipo = area->spacedata.first;
if (sipo->mode != SIPO_MODE_DRIVERS && sipo->flag & SIPO_SHOW_MARKERS) {
return true;
}
break;
}
case SPACE_NLA: {
- SpaceNla *snla = sa->spacedata.first;
+ SpaceNla *snla = area->spacedata.first;
if (snla->flag & SNLA_SHOW_MARKERS) {
return true;
}
break;
}
case SPACE_SEQ: {
- SpaceSeq *seq = sa->spacedata.first;
+ SpaceSeq *seq = area->spacedata.first;
if (seq->flag & SEQ_SHOW_MARKERS) {
return true;
}
@@ -355,7 +358,7 @@ void ED_markers_deselect_all(ListBase *markers, int action)
action = ED_markers_get_first_selected(markers) ? SEL_DESELECT : SEL_SELECT;
}
- for (TimeMarker *marker = markers->first; marker; marker = marker->next) {
+ LISTBASE_FOREACH (TimeMarker *, marker, markers) {
if (action == SEL_SELECT) {
marker->flag |= SELECT;
}
@@ -416,41 +419,44 @@ void debug_markers_print_list(ListBase *markers)
/* ************* Marker Drawing ************ */
-static void marker_color_get(TimeMarker *marker, unsigned char *color)
+static void marker_color_get(const TimeMarker *marker, uchar *r_text_color, uchar *r_line_color)
{
if (marker->flag & SELECT) {
- UI_GetThemeColor4ubv(TH_TEXT_HI, color);
+ UI_GetThemeColor4ubv(TH_TEXT_HI, r_text_color);
+ UI_GetThemeColor4ubv(TH_TIME_MARKER_LINE_SELECTED, r_line_color);
}
else {
- UI_GetThemeColor4ubv(TH_TEXT, color);
+ UI_GetThemeColor4ubv(TH_TEXT, r_text_color);
+ UI_GetThemeColor4ubv(TH_TIME_MARKER_LINE, r_line_color);
}
}
-static void draw_marker_name(const uiFontStyle *fstyle,
+static void draw_marker_name(const uchar *text_color,
+ const uiFontStyle *fstyle,
TimeMarker *marker,
float marker_x,
float text_y)
{
- unsigned char text_color[4];
- marker_color_get(marker, text_color);
-
const char *name = marker->name;
+ uchar final_text_color[4];
+
+ copy_v4_v4_uchar(final_text_color, text_color);
#ifdef DURIAN_CAMERA_SWITCH
if (marker->camera) {
Object *camera = marker->camera;
name = camera->id.name + 2;
if (camera->restrictflag & OB_RESTRICT_RENDER) {
- text_color[3] = 100;
+ final_text_color[3] = 100;
}
}
#endif
int name_x = marker_x + UI_DPI_ICON_SIZE * 0.6;
- UI_fontstyle_draw_simple(fstyle, name_x, text_y, name, text_color);
+ UI_fontstyle_draw_simple(fstyle, name_x, text_y, name, final_text_color);
}
-static void draw_marker_line(const float color[4], int xpos, int ymin, int ymax)
+static void draw_marker_line(const uchar *color, int xpos, int ymin, int ymax)
{
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -461,7 +467,7 @@ static void draw_marker_line(const float color[4], int xpos, int ymin, int ymax)
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniformColor4fv(color);
+ immUniformColor4ubv(color);
immUniform1i("colors_len", 0); /* "simple" mode */
immUniform1f("dash_width", 6.0f);
immUniform1f("dash_factor", 0.5f);
@@ -493,19 +499,15 @@ static int marker_get_icon_id(TimeMarker *marker, int flag)
static void draw_marker(
const uiFontStyle *fstyle, TimeMarker *marker, int cfra, int xpos, int flag, int region_height)
{
+ uchar line_color[4], text_color[4];
+
+ marker_color_get(marker, text_color, line_color);
+
GPU_blend(true);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- float color[4];
- if (marker->flag & SELECT) {
- copy_v4_fl4(color, 1.0f, 1.0f, 1.0f, 0.38f);
- }
- else {
- copy_v4_fl4(color, 0.0f, 0.0f, 0.0f, 0.38f);
- }
-
- draw_marker_line(color, xpos, UI_DPI_FAC * 20, region_height);
+ draw_marker_line(line_color, xpos, UI_DPI_FAC * 20, region_height);
int icon_id = marker_get_icon_id(marker, flag);
UI_icon_draw(xpos - 0.55f * UI_DPI_ICON_SIZE, UI_DPI_FAC * 18, icon_id);
@@ -518,7 +520,7 @@ static void draw_marker(
if ((marker->flag & SELECT) || (cfra - 4 <= marker->frame && marker->frame <= cfra)) {
name_y += UI_DPI_FAC * 10;
}
- draw_marker_name(fstyle, marker, xpos, name_y);
+ draw_marker_name(text_color, fstyle, marker, xpos, name_y);
}
static void draw_markers_background(rctf *rect)
@@ -526,7 +528,7 @@ static void draw_markers_background(rctf *rect)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- unsigned char shade[4];
+ uchar shade[4];
UI_GetThemeColor4ubv(TH_TIME_SCRUB_BACKGROUND, shade);
immUniformColor4ubv(shade);
@@ -576,7 +578,7 @@ void ED_markers_draw(const bContext *C, int flag)
return;
}
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View2D *v2d = UI_view2d_fromcontext(C);
int cfra = CTX_data_scene(C)->r.cfra;
@@ -597,17 +599,17 @@ void ED_markers_draw(const bContext *C, int flag)
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
/* Separate loops in order to draw selected markers on top */
- for (TimeMarker *marker = markers->first; marker; marker = marker->next) {
+ LISTBASE_FOREACH (TimeMarker *, marker, markers) {
if ((marker->flag & SELECT) == 0) {
if (marker_is_in_frame_range(marker, clip_frame_range)) {
- draw_marker(fstyle, marker, cfra, marker->frame * xscale, flag, ar->winy);
+ draw_marker(fstyle, marker, cfra, marker->frame * xscale, flag, region->winy);
}
}
}
- for (TimeMarker *marker = markers->first; marker; marker = marker->next) {
+ LISTBASE_FOREACH (TimeMarker *, marker, markers) {
if (marker->flag & SELECT) {
if (marker_is_in_frame_range(marker, clip_frame_range)) {
- draw_marker(fstyle, marker, cfra, marker->frame * xscale, flag, ar->winy);
+ draw_marker(fstyle, marker, cfra, marker->frame * xscale, flag, region->winy);
}
}
}
@@ -871,10 +873,10 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *eve
{
bool tweak = RNA_boolean_get(op->ptr, "tweak");
if (tweak) {
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
ListBase *markers = ED_context_get_markers(C);
- if (!region_position_is_over_marker(v2d, markers, event->x - ar->winrct.xmin)) {
+ if (!region_position_is_over_marker(v2d, markers, event->x - region->winrct.xmin)) {
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
}
@@ -904,7 +906,7 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *eve
static void ed_marker_move_apply(bContext *C, wmOperator *op)
{
#ifdef DURIAN_CAMERA_SWITCH
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
Object *camera = scene->camera;
#endif
@@ -928,7 +930,7 @@ static void ed_marker_move_apply(bContext *C, wmOperator *op)
BKE_scene_camera_switch_update(scene);
if (camera != scene->camera) {
- BKE_screen_view3d_scene_sync(sc, scene);
+ BKE_screen_view3d_scene_sync(screen, scene);
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
}
#endif
@@ -966,7 +968,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even
else {
bool handled = false;
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
ed_marker_move_cancel(C, op);
return OPERATOR_CANCELLED;
case RIGHTMOUSE:
@@ -978,8 +980,8 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even
/* else continue; <--- see if release event should be caught for tweak-end */
ATTR_FALLTHROUGH;
- case RETKEY:
- case PADENTER:
+ case EVT_RETKEY:
+ case EVT_PADENTER:
case LEFTMOUSE:
case MIDDLEMOUSE:
if (WM_event_is_modal_tweak_exit(event, mm->event_type)) {
@@ -1154,7 +1156,7 @@ static void MARKER_OT_duplicate(wmOperatorType *ot)
static void deselect_markers(ListBase *markers)
{
- for (TimeMarker *marker = markers->first; marker; marker = marker->next) {
+ LISTBASE_FOREACH (TimeMarker *, marker, markers) {
marker->flag &= ~SELECT;
}
}
@@ -1338,11 +1340,11 @@ static void MARKER_OT_select(wmOperatorType *ot)
static int ed_marker_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
ListBase *markers = ED_context_get_markers(C);
- bool over_marker = region_position_is_over_marker(v2d, markers, event->x - ar->winrct.xmin);
+ bool over_marker = region_position_is_over_marker(v2d, markers, event->x - region->winrct.xmin);
bool tweak = RNA_boolean_get(op->ptr, "tweak");
if (tweak && over_marker) {
@@ -1371,7 +1373,7 @@ static int ed_marker_box_select_exec(bContext *C, wmOperator *op)
ED_markers_deselect_all(markers, SEL_DESELECT);
}
- for (TimeMarker *marker = markers->first; marker; marker = marker->next) {
+ LISTBASE_FOREACH (TimeMarker *, marker, markers) {
if (BLI_rctf_isect_x(&rect, marker->frame)) {
SET_FLAG_FROM_TEST(marker->flag, select, SELECT);
}
@@ -1557,8 +1559,9 @@ static void MARKER_OT_rename(wmOperatorType *ot)
static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
ListBase *markers = ED_context_get_markers(C);
- Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scenes, RNA_enum_get(op->ptr, "scene"));
+ Scene *scene_to = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
TimeMarker *marker, *marker_new;
if (scene_to == NULL) {
@@ -1618,7 +1621,7 @@ static void MARKER_OT_make_links_scene(wmOperatorType *ot)
static int ed_marker_camera_bind_exec(bContext *C, wmOperator *op)
{
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
ListBase *markers = ED_context_get_markers(C);
@@ -1643,7 +1646,7 @@ static int ed_marker_camera_bind_exec(bContext *C, wmOperator *op)
BLI_addtail(markers, marker);
/* deselect all others, so that the user can then move it without problems */
- for (TimeMarker *m = markers->first; m; m = m->next) {
+ LISTBASE_FOREACH (TimeMarker *, m, markers) {
if (m != marker) {
m->flag &= ~SELECT;
}
@@ -1655,7 +1658,7 @@ static int ed_marker_camera_bind_exec(bContext *C, wmOperator *op)
/* camera may have changes */
BKE_scene_camera_switch_update(scene);
- BKE_screen_view3d_scene_sync(sc, scene);
+ BKE_screen_view3d_scene_sync(screen, scene);
WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index e6ab3609507..4c10c66dfa6 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -22,16 +22,16 @@
#include <stdlib.h>
+#include "BLI_dlrbTree.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_dlrbTree.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_scene_types.h"
-#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_anim_data.h"
#include "BKE_main.h"
#include "BKE_scene.h"
@@ -228,7 +228,7 @@ static void motionpath_get_global_framerange(ListBase *targets, int *r_sfra, int
{
*r_sfra = INT_MAX;
*r_efra = INT_MIN;
- for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
+ LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
*r_sfra = min_ii(*r_sfra, mpt->mpath->start_frame);
*r_efra = max_ii(*r_efra, mpt->mpath->end_frame);
}
@@ -348,7 +348,7 @@ static void motionpath_calculate_update_range(MPathTarget *mpt,
static void motionpath_free_free_tree_data(ListBase *targets)
{
- for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
+ LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
BLI_dlrbTree_free(&mpt->keys);
}
}
@@ -412,7 +412,7 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph,
DEG_make_inactive(depsgraph);
}
- for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
+ LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
mpt->ob_eval = DEG_get_evaluated_object(depsgraph, mpt->ob);
AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id);
@@ -492,7 +492,7 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph,
}
/* clear recalc flags from targets */
- for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) {
+ LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
bMotionPath *mpath = mpt->mpath;
/* get pointer to animviz settings for each target */
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 9e3f91bc971..40cd368e02b 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -21,22 +21,22 @@
* \ingroup edanimation
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include "BLI_sys_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math_base.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
#include "BKE_context.h"
-#include "BKE_sequencer.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_scene.h"
+#include "BKE_sequencer.h"
#include "UI_view2d.h"
@@ -49,6 +49,7 @@
#include "ED_anim_api.h"
#include "ED_screen.h"
#include "ED_sequencer.h"
+#include "ED_time_scrub_ui.h"
#include "ED_util.h"
#include "DEG_depsgraph.h"
@@ -61,7 +62,7 @@
/* Check if the operator can be run from the current context */
static bool change_frame_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* XXX temp? prevent changes during render */
if (G.is_rendering) {
@@ -71,16 +72,10 @@ static bool change_frame_poll(bContext *C)
/* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
* this shouldn't show up in 3D editor (or others without 2D timeline view) via search
*/
- if (sa) {
- if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
+ if (area) {
+ if (ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP, SPACE_GRAPH)) {
return true;
}
- else if (sa->spacetype == SPACE_GRAPH) {
- /* NOTE: Graph Editor has special version which does some extra stuff.
- * No need to show the generic error message for that case though!
- */
- return false;
- }
}
CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
@@ -151,11 +146,13 @@ static float frame_from_event(bContext *C, const wmEvent *event)
static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
bScreen *screen = CTX_wm_screen(C);
- if (sa && sa->spacetype == SPACE_SEQ) {
- SpaceSeq *sseq = sa->spacedata.first;
- if (ED_space_sequencer_check_show_strip(sseq)) {
+ if (area && area->spacetype == SPACE_SEQ) {
+ SpaceSeq *sseq = area->spacedata.first;
+ ARegion *region = CTX_wm_region(C);
+ if (ED_space_sequencer_check_show_strip(sseq) &&
+ !ED_time_scrub_event_in_region(region, event)) {
ED_sequencer_special_preview_set(C, event->mval);
}
}
@@ -215,7 +212,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
ret = OPERATOR_FINISHED;
break;
@@ -233,8 +230,8 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
break;
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY:
+ case EVT_LEFTCTRLKEY:
+ case EVT_RIGHTCTRLKEY:
if (event->val == KM_RELEASE) {
RNA_boolean_set(op->ptr, "snap", false);
}
@@ -282,7 +279,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
static bool anim_set_end_frames_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* XXX temp? prevent changes during render */
if (G.is_rendering) {
@@ -292,8 +289,8 @@ static bool anim_set_end_frames_poll(bContext *C)
/* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
* this shouldn't show up in 3D editor (or others without 2D timeline view) via search
*/
- if (sa) {
- if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
+ if (area) {
+ if (ELEM(area->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
return true;
}
}
@@ -403,7 +400,7 @@ static void ANIM_OT_end_frame_set(wmOperatorType *ot)
static int previewrange_define_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float sfra, efra;
rcti rect;
@@ -411,8 +408,8 @@ static int previewrange_define_exec(bContext *C, wmOperator *op)
WM_operator_properties_border_to_rcti(op, &rect);
/* convert min/max values to frames (i.e. region to 'tot' rect) */
- sfra = UI_view2d_region_to_view_x(&ar->v2d, rect.xmin);
- efra = UI_view2d_region_to_view_x(&ar->v2d, rect.xmax);
+ sfra = UI_view2d_region_to_view_x(&region->v2d, rect.xmin);
+ efra = UI_view2d_region_to_view_x(&region->v2d, rect.xmax);
/* set start/end frames for preview-range
* - must clamp within allowable limits
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 64f7fe034dc..82e24eaa6e3 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -21,24 +21,26 @@
* \ingroup edanimation
*/
+#include <ctype.h>
#include <stdio.h>
#include <string.h>
-#include <ctype.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
#include "DNA_texture_types.h"
+#include "BKE_anim_data.h"
#include "BKE_animsys.h"
-#include "BKE_fcurve.h"
#include "BKE_context.h"
+#include "BKE_fcurve.h"
+#include "BKE_fcurve_driver.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
@@ -421,7 +423,8 @@ int ANIM_add_driver_with_target(ReportList *reports,
/* --------------------------------- */
-/* Main Driver Management API calls:
+/**
+ * Main Driver Management API calls:
* Add a new driver for the specified property on the given ID block
*/
int ANIM_add_driver(
@@ -1098,15 +1101,15 @@ static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *
/* 1) Create a new "empty" driver for this property */
char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
- short success = 0;
+ bool changed = false;
if (path) {
- success += ANIM_add_driver(
- op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON);
+ changed |= (ANIM_add_driver(
+ op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON) != 0);
MEM_freeN(path);
}
- if (success) {
+ if (changed) {
/* send updates */
UI_context_update_anim_flag(C);
DEG_id_tag_update(ptr.owner_id, ID_RECALC_COPY_ON_WRITE);
@@ -1144,7 +1147,7 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
- short success = 0;
+ bool changed = false;
int index;
const bool all = RNA_boolean_get(op->ptr, "all");
@@ -1159,20 +1162,20 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op)
char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
if (path) {
- success = ANIM_remove_driver(op->reports, ptr.owner_id, path, index, 0);
+ changed = ANIM_remove_driver(op->reports, ptr.owner_id, path, index, 0);
MEM_freeN(path);
}
}
- if (success) {
+ if (changed) {
/* send updates */
UI_context_update_anim_flag(C);
DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
}
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_driver_button_remove(wmOperatorType *ot)
@@ -1234,7 +1237,7 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
- short success = 0;
+ bool changed = false;
int index;
/* try to create driver using property retrieved from UI */
@@ -1245,7 +1248,7 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op)
if (path) {
/* only copy the driver for the button that this was involved for */
- success = ANIM_copy_driver(op->reports, ptr.owner_id, path, index, 0);
+ changed = ANIM_copy_driver(op->reports, ptr.owner_id, path, index, 0);
UI_context_update_anim_flag(C);
@@ -1254,7 +1257,7 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op)
}
/* since we're just copying, we don't really need to do anything else...*/
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_copy_driver_button(wmOperatorType *ot)
@@ -1278,7 +1281,7 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
- short success = 0;
+ bool changed = false;
int index;
/* try to create driver using property retrieved from UI */
@@ -1289,7 +1292,7 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
if (path) {
/* only copy the driver for the button that this was involved for */
- success = ANIM_paste_driver(op->reports, ptr.owner_id, path, index, 0);
+ changed = ANIM_paste_driver(op->reports, ptr.owner_id, path, index, 0);
UI_context_update_anim_flag(C);
@@ -1304,7 +1307,7 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
}
/* since we're just copying, we don't really need to do anything else...*/
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_paste_driver_button(wmOperatorType *ot)
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 705351522f8..eadaa449b92 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -42,7 +42,6 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
@@ -178,7 +177,7 @@ static void draw_modifier__generator(uiLayout *layout,
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
float *cp = NULL;
char xval[32];
- unsigned int i;
+ uint i;
int maxXWidth;
/* draw polynomial order selector */
@@ -274,7 +273,7 @@ static void draw_modifier__generator(uiLayout *layout,
/* 'x' param (and '+' if necessary) */
if (i == 0) {
- BLI_strncpy(xval, "", sizeof(xval));
+ BLI_strncpy(xval, " ", sizeof(xval));
}
else if (i == 1) {
BLI_strncpy(xval, "x", sizeof(xval));
@@ -317,7 +316,7 @@ static void draw_modifier__generator(uiLayout *layout,
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* Factorized polynomial expression */
{
float *cp = NULL;
- unsigned int i;
+ uint i;
/* draw polynomial order selector */
row = uiLayoutRow(layout, false);
@@ -718,28 +717,31 @@ static void draw_modifier__envelope(uiLayout *layout,
/* control points list */
for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
+ PointerRNA ctrl_ptr;
+ RNA_pointer_create(fcurve_owner_id, &RNA_FModifierEnvelopeControlPoint, fed, &ctrl_ptr);
+
/* get a new row to operate on */
row = uiLayoutRow(layout, true);
block = uiLayoutGetBlock(row);
UI_block_align_begin(block);
- but = uiDefButF(block,
- UI_BTYPE_NUM,
- B_FMODIFIER_REDRAW,
- IFACE_("Fra:"),
- 0,
- 0,
- 4.5 * UI_UNIT_X,
- UI_UNIT_Y,
- &fed->time,
- -MAXFRAMEF,
- MAXFRAMEF,
- 10,
- 1,
- TIP_("Frame that envelope point occurs"));
- UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
-
- uiDefButF(block,
+ uiDefButR(block,
+ UI_BTYPE_NUM,
+ B_FMODIFIER_REDRAW,
+ IFACE_("Fra:"),
+ 0,
+ 0,
+ 4.5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ &ctrl_ptr,
+ "frame",
+ -1,
+ -MAXFRAMEF,
+ MAXFRAMEF,
+ 10,
+ 1,
+ NULL);
+ uiDefButR(block,
UI_BTYPE_NUM,
B_FMODIFIER_REDRAW,
IFACE_("Min:"),
@@ -747,13 +749,15 @@ static void draw_modifier__envelope(uiLayout *layout,
0,
5 * UI_UNIT_X,
UI_UNIT_Y,
- &fed->min,
+ &ctrl_ptr,
+ "min",
+ -1,
-UI_FLT_MAX,
UI_FLT_MAX,
10,
2,
- TIP_("Minimum bound of envelope at this point"));
- uiDefButF(block,
+ NULL);
+ uiDefButR(block,
UI_BTYPE_NUM,
B_FMODIFIER_REDRAW,
IFACE_("Max:"),
@@ -761,12 +765,14 @@ static void draw_modifier__envelope(uiLayout *layout,
0,
5 * UI_UNIT_X,
UI_UNIT_Y,
- &fed->max,
+ &ctrl_ptr,
+ "max",
+ -1,
-UI_FLT_MAX,
UI_FLT_MAX,
10,
2,
- TIP_("Maximum bound of envelope at this point"));
+ NULL);
but = uiDefIconBut(block,
UI_BTYPE_BUT,
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 479e7192b0e..b921ba039be 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -23,25 +23,26 @@
/* System includes ----------------------------------------------------- */
+#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <float.h>
#include "MEM_guardedalloc.h"
#include "BLI_dlrbTree.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_rect.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
+#include "DNA_brush_types.h"
#include "DNA_cachefile_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "DNA_gpencil_types.h"
-#include "DNA_brush_types.h"
#include "DNA_mask_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_fcurve.h"
@@ -505,14 +506,14 @@ static void update_keyblocks(DLRBT_Tree *keys, BezTriple *bezt, int bezt_len)
/* Find the curve count */
int max_curve = 0;
- for (ActKeyColumn *col = keys->first; col; col = col->next) {
+ LISTBASE_FOREACH (ActKeyColumn *, col, keys) {
max_curve = MAX2(max_curve, col->totcurve);
}
/* Propagate blocks to inserted keys */
ActKeyColumn *prev_ready = NULL;
- for (ActKeyColumn *col = keys->first; col; col = col->next) {
+ LISTBASE_FOREACH (ActKeyColumn *, col, keys) {
/* Pre-existing column. */
if (col->totcurve > 0) {
prev_ready = col;
@@ -558,11 +559,11 @@ void draw_keyframe_shape(float x,
short key_type,
short mode,
float alpha,
- unsigned int pos_id,
- unsigned int size_id,
- unsigned int color_id,
- unsigned int outline_color_id,
- unsigned int flags_id,
+ uint pos_id,
+ uint size_id,
+ uint color_id,
+ uint outline_color_id,
+ uint flags_id,
short handle_type,
short extreme_type)
{
@@ -595,9 +596,9 @@ void draw_keyframe_shape(float x,
size -= 0.8f * key_type;
}
- unsigned char fill_col[4];
- unsigned char outline_col[4];
- unsigned int flags = 0;
+ uchar fill_col[4];
+ uchar outline_col[4];
+ uint flags = 0;
/* draw! */
if (draw_fill) {
@@ -730,7 +731,7 @@ static void draw_keylist(View2D *v2d,
ipo_color_mix[3] *= 0.5f;
uint block_len = 0;
- for (ActKeyColumn *ab = keys->first; ab; ab = ab->next) {
+ LISTBASE_FOREACH (ActKeyColumn *, ab, keys) {
if (actkeyblock_get_valid_hold(ab)) {
block_len++;
}
@@ -746,7 +747,7 @@ static void draw_keylist(View2D *v2d,
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GPU_PRIM_TRIS, 6 * block_len);
- for (ActKeyColumn *ab = keys->first; ab; ab = ab->next) {
+ LISTBASE_FOREACH (ActKeyColumn *, ab, keys) {
int valid_hold = actkeyblock_get_valid_hold(ab);
if (valid_hold != 0) {
if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
@@ -791,7 +792,7 @@ static void draw_keylist(View2D *v2d,
if (keys) {
/* count keys */
uint key_len = 0;
- for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
+ LISTBASE_FOREACH (ActKeyColumn *, ak, keys) {
/* Optimization: if keyframe doesn't appear within 5 units (screenspace)
* in visible area, don't draw.
* This might give some improvements,
@@ -822,7 +823,7 @@ static void draw_keylist(View2D *v2d,
short handle_type = KEYFRAME_HANDLE_NONE, extreme_type = KEYFRAME_EXTREME_NONE;
- for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
+ LISTBASE_FOREACH (ActKeyColumn *, ak, keys) {
if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
if (show_ipo) {
handle_type = ak->handle_type;
@@ -1153,7 +1154,7 @@ void cachefile_to_keylist(bDopeSheet *ads,
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* loop through each F-Curve, grabbing the keyframes */
- for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
+ LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
}
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index dc413e936eb..2dae4e8b4c5 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -20,17 +20,17 @@
* \ingroup edanimation
*/
+#include <float.h>
+#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
-#include <float.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_lasso_2d.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -79,7 +79,7 @@ short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked,
{
BezTriple *bezt;
short ok = 0;
- unsigned int i;
+ uint i;
/* sanity check */
if (ELEM(NULL, fcu, fcu->bezt)) {
@@ -456,6 +456,24 @@ short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked,
return 0;
}
+void ANIM_animdata_keyframe_callback(bAnimContext *ac,
+ eAnimFilter_Flags filter,
+ KeyframeEditFunc callback_fn)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, callback_fn, calchandles_fcurve);
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+
+ ANIM_animdata_update(ac, &anim_data);
+ ANIM_animdata_freelist(&anim_data);
+}
+
/* ************************************************************************** */
/* Keyframe Integrity Tools */
@@ -501,7 +519,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
ok |= KEYFRAME_OK_KEY; \
\
if (ked && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { \
- /* Only act on visible items, so check handle visiblity state. */ \
+ /* Only act on visible items, so check handle visibility state. */ \
const bool handles_visible = ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ? \
(BEZT_ISSEL_ANY(bezt)) : \
true); \
@@ -615,7 +633,7 @@ bool keyframe_region_lasso_test(const KeyframeEdit_LassoData *data_lasso, const
BLI_rctf_transform_pt_v(data_lasso->rectf_view, data_lasso->rectf_scaled, xy_view, xy);
if (BLI_lasso_is_point_inside(
- data_lasso->mcords, data_lasso->mcords_tot, xy_view[0], xy_view[1], INT_MAX)) {
+ data_lasso->mcoords, data_lasso->mcoords_len, xy_view[0], xy_view[1], INT_MAX)) {
return true;
}
}
@@ -1459,7 +1477,7 @@ KeyframeEditFunc ANIM_editkeyframes_easing(short mode)
static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
{
- /* Only act on visible items, so check handle visiblity state. */
+ /* Only act on visible items, so check handle visibility state. */
const bool handles_visible = ked && ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ?
(BEZT_ISSEL_ANY(bezt)) :
true);
@@ -1485,7 +1503,7 @@ static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt)
{
- /* Only act on visible items, so check handle visiblity state. */
+ /* Only act on visible items, so check handle visibility state. */
const bool handles_visible = ked && ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ?
(BEZT_ISSEL_ANY(bezt)) :
true);
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index ed5cb65c42e..fc9ec870496 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -21,17 +21,17 @@
* \ingroup edanimation
*/
+#include <float.h>
+#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
-#include <float.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-#include "BLI_string_utils.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
+#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -39,17 +39,17 @@
#include "BKE_action.h"
#include "BKE_curve.h"
+#include "BKE_deform.h"
#include "BKE_fcurve.h"
-#include "BKE_report.h"
#include "BKE_main.h"
-#include "BKE_deform.h"
+#include "BKE_report.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
#include "ED_anim_api.h"
-#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
+#include "ED_keyframing.h"
/* This file contains code for various keyframe-editing tools which are 'destructive'
* (i.e. they will modify the order of the keyframes, and change the size of the array).
@@ -1189,7 +1189,7 @@ short paste_animedit_keys(bAnimContext *ac,
* one F-Curve has been pasted into.
*/
for (pass = 0; pass < 3; pass++) {
- unsigned int totmatch = 0;
+ uint totmatch = 0;
for (ale = anim_data->first; ale; ale = ale->next) {
/* Find buffer item to paste from:
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 14b1f6523d9..04061ceea51 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -21,11 +21,11 @@
* \ingroup edanimation
*/
-#include <stdio.h>
+#include <float.h>
+#include <math.h>
#include <stddef.h>
+#include <stdio.h>
#include <string.h>
-#include <math.h>
-#include <float.h>
#include "MEM_guardedalloc.h"
@@ -40,17 +40,19 @@
#include "DNA_constraint_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
#include "BKE_action.h"
+#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
+#include "BKE_fcurve_driver.h"
#include "BKE_global.h"
-#include "BKE_idcode.h"
+#include "BKE_idtype.h"
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -62,10 +64,10 @@
#include "DEG_depsgraph_query.h"
#include "ED_anim_api.h"
-#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
-#include "ED_screen.h"
+#include "ED_keyframing.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -87,7 +89,7 @@ static KeyingSet *keyingset_get_from_op_with_error(wmOperator *op,
/* Keyframing Setting Wrangling */
/* Get the active settings for keyframing settings from context (specifically the given scene) */
-short ANIM_get_keyframing_flags(Scene *scene, short incl_mode)
+eInsertKeyFlags ANIM_get_keyframing_flags(Scene *scene, const bool use_autokey_mode)
{
eInsertKeyFlags flag = INSERTKEY_NOFLAGS;
@@ -110,7 +112,7 @@ short ANIM_get_keyframing_flags(Scene *scene, short incl_mode)
}
/* only if including settings from the autokeying mode... */
- if (incl_mode) {
+ if (use_autokey_mode) {
/* keyframing mode - only replace existing keyframes */
if (IS_AUTOKEY_MODE(scene, EDITKEYS)) {
flag |= INSERTKEY_REPLACE;
@@ -131,13 +133,13 @@ short ANIM_get_keyframing_flags(Scene *scene, short incl_mode)
/* Get (or add relevant data to be able to do so) the Active Action for the given
* Animation Data block, given an ID block where the Animation Data should reside.
*/
-bAction *verify_adt_action(Main *bmain, ID *id, short add)
+bAction *ED_id_action_ensure(Main *bmain, ID *id)
{
AnimData *adt;
/* init animdata if none available yet */
adt = BKE_animdata_from_id(id);
- if ((adt == NULL) && (add)) {
+ if (adt == NULL) {
adt = BKE_animdata_add_id(id);
}
if (adt == NULL) {
@@ -148,7 +150,7 @@ bAction *verify_adt_action(Main *bmain, ID *id, short add)
/* init action if none available yet */
/* TODO: need some wizardry to handle NLA stuff correct */
- if ((adt->action == NULL) && (add)) {
+ if (adt->action == NULL) {
/* init action name from name of ID block */
char actname[sizeof(id->name) - 2];
BLI_snprintf(actname, sizeof(actname), "%sAction", id->name + 2);
@@ -172,21 +174,34 @@ bAction *verify_adt_action(Main *bmain, ID *id, short add)
return adt->action;
}
-/* Get (or add relevant data to be able to do so) F-Curve from the Active Action,
+/**
+ * Find the F-Curve from the Active Action,
* for the given Animation Data block. This assumes that all the destinations are valid.
*/
-FCurve *verify_fcurve(Main *bmain,
- bAction *act,
- const char group[],
- PointerRNA *ptr,
- const char rna_path[],
- const int array_index,
- short add)
+FCurve *ED_action_fcurve_find(struct bAction *act, const char rna_path[], const int array_index)
+{
+ /* Sanity checks. */
+ if (ELEM(NULL, act, rna_path)) {
+ return NULL;
+ }
+ return list_find_fcurve(&act->curves, rna_path, array_index);
+}
+
+/**
+ * Get (or add relevant data to be able to do so) F-Curve from the Active Action,
+ * for the given Animation Data block. This assumes that all the destinations are valid.
+ */
+FCurve *ED_action_fcurve_ensure(struct Main *bmain,
+ struct bAction *act,
+ const char group[],
+ struct PointerRNA *ptr,
+ const char rna_path[],
+ const int array_index)
{
bActionGroup *agrp;
FCurve *fcu;
- /* sanity checks */
+ /* Sanity checks. */
if (ELEM(NULL, act, rna_path)) {
return NULL;
}
@@ -197,7 +212,7 @@ FCurve *verify_fcurve(Main *bmain,
*/
fcu = list_find_fcurve(&act->curves, rna_path, array_index);
- if ((fcu == NULL) && (add)) {
+ if (fcu == NULL) {
/* use default settings to make a F-Curve */
fcu = MEM_callocN(sizeof(FCurve), "FCurve");
@@ -223,7 +238,7 @@ FCurve *verify_fcurve(Main *bmain,
/* sync bone group colors if applicable */
if (ptr && (ptr->type == &RNA_PoseBone)) {
Object *ob = (Object *)ptr->owner_id;
- bPoseChannel *pchan = (bPoseChannel *)ptr->data;
+ bPoseChannel *pchan = ptr->data;
bPose *pose = ob->pose;
bActionGroup *grp;
@@ -481,7 +496,7 @@ int insert_vert_fcurve(
FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag)
{
BezTriple beztr = {{{0}}};
- unsigned int oldTot = fcu->totvert;
+ uint oldTot = fcu->totvert;
int a;
/* set all three points, for nicer start position
@@ -821,7 +836,7 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
*/
if (ptr->type == &RNA_Object) {
/* Object */
- Object *ob = (Object *)ptr->data;
+ Object *ob = ptr->data;
RigidBodyOb *rbo = ob->rigidbody_object;
con = ob->constraints.first;
@@ -833,7 +848,7 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
}
else if (ptr->type == &RNA_PoseBone) {
/* Pose Channel */
- bPoseChannel *pchan = (bPoseChannel *)ptr->data;
+ bPoseChannel *pchan = ptr->data;
con = pchan->constraints.first;
identifier = RNA_property_identifier(prop);
@@ -983,7 +998,7 @@ static float *visualkey_get_values(
* - assume that array_index will be sane
*/
if (ptr->type == &RNA_Object) {
- Object *ob = (Object *)ptr->data;
+ Object *ob = ptr->data;
/* Loc code is specific... */
if (strstr(identifier, "location")) {
copy_v3_v3(buffer, ob->obmat[3]);
@@ -995,7 +1010,7 @@ static float *visualkey_get_values(
rotmode = ob->rotmode;
}
else if (ptr->type == &RNA_PoseBone) {
- bPoseChannel *pchan = (bPoseChannel *)ptr->data;
+ bPoseChannel *pchan = ptr->data;
BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, tmat);
rotmode = pchan->rotmode;
@@ -1284,7 +1299,9 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
* but still try to get the F-Curve if it exists...
*/
bool can_create_curve = (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) == 0;
- FCurve *fcu = verify_fcurve(bmain, act, group, ptr, rna_path, array_index, can_create_curve);
+ FCurve *fcu = can_create_curve ?
+ ED_action_fcurve_ensure(bmain, act, group, ptr, rna_path, array_index) :
+ ED_action_fcurve_find(act, rna_path, array_index);
/* we may not have a F-Curve when we're replacing only... */
if (fcu) {
@@ -1313,7 +1330,9 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
}
}
-/* Main Keyframing API call:
+/**
+ * Main Keyframing API call
+ *
* Use this when validation of necessary animation data is necessary, since it may not exist yet.
*
* The flag argument is used for special settings that alter the behavior of
@@ -1321,18 +1340,20 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
* and extra keyframe filtering.
*
* index of -1 keys all array indices
+ *
+ * \return The number of key-frames inserted.
*/
-short insert_keyframe(Main *bmain,
- ReportList *reports,
- ID *id,
- bAction *act,
- const char group[],
- const char rna_path[],
- int array_index,
- float cfra,
- eBezTriple_KeyframeType keytype,
- ListBase *nla_cache,
- eInsertKeyFlags flag)
+int insert_keyframe(Main *bmain,
+ ReportList *reports,
+ ID *id,
+ bAction *act,
+ const char group[],
+ const char rna_path[],
+ int array_index,
+ float cfra,
+ eBezTriple_KeyframeType keytype,
+ ListBase *nla_cache,
+ eInsertKeyFlags flag)
{
PointerRNA id_ptr, ptr;
PropertyRNA *prop = NULL;
@@ -1361,7 +1382,7 @@ short insert_keyframe(Main *bmain,
/* if no action is provided, keyframe to the default one attached to this ID-block */
if (act == NULL) {
/* get action to add F-Curve+keyframe to */
- act = verify_adt_action(bmain, id, 1);
+ act = ED_id_action_ensure(bmain, id);
if (act == NULL) {
BKE_reportf(reports,
@@ -1555,15 +1576,16 @@ static void deg_tag_after_keyframe_delete(Main *bmain, ID *id, AnimData *adt)
}
}
-short delete_keyframe(Main *bmain,
- ReportList *reports,
- ID *id,
- bAction *act,
- const char group[],
- const char rna_path[],
- int array_index,
- float cfra,
- eInsertKeyFlags UNUSED(flag))
+/**
+ * \return The number of key-frames deleted.
+ */
+int delete_keyframe(Main *bmain,
+ ReportList *reports,
+ ID *id,
+ bAction *act,
+ const char rna_path[],
+ int array_index,
+ float cfra)
{
AnimData *adt = BKE_animdata_from_id(id);
PointerRNA id_ptr, ptr;
@@ -1625,7 +1647,7 @@ short delete_keyframe(Main *bmain,
/* will only loop once unless the array index was -1 */
for (; array_index < array_index_max; array_index++) {
- FCurve *fcu = verify_fcurve(bmain, act, group, &ptr, rna_path, array_index, 0);
+ FCurve *fcu = ED_action_fcurve_find(act, rna_path, array_index);
/* check if F-Curve exists and/or whether it can be edited */
if (fcu == NULL) {
@@ -1637,7 +1659,7 @@ short delete_keyframe(Main *bmain,
RPT_WARNING,
"Not deleting keyframe for locked F-Curve '%s' for %s '%s'",
fcu->rna_path,
- BKE_idcode_to_name(GS(id->name)),
+ BKE_idtype_idcode_to_name(GS(id->name)),
id->name + 2);
continue;
}
@@ -1654,21 +1676,23 @@ short delete_keyframe(Main *bmain,
/* ************************************************** */
/* KEYFRAME CLEAR */
-/* Main Keyframing API call:
+/**
+ * Main Keyframing API call:
* Use this when validation of necessary animation data isn't necessary as it
* already exists. It will clear the current buttons fcurve(s).
*
* The flag argument is used for special settings that alter the behavior of
* the keyframe deletion. These include the quick refresh options.
+ *
+ * \return The number of f-curves removed.
*/
-static short clear_keyframe(Main *bmain,
- ReportList *reports,
- ID *id,
- bAction *act,
- const char group[],
- const char rna_path[],
- int array_index,
- eInsertKeyFlags UNUSED(flag))
+static int clear_keyframe(Main *bmain,
+ ReportList *reports,
+ ID *id,
+ bAction *act,
+ const char rna_path[],
+ int array_index,
+ eInsertKeyFlags UNUSED(flag))
{
AnimData *adt = BKE_animdata_from_id(id);
PointerRNA id_ptr, ptr;
@@ -1727,7 +1751,7 @@ static short clear_keyframe(Main *bmain,
/* will only loop once unless the array index was -1 */
for (; array_index < array_index_max; array_index++) {
- FCurve *fcu = verify_fcurve(bmain, act, group, &ptr, rna_path, array_index, 0);
+ FCurve *fcu = ED_action_fcurve_find(act, rna_path, array_index);
/* check if F-Curve exists and/or whether it can be edited */
if (fcu == NULL) {
@@ -1739,7 +1763,7 @@ static short clear_keyframe(Main *bmain,
RPT_WARNING,
"Not clearing all keyframes from locked F-Curve '%s' for %s '%s'",
fcu->rna_path,
- BKE_idcode_to_name(GS(id->name)),
+ BKE_idtype_idcode_to_name(GS(id->name)),
id->name + 2);
continue;
}
@@ -1771,11 +1795,11 @@ enum {
*/
static bool modify_key_op_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Scene *scene = CTX_data_scene(C);
/* if no area or active scene */
- if (ELEM(NULL, sa, scene)) {
+ if (ELEM(NULL, area, scene)) {
return false;
}
@@ -1792,7 +1816,7 @@ static int insert_key_exec(bContext *C, wmOperator *op)
bool ob_edit_mode = false;
float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
- short success;
+ int num_channels;
KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene);
if (ks == NULL) {
@@ -1808,13 +1832,13 @@ static int insert_key_exec(bContext *C, wmOperator *op)
}
/* try to insert keyframes for the channels specified by KeyingSet */
- success = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ num_channels = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
if (G.debug & G_DEBUG) {
BKE_reportf(op->reports,
RPT_INFO,
"Keying set '%s' - successfully added %d keyframes",
ks->name,
- success);
+ num_channels);
}
/* restore the edit mode if necessary */
@@ -1823,17 +1847,17 @@ static int insert_key_exec(bContext *C, wmOperator *op)
}
/* report failure or do updates? */
- if (success == MODIFYKEY_INVALID_CONTEXT) {
+ if (num_channels < 0) {
BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
return OPERATOR_CANCELLED;
}
- else if (success) {
+ else if (num_channels > 0) {
/* if the appropriate properties have been set, make a note that we've inserted something */
if (RNA_boolean_get(op->ptr, "confirm_success")) {
BKE_reportf(op->reports,
RPT_INFO,
"Successfully added %d keyframes for keying set '%s'",
- success,
+ num_channels,
ks->name);
}
@@ -1996,7 +2020,7 @@ static int delete_key_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
- short success;
+ int num_channels;
KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene);
if (ks == NULL) {
@@ -2033,23 +2057,23 @@ static int delete_key_exec(bContext *C, wmOperator *op)
}
/* try to delete keyframes for the channels specified by KeyingSet */
- success = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
+ num_channels = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
if (G.debug & G_DEBUG) {
- printf("KeyingSet '%s' - Successfully removed %d Keyframes\n", ks->name, success);
+ printf("KeyingSet '%s' - Successfully removed %d Keyframes\n", ks->name, num_channels);
}
/* report failure or do updates? */
- if (success == MODIFYKEY_INVALID_CONTEXT) {
+ if (num_channels < 0) {
BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set");
return OPERATOR_CANCELLED;
}
- else if (success) {
+ else if (num_channels > 0) {
/* if the appropriate properties have been set, make a note that we've inserted something */
if (RNA_boolean_get(op->ptr, "confirm_success")) {
BKE_reportf(op->reports,
RPT_INFO,
"Successfully removed %d keyframes for keying set '%s'",
- success,
+ num_channels,
ks->name);
}
@@ -2355,13 +2379,13 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
char *path;
uiBut *but;
float cfra = (float)CFRA;
- short success = 0;
+ bool changed = false;
int index;
const bool all = RNA_boolean_get(op->ptr, "all");
eInsertKeyFlags flag = INSERTKEY_NOFLAGS;
/* flags for inserting keyframes */
- flag = ANIM_get_keyframing_flags(scene, 1);
+ flag = ANIM_get_keyframing_flags(scene, true);
/* try to insert keyframe using property retrieved from UI */
if (!(but = UI_context_active_but_prop_get(C, &ptr, &prop, &index))) {
@@ -2375,11 +2399,11 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
* strips themselves. These are stored separately or else the properties will
* not have any effect.
*/
- NlaStrip *strip = (NlaStrip *)ptr.data;
+ NlaStrip *strip = ptr.data;
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
if (fcu) {
- success = insert_keyframe_direct(
+ changed = insert_keyframe_direct(
op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, 0);
}
else {
@@ -2396,7 +2420,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
if (fcu && driven) {
- success = insert_keyframe_direct(
+ changed = insert_keyframe_direct(
op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, INSERTKEY_DRIVER);
}
}
@@ -2416,7 +2440,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
* TODO: Perhaps we can extend this behavior in future for other properties...
*/
if (ptr.type == &RNA_PoseBone) {
- bPoseChannel *pchan = (bPoseChannel *)ptr.data;
+ bPoseChannel *pchan = ptr.data;
group = pchan->name;
}
else if ((ptr.type == &RNA_Object) &&
@@ -2433,17 +2457,17 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
index = -1;
}
- success = insert_keyframe(bmain,
- op->reports,
- ptr.owner_id,
- NULL,
- group,
- path,
- index,
- cfra,
- ts->keyframe_type,
- NULL,
- flag);
+ changed = (insert_keyframe(bmain,
+ op->reports,
+ ptr.owner_id,
+ NULL,
+ group,
+ path,
+ index,
+ cfra,
+ ts->keyframe_type,
+ NULL,
+ flag) != 0);
MEM_freeN(path);
}
@@ -2467,12 +2491,12 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
RPT_WARNING,
"Button doesn't appear to have any property information attached (ptr.data = "
"%p, prop = %p)",
- (void *)ptr.data,
+ ptr.data,
(void *)prop);
}
}
- if (success) {
+ if (changed) {
ID *id = ptr.owner_id;
AnimData *adt = BKE_animdata_from_id(id);
if (adt->action != NULL) {
@@ -2487,7 +2511,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
}
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyframe_insert_button(wmOperatorType *ot)
@@ -2518,7 +2542,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
char *path;
float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
- short success = 0;
+ bool changed = false;
int index;
const bool all = RNA_boolean_get(op->ptr, "all");
@@ -2535,7 +2559,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
* not have any effect.
*/
ID *id = ptr.owner_id;
- NlaStrip *strip = (NlaStrip *)ptr.data;
+ NlaStrip *strip = ptr.data;
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
if (fcu) {
@@ -2545,7 +2569,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
RPT_WARNING,
"Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
strip->name,
- BKE_idcode_to_name(GS(id->name)),
+ BKE_idtype_idcode_to_name(GS(id->name)),
id->name + 2);
}
else {
@@ -2561,7 +2585,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
if (found) {
/* delete the key at the index (will sanity check + do recalc afterwards) */
delete_fcurve_key(fcu, i, 1);
- success = true;
+ changed = true;
}
}
}
@@ -2576,8 +2600,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
index = -1;
}
- success = delete_keyframe(
- bmain, op->reports, ptr.owner_id, NULL, NULL, path, index, cfra, 0);
+ changed = delete_keyframe(bmain, op->reports, ptr.owner_id, NULL, path, index, cfra) != 0;
MEM_freeN(path);
}
else if (G.debug & G_DEBUG) {
@@ -2586,10 +2609,10 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
}
}
else if (G.debug & G_DEBUG) {
- printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
+ printf("ptr.data = %p, prop = %p\n", ptr.data, (void *)prop);
}
- if (success) {
+ if (changed) {
/* send updates */
UI_context_update_anim_flag(C);
@@ -2597,7 +2620,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
}
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
@@ -2626,7 +2649,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
PropertyRNA *prop = NULL;
Main *bmain = CTX_data_main(C);
char *path;
- short success = 0;
+ bool changed = false;
int index;
const bool all = RNA_boolean_get(op->ptr, "all");
@@ -2645,7 +2668,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
index = -1;
}
- success += clear_keyframe(bmain, op->reports, ptr.owner_id, NULL, NULL, path, index, 0);
+ changed |= (clear_keyframe(bmain, op->reports, ptr.owner_id, NULL, path, index, 0) != 0);
MEM_freeN(path);
}
else if (G.debug & G_DEBUG) {
@@ -2653,10 +2676,10 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
}
}
else if (G.debug & G_DEBUG) {
- printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
+ printf("ptr.data = %p, prop = %p\n", ptr.data, (void *)prop);
}
- if (success) {
+ if (changed) {
/* send updates */
UI_context_update_anim_flag(C);
@@ -2664,7 +2687,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL);
}
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
@@ -2688,7 +2711,7 @@ void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
/* ******************************************* */
/* AUTO KEYFRAME */
-bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
+bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
{
float cfra = (float)CFRA; // XXX for now, this will do
@@ -2848,7 +2871,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOMAT)) {
/* if only active, then we can skip a lot of looping */
if (filter & ANIMFILTER_KEYS_ACTIVE) {
- Material *ma = give_current_material(ob, (ob->actcol + 1));
+ Material *ma = BKE_object_material_get(ob, (ob->actcol + 1));
/* we only retrieve the active material... */
if (id_frame_has_keyframe((ID *)ma, frame, filter)) {
@@ -2860,7 +2883,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
/* loop over materials */
for (a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
+ Material *ma = BKE_object_material_get(ob, a + 1);
if (id_frame_has_keyframe((ID *)ma, frame, filter)) {
return true;
@@ -2916,10 +2939,10 @@ bool ED_autokeyframe_object(bContext *C, Scene *scene, Object *ob, KeyingSet *ks
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
ListBase dsources = {NULL, NULL};
- /* now insert the keyframe(s) using the Keying Set
- * 1) add datasource override for the Object
- * 2) insert keyframes
- * 3) free the extra info
+ /* Now insert the key-frame(s) using the Keying Set:
+ * 1) Add data-source override for the Object.
+ * 2) Insert key-frames.
+ * 3) Free the extra info.
*/
ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
@@ -2938,10 +2961,10 @@ bool ED_autokeyframe_pchan(
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
ListBase dsources = {NULL, NULL};
- /* now insert the keyframe(s) using the Keying Set
- * 1) add datasource override for the PoseChannel
- * 2) insert keyframes
- * 3) free the extra info
+ /* Now insert the keyframe(s) using the Keying Set:
+ * 1) Add data-source override for the pose-channel.
+ * 2) Insert key-frames.
+ * 3) Free the extra info.
*/
ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
@@ -3014,9 +3037,7 @@ bool ED_autokeyframe_property(
if (autokeyframe_cfra_can_key(scene, id)) {
ReportList *reports = CTX_wm_reports(C);
ToolSettings *ts = scene->toolsettings;
- short flag = ANIM_get_keyframing_flags(scene, 1);
-
- fcu->flag &= ~FCURVE_SELECTED;
+ const eInsertKeyFlags flag = ANIM_get_keyframing_flags(scene, true);
/* Note: We use rnaindex instead of fcu->array_index,
* because a button may control all items of an array at once.
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 258c0e4f1f6..89c7860982b 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -21,11 +21,11 @@
* \ingroup edanimation
*/
-#include <stdio.h>
+#include <float.h>
+#include <math.h>
#include <stddef.h>
+#include <stdio.h>
#include <string.h>
-#include <math.h>
-#include <float.h>
#include "MEM_guardedalloc.h"
@@ -33,12 +33,12 @@
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
-#include "BKE_main.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
@@ -109,7 +109,8 @@ static bool keyingset_poll_activePath_edit(bContext *C)
static int add_default_keyingset_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- short flag = 0, keyingflag = 0;
+ eKS_Settings flag = 0;
+ eInsertKeyFlags keyingflag = 0;
/* validate flags
* - absolute KeyingSets should be created by default
@@ -117,7 +118,7 @@ static int add_default_keyingset_exec(bContext *C, wmOperator *UNUSED(op))
flag |= KEYINGSET_ABSOLUTE;
/* 2nd arg is 0 to indicate that we don't want to include autokeying mode related settings */
- keyingflag = ANIM_get_keyframing_flags(scene, 0);
+ keyingflag = ANIM_get_keyframing_flags(scene, false);
/* call the API func, and set the active keyingset index */
BKE_keyingset_add(&scene->keyingsets, NULL, NULL, flag, keyingflag);
@@ -289,7 +290,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
PropertyRNA *prop = NULL;
PointerRNA ptr = {NULL};
char *path = NULL;
- short success = 0;
+ bool changed = false;
int index = 0, pflag = 0;
const bool all = RNA_boolean_get(op->ptr, "all");
@@ -304,14 +305,15 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
* - add a new one if it doesn't exist
*/
if (scene->active_keyingset == 0) {
- short flag = 0, keyingflag = 0;
+ eKS_Settings flag = 0;
+ eInsertKeyFlags keyingflag = 0;
/* validate flags
* - absolute KeyingSets should be created by default
*/
flag |= KEYINGSET_ABSOLUTE;
- keyingflag |= ANIM_get_keyframing_flags(scene, 0);
+ keyingflag |= ANIM_get_keyframing_flags(scene, false);
if (IS_AUTOKEY_FLAG(scene, XYZ2RGB)) {
keyingflag |= INSERTKEY_XYZ2RGB;
@@ -350,14 +352,14 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
/* add path to this setting */
BKE_keyingset_add_path(ks, ptr.owner_id, NULL, path, index, pflag, KSP_GROUP_KSNAME);
ks->active_path = BLI_listbase_count(&ks->paths);
- success = 1;
+ changed = true;
/* free the temp path created */
MEM_freeN(path);
}
}
- if (success) {
+ if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
@@ -365,7 +367,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
BKE_reportf(op->reports, RPT_INFO, "Property added to Keying Set: '%s'", ks->name);
}
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyingset_button_add(wmOperatorType *ot)
@@ -395,7 +397,7 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
PropertyRNA *prop = NULL;
PointerRNA ptr = {NULL};
char *path = NULL;
- short success = 0;
+ bool changed = false;
int index = 0;
/* try to add to keyingset using property retrieved from UI */
@@ -431,7 +433,7 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
if (ksp) {
BKE_keyingset_free_path(ks, ksp);
- success = 1;
+ changed = true;
}
/* free temp path used */
@@ -439,7 +441,7 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
}
}
- if (success) {
+ if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
@@ -447,7 +449,7 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_INFO, "Property removed from Keying Set");
}
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void ANIM_OT_keyingset_button_remove(wmOperatorType *ot)
@@ -644,8 +646,8 @@ void ANIM_keyingset_infos_exit(void)
next = ksi->next;
/* free extra RNA data, and remove from list */
- if (ksi->ext.free) {
- ksi->ext.free(ksi->ext.data);
+ if (ksi->rna_ext.free) {
+ ksi->rna_ext.free(ksi->rna_ext.data);
}
BLI_freelinkN(&keyingset_type_infos, ksi);
}
@@ -671,7 +673,7 @@ bool ANIM_keyingset_find_id(KeyingSet *ks, ID *id)
/* Getters for Active/Indices ----------------------------- */
/* Get the active Keying Set for the Scene provided */
-KeyingSet *ANIM_scene_get_active_keyingset(Scene *scene)
+KeyingSet *ANIM_scene_get_active_keyingset(const Scene *scene)
{
/* if no scene, we've got no hope of finding the Keying Set */
if (scene == NULL) {
@@ -726,7 +728,7 @@ int ANIM_scene_get_keyingset_index(Scene *scene, KeyingSet *ks)
}
/* Get Keying Set to use for Auto-Keyframing some transforms */
-KeyingSet *ANIM_get_keyingset_for_autokeying(Scene *scene, const char *transformKSName)
+KeyingSet *ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName)
{
/* get KeyingSet to use
* - use the active KeyingSet if defined (and user wants to use it for all autokeying),
@@ -931,14 +933,15 @@ void ANIM_relative_keyingset_add_source(ListBase *dsources, ID *id, StructRNA *s
/* KeyingSet Operations (Insert/Delete Keyframes) ------------ */
-/* Given a KeyingSet and context info, validate Keying Set's paths.
+/**
+ * Given a KeyingSet and context info, validate Keying Set's paths.
* This is only really necessary with relative/built-in KeyingSets
* where their list of paths is dynamically generated based on the
* current context info.
*
* Returns 0 if succeeded, otherwise an error code: eModifyKey_Returns
*/
-short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
+eModifyKey_Returns ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
{
/* sanity check */
if (ks == NULL) {
@@ -990,12 +993,12 @@ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
}
/* Determine which keying flags apply based on the override flags */
-static short keyingset_apply_keying_flags(const short base_flags,
- const short overrides,
- const short own_flags)
+static eInsertKeyFlags keyingset_apply_keying_flags(const eInsertKeyFlags base_flags,
+ const eInsertKeyFlags overrides,
+ const eInsertKeyFlags own_flags)
{
/* Pass through all flags by default (i.e. even not explicitly listed ones). */
- short result = base_flags;
+ eInsertKeyFlags result = base_flags;
/* The logic for whether a keying flag applies is as follows:
* - If the flag in question is set in "overrides", that means that the
@@ -1025,7 +1028,9 @@ static short keyingset_apply_keying_flags(const short base_flags,
* Given a KeyingSet and context info (if required),
* modify keyframes for the channels specified by the KeyingSet.
* This takes into account many of the different combinations of using KeyingSets.
- * Returns the number of channels that keyframes were added to
+ *
+ * \returns the number of channels that key-frames were added or
+ * an #eModifyKey_Returns value (always a negative number).
*/
int ANIM_apply_keyingset(
bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
@@ -1035,9 +1040,10 @@ int ANIM_apply_keyingset(
ReportList *reports = CTX_wm_reports(C);
KS_Path *ksp;
ListBase nla_cache = {NULL, NULL};
- const short base_kflags = ANIM_get_keyframing_flags(scene, 1);
+ const eInsertKeyFlags base_kflags = ANIM_get_keyframing_flags(scene, true);
const char *groupname = NULL;
- short kflag = 0, success = 0;
+ eInsertKeyFlags kflag = 0;
+ int num_channels = 0;
char keytype = scene->toolsettings->keyframe_type;
/* sanity checks */
@@ -1055,17 +1061,19 @@ int ANIM_apply_keyingset(
}
/* if relative Keying Sets, poll and build up the paths */
- success = ANIM_validate_keyingset(C, dsources, ks);
-
- if (success != 0) {
- /* return error code if failed */
- return success;
+ {
+ const eModifyKey_Returns error = ANIM_validate_keyingset(C, dsources, ks);
+ if (error != 0) {
+ BLI_assert(error < 0);
+ /* return error code if failed */
+ return error;
+ }
}
/* apply the paths as specified in the KeyingSet now */
for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
int arraylen, i;
- short kflag2;
+ eInsertKeyFlags kflag2;
/* skip path if no ID pointer is specified */
if (ksp->id == NULL) {
@@ -1123,21 +1131,20 @@ int ANIM_apply_keyingset(
for (; i < arraylen; i++) {
/* action to take depends on mode */
if (mode == MODIFYKEY_MODE_INSERT) {
- success += insert_keyframe(bmain,
- reports,
- ksp->id,
- act,
- groupname,
- ksp->rna_path,
- i,
- cfra,
- keytype,
- &nla_cache,
- kflag2);
+ num_channels += insert_keyframe(bmain,
+ reports,
+ ksp->id,
+ act,
+ groupname,
+ ksp->rna_path,
+ i,
+ cfra,
+ keytype,
+ &nla_cache,
+ kflag2);
}
else if (mode == MODIFYKEY_MODE_DELETE) {
- success += delete_keyframe(
- bmain, reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2);
+ num_channels += delete_keyframe(bmain, reports, ksp->id, act, ksp->rna_path, i, cfra);
}
}
@@ -1163,7 +1170,8 @@ int ANIM_apply_keyingset(
BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
/* return the number of channels successfully affected */
- return success;
+ BLI_assert(num_channels >= 0);
+ return num_channels;
}
/* ************************************************** */
diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c
index ae489fb5233..7679995d9a4 100644
--- a/source/blender/editors/animation/time_scrub_ui.c
+++ b/source/blender/editors/animation/time_scrub_ui.c
@@ -34,23 +34,23 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
-#include "UI_view2d.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "DNA_scene_types.h"
-#include "BLI_rect.h"
#include "BLI_math.h"
+#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_timecode.h"
#include "RNA_access.h"
-static void get_time_scrub_region_rect(const ARegion *ar, rcti *rect)
+static void get_time_scrub_region_rect(const ARegion *region, rcti *rect)
{
rect->xmin = 0;
- rect->xmax = ar->winx;
- rect->ymax = ar->winy;
+ rect->xmax = region->winx;
+ rect->ymax = region->winy;
rect->ymin = rect->ymax - UI_TIME_SCRUB_MARGIN_Y;
}
@@ -95,7 +95,7 @@ static void draw_current_frame(const Scene *scene,
int current_frame)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- const unsigned char color[] = {255, 255, 255, 255};
+ const uchar color[] = {255, 255, 255, 255};
int frame_x = UI_view2d_view_to_region_x(v2d, current_frame);
char frame_str[64];
@@ -109,14 +109,14 @@ static void draw_current_frame(const Scene *scene,
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_3fvAlpha(true,
- frame_x - box_width / 2 + U.pixelsize / 2,
- scrub_region_rect->ymin + box_padding,
- frame_x + box_width / 2 + U.pixelsize / 2,
- scrub_region_rect->ymax - box_padding,
- 4 * UI_DPI_FAC,
- bg_color,
- 1.0f);
+ UI_draw_roundbox_3fv_alpha(true,
+ frame_x - box_width / 2 + U.pixelsize / 2,
+ scrub_region_rect->ymin + box_padding,
+ frame_x + box_width / 2 + U.pixelsize / 2,
+ scrub_region_rect->ymax - box_padding,
+ 4 * UI_DPI_FAC,
+ bg_color,
+ 1.0f);
UI_GetThemeColorShade4fv(TH_CFRAME, 5, bg_color);
UI_draw_roundbox_aa(false,
@@ -134,18 +134,18 @@ static void draw_current_frame(const Scene *scene,
color);
}
-void ED_time_scrub_draw(const ARegion *ar,
+void ED_time_scrub_draw(const ARegion *region,
const Scene *scene,
bool display_seconds,
bool discrete_frames)
{
- const View2D *v2d = &ar->v2d;
+ const View2D *v2d = &region->v2d;
GPU_matrix_push_projection();
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
rcti scrub_region_rect;
- get_time_scrub_region_rect(ar, &scrub_region_rect);
+ get_time_scrub_region_rect(region, &scrub_region_rect);
draw_background(&scrub_region_rect);
@@ -153,11 +153,11 @@ void ED_time_scrub_draw(const ARegion *ar,
numbers_rect.ymin = get_centered_text_y(&scrub_region_rect) - 4 * UI_DPI_FAC;
if (discrete_frames) {
UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT);
+ region, v2d, &numbers_rect, scene, display_seconds, TH_TEXT);
}
else {
UI_view2d_draw_scale_x__frames_or_seconds(
- ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT);
+ region, v2d, &numbers_rect, scene, display_seconds, TH_TEXT);
}
draw_current_frame(scene, display_seconds, v2d, &scrub_region_rect, scene->r.cfra);
@@ -165,23 +165,23 @@ void ED_time_scrub_draw(const ARegion *ar,
GPU_matrix_pop_projection();
}
-bool ED_time_scrub_event_in_region(const ARegion *ar, const wmEvent *event)
+bool ED_time_scrub_event_in_region(const ARegion *region, const wmEvent *event)
{
- rcti rect = ar->winrct;
+ rcti rect = region->winrct;
rect.ymin = rect.ymax - UI_TIME_SCRUB_MARGIN_Y;
return BLI_rcti_isect_pt(&rect, event->x, event->y);
}
-void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet)
+void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *region, bDopeSheet *dopesheet)
{
GPU_matrix_push_projection();
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
rcti rect;
rect.xmin = 0;
- rect.xmax = ar->winx;
- rect.ymin = ar->winy - UI_TIME_SCRUB_MARGIN_Y;
- rect.ymax = ar->winy;
+ rect.xmax = region->winx;
+ rect.ymin = region->winy - UI_TIME_SCRUB_MARGIN_Y;
+ rect.ymax = region->winy;
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -189,7 +189,7 @@ void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *ar, bDopeShee
immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
immUnbindProgram();
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
PointerRNA ptr;
RNA_pointer_create(&CTX_wm_screen(C)->id, &RNA_DopeSheet, dopesheet, &ptr);
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 7a14de2b240..d941f8ce95f 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -22,6 +22,7 @@
* \ingroup edarmature
*/
+#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_object_types.h"
@@ -30,16 +31,20 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLI_ghash.h"
+#include "BLI_math.h"
#include "BLI_string_utils.h"
#include "BKE_action.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
-#include "BKE_idprop.h"
#include "BKE_deform.h"
+#include "BKE_fcurve.h"
+#include "BKE_idprop.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -48,6 +53,7 @@
#include "WM_types.h"
#include "ED_armature.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -217,6 +223,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
DEG_id_tag_update(&obedit->id, ID_RECALC_SELECT);
+ ED_outliner_select_sync_from_edit_bone_tag(C);
return OPERATOR_FINISHED;
}
@@ -228,13 +235,13 @@ static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEv
/* temporarily change 3d cursor position */
Scene *scene;
- ARegion *ar;
+ ARegion *region;
View3D *v3d;
float tvec[3], oldcurs[3], mval_f[2];
int retv;
scene = CTX_data_scene(C);
- ar = CTX_wm_region(C);
+ region = CTX_wm_region(C);
v3d = CTX_wm_view3d(C);
View3DCursor *cursor = &scene->cursor;
@@ -242,7 +249,7 @@ static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEv
copy_v3_v3(oldcurs, cursor->location);
copy_v2fl_v2i(mval_f, event->mval);
- ED_view3d_win_to_3d(v3d, ar, cursor->location, mval_f, tvec);
+ ED_view3d_win_to_3d(v3d, region, cursor->location, mval_f, tvec);
copy_v3_v3(cursor->location, tvec);
/* extrude to the where new cursor is and store the operation result */
@@ -341,7 +348,7 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
GHash *name_map = BLI_ghash_str_new(__func__);
- for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) {
+ LISTBASE_FOREACH (EditBone *, ebone_src, editbones) {
EditBone *ebone_dst = ebone_src->temp.ebone;
if (!ebone_dst) {
ebone_dst = ED_armature_ebone_get_mirrored(editbones, ebone_src);
@@ -351,7 +358,7 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
}
}
- for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) {
+ LISTBASE_FOREACH (EditBone *, ebone_src, editbones) {
EditBone *ebone_dst = ebone_src->temp.ebone;
if (ebone_dst) {
bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name);
@@ -375,25 +382,20 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
BLI_ghash_free(name_map, NULL, NULL);
}
-/*
- * Note: When duplicating cross objects, editbones here is the list of bones
- * from the SOURCE object but ob is the DESTINATION object
- * */
-void updateDuplicateSubtargetObjects(EditBone *dupBone,
+static void updateDuplicateSubtarget(EditBone *dup_bone,
ListBase *editbones,
- Object *src_ob,
- Object *dst_ob)
+ Object *ob,
+ bool lookup_mirror_subtarget)
{
- /* If an edit bone has been duplicated, lets
- * update it's constraints if the subtarget
- * they point to has also been duplicated
+ /* If an edit bone has been duplicated, lets update it's constraints if the
+ * subtarget they point to has also been duplicated.
*/
EditBone *oldtarget, *newtarget;
bPoseChannel *pchan;
bConstraint *curcon;
ListBase *conlist;
- if ((pchan = BKE_pose_channel_verify(dst_ob->pose, dupBone->name))) {
+ if ((pchan = BKE_pose_channel_verify(ob->pose, dup_bone->name))) {
if ((conlist = &pchan->constraints)) {
for (curcon = conlist->first; curcon; curcon = curcon->next) {
/* does this constraint have a subtarget in
@@ -407,8 +409,7 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone,
cti->get_constraint_targets(curcon, &targets);
for (ct = targets.first; ct; ct = ct->next) {
- if ((ct->tar == src_ob) && (ct->subtarget[0])) {
- ct->tar = dst_ob; /* update target */
+ if ((ct->tar == ob) && (ct->subtarget[0])) {
oldtarget = get_named_editbone(editbones, ct->subtarget);
if (oldtarget) {
/* was the subtarget bone duplicated too? If
@@ -419,6 +420,17 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone,
newtarget = oldtarget->temp.ebone;
BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
}
+ else if (lookup_mirror_subtarget) {
+ /* The subtarget was not selected for duplication, try to see if a mirror bone of
+ * the current target exists */
+ char name_flip[MAXBONENAME];
+
+ BLI_string_flip_side_name(name_flip, oldtarget->name, false, sizeof(name_flip));
+ newtarget = get_named_editbone(editbones, name_flip);
+ if (newtarget) {
+ BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
+ }
+ }
}
}
}
@@ -432,32 +444,434 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone,
}
}
-void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob)
+static void updateDuplicateActionConstraintSettings(EditBone *dup_bone,
+ EditBone *orig_bone,
+ Object *ob,
+ bConstraint *curcon)
{
- updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob);
+ bActionConstraint *act_con = (bActionConstraint *)curcon->data;
+ bAction *act = (bAction *)act_con->act;
+
+ float mat[4][4];
+
+ unit_m4(mat);
+ bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, act_con->subtarget);
+ BKE_constraint_mat_convertspace(
+ ob, target_pchan, mat, curcon->tarspace, CONSTRAINT_SPACE_LOCAL, false);
+
+ float max_axis_val = 0;
+ int max_axis = 0;
+ /* Which axis represents X now. IE, which axis defines the mirror plane. */
+ for (int i = 0; i < 3; i++) {
+ float cur_val = fabsf(mat[0][i]);
+ if (cur_val > max_axis_val) {
+ max_axis = i;
+ max_axis_val = cur_val;
+ }
+ }
+
+ /* data->type is mapped as follows for backwards compatibility:
+ * 00,01,02 - rotation (it used to be like this)
+ * 10,11,12 - scaling
+ * 20,21,22 - location
+ */
+ /* Mirror the target range */
+ if (act_con->type < 10 && act_con->type != max_axis) {
+ /* Y or Z rotation */
+ act_con->min = -act_con->min;
+ act_con->max = -act_con->max;
+ }
+ else if (act_con->type == max_axis + 10) {
+ /* X scaling */
+ }
+ else if (act_con->type == max_axis + 20) {
+ /* X location */
+ float imat[4][4];
+
+ invert_m4_m4(imat, mat);
+
+ float min_vec[3], max_vec[3];
+
+ zero_v3(min_vec);
+ zero_v3(max_vec);
+
+ min_vec[0] = act_con->min;
+ max_vec[0] = act_con->max;
+
+ /* convert values into local object space */
+ mul_m4_v3(mat, min_vec);
+ mul_m4_v3(mat, max_vec);
+
+ min_vec[0] *= -1;
+ max_vec[0] *= -1;
+
+ /* convert back to the settings space */
+ mul_m4_v3(imat, min_vec);
+ mul_m4_v3(imat, max_vec);
+
+ act_con->min = min_vec[0];
+ act_con->max = max_vec[0];
+ }
+
+ /* See if there is any channels that uses this bone */
+ ListBase ani_curves;
+ BLI_listbase_clear(&ani_curves);
+ if (list_find_data_fcurves(&ani_curves, &act->curves, "pose.bones[", orig_bone->name)) {
+ /* Create a copy and mirror the animation */
+ for (LinkData *ld = ani_curves.first; ld; ld = ld->next) {
+ FCurve *old_curve = ld->data;
+ FCurve *new_curve = copy_fcurve(old_curve);
+ bActionGroup *agrp;
+
+ char *old_path = new_curve->rna_path;
+
+ new_curve->rna_path = BLI_str_replaceN(old_path, orig_bone->name, dup_bone->name);
+ MEM_freeN(old_path);
+
+ /* Flip the animation */
+ int i;
+ BezTriple *bezt;
+ for (i = 0, bezt = new_curve->bezt; i < new_curve->totvert; i++, bezt++) {
+ const size_t slength = strlen(new_curve->rna_path);
+ bool flip = false;
+ if (BLI_strn_endswith(new_curve->rna_path, "location", slength) &&
+ new_curve->array_index == 0) {
+ flip = true;
+ }
+ else if (BLI_strn_endswith(new_curve->rna_path, "rotation_quaternion", slength) &&
+ ELEM(new_curve->array_index, 2, 3)) {
+ flip = true;
+ }
+ else if (BLI_strn_endswith(new_curve->rna_path, "rotation_euler", slength) &&
+ ELEM(new_curve->array_index, 1, 2)) {
+ flip = true;
+ }
+ else if (BLI_strn_endswith(new_curve->rna_path, "rotation_axis_angle", slength) &&
+ ELEM(new_curve->array_index, 2, 3)) {
+ flip = true;
+ }
+
+ if (flip) {
+ bezt->vec[0][1] *= -1;
+ bezt->vec[1][1] *= -1;
+ bezt->vec[2][1] *= -1;
+ }
+ }
+
+ /* Make sure that a action group name for the new bone exists */
+ agrp = BKE_action_group_find_name(act, dup_bone->name);
+
+ if (agrp == NULL) {
+ agrp = action_groups_add_new(act, dup_bone->name);
+ }
+ BLI_assert(agrp != NULL);
+ action_groups_add_channel(act, agrp, new_curve);
+ }
+ }
+ BLI_freelistN(&ani_curves);
+
+ /* Make deps graph aware of our changes */
+ DEG_id_tag_update(&act->id, ID_RECALC_ANIMATION_NO_FLUSH);
}
-EditBone *duplicateEditBoneObjects(
- EditBone *curBone, const char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
+static void updateDuplicateKinematicConstraintSettings(bConstraint *curcon)
{
- EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
+ /* IK constraint */
+ bKinematicConstraint *ik = (bKinematicConstraint *)curcon->data;
+ ik->poleangle = -M_PI - ik->poleangle;
+ /* Wrap the angle to the +/-180.0f range (default soft limit of the input boxes). */
+ ik->poleangle = angle_wrap_rad(ik->poleangle);
+}
- /* Copy data from old bone to new bone */
- memcpy(eBone, curBone, sizeof(EditBone));
+static void updateDuplicateLocRotConstraintSettings(Object *ob,
+ bPoseChannel *pchan,
+ bConstraint *curcon)
+{
+ /* This code assumes that bRotLimitConstraint and bLocLimitConstraint have the same fields in
+ * the same memory locations. */
+ BLI_assert(sizeof(bLocLimitConstraint) == sizeof(bRotLimitConstraint));
- curBone->temp.ebone = eBone;
- eBone->temp.ebone = curBone;
+ bRotLimitConstraint *limit = (bRotLimitConstraint *)curcon->data;
+ float local_mat[4][4], imat[4][4];
- if (name != NULL) {
- BLI_strncpy(eBone->name, name, sizeof(eBone->name));
+ float min_vec[3], max_vec[3];
+
+ min_vec[0] = limit->xmin;
+ min_vec[1] = limit->ymin;
+ min_vec[2] = limit->zmin;
+
+ max_vec[0] = limit->xmax;
+ max_vec[1] = limit->ymax;
+ max_vec[2] = limit->zmax;
+
+ unit_m4(local_mat);
+
+ BKE_constraint_mat_convertspace(
+ ob, pchan, local_mat, curcon->ownspace, CONSTRAINT_SPACE_LOCAL, false);
+
+ if (curcon->type == CONSTRAINT_TYPE_ROTLIMIT) {
+ /* Zero out any location translation */
+ local_mat[3][0] = local_mat[3][1] = local_mat[3][2] = 0;
+ }
+
+ invert_m4_m4(imat, local_mat);
+ /* convert values into local object space */
+ mul_m4_v3(local_mat, min_vec);
+ mul_m4_v3(local_mat, max_vec);
+
+ if (curcon->type == CONSTRAINT_TYPE_ROTLIMIT) {
+ float min_copy[3];
+
+ copy_v3_v3(min_copy, min_vec);
+
+ min_vec[1] = max_vec[1] * -1;
+ min_vec[2] = max_vec[2] * -1;
+
+ max_vec[1] = min_copy[1] * -1;
+ max_vec[2] = min_copy[2] * -1;
+ }
+ else {
+ float min_x_copy = min_vec[0];
+
+ min_vec[0] = max_vec[0] * -1;
+ max_vec[0] = min_x_copy * -1;
+ }
+
+ /* convert back to the settings space */
+ mul_m4_v3(imat, min_vec);
+ mul_m4_v3(imat, max_vec);
+
+ limit->xmin = min_vec[0];
+ limit->ymin = min_vec[1];
+ limit->zmin = min_vec[2];
+
+ limit->xmax = max_vec[0];
+ limit->ymax = max_vec[1];
+ limit->zmax = max_vec[2];
+}
+
+static void updateDuplicateTransformConstraintSettings(Object *ob,
+ bPoseChannel *pchan,
+ bConstraint *curcon)
+{
+ bTransformConstraint *trans = (bTransformConstraint *)curcon->data;
+
+ float target_mat[4][4], own_mat[4][4], imat[4][4];
+
+ unit_m4(own_mat);
+ BKE_constraint_mat_convertspace(
+ ob, pchan, own_mat, curcon->ownspace, CONSTRAINT_SPACE_LOCAL, false);
+
+ /* ###Source map mirroring### */
+ float old_min, old_max;
+
+ /* Source location */
+ invert_m4_m4(imat, own_mat);
+
+ /* convert values into local object space */
+ mul_m4_v3(own_mat, trans->from_min);
+ mul_m4_v3(own_mat, trans->from_max);
+
+ old_min = trans->from_min[0];
+ old_max = trans->from_max[0];
+
+ trans->from_min[0] = -old_max;
+ trans->from_max[0] = -old_min;
+
+ /* convert back to the settings space */
+ mul_m4_v3(imat, trans->from_min);
+ mul_m4_v3(imat, trans->from_max);
+
+ /* Source rotation */
+
+ /* Zero out any location translation */
+ own_mat[3][0] = own_mat[3][1] = own_mat[3][2] = 0;
+
+ invert_m4_m4(imat, own_mat);
+
+ /* convert values into local object space */
+ mul_m4_v3(own_mat, trans->from_min_rot);
+ mul_m4_v3(own_mat, trans->from_max_rot);
+
+ old_min = trans->from_min_rot[1];
+ old_max = trans->from_max_rot[1];
+
+ trans->from_min_rot[1] = old_max * -1;
+ trans->from_max_rot[1] = old_min * -1;
+
+ old_min = trans->from_min_rot[2];
+ old_max = trans->from_max_rot[2];
+
+ trans->from_min_rot[2] = old_max * -1;
+ trans->from_max_rot[2] = old_min * -1;
+
+ /* convert back to the settings space */
+ mul_m4_v3(imat, trans->from_min_rot);
+ mul_m4_v3(imat, trans->from_max_rot);
+
+ /* Source scale does not require any mirroring */
+
+ /* ###Destination map mirroring### */
+ float temp_vec[3];
+ float imat_rot[4][4];
+
+ bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, trans->subtarget);
+ unit_m4(target_mat);
+ BKE_constraint_mat_convertspace(
+ ob, target_pchan, target_mat, curcon->tarspace, CONSTRAINT_SPACE_LOCAL, false);
+
+ invert_m4_m4(imat, target_mat);
+ /* convert values into local object space */
+ mul_m4_v3(target_mat, trans->to_min);
+ mul_m4_v3(target_mat, trans->to_max);
+ mul_m4_v3(target_mat, trans->to_min_scale);
+ mul_m4_v3(target_mat, trans->to_max_scale);
+
+ /* Zero out any location translation */
+ target_mat[3][0] = target_mat[3][1] = target_mat[3][2] = 0;
+ invert_m4_m4(imat_rot, target_mat);
+
+ mul_m4_v3(target_mat, trans->to_min_rot);
+ mul_m4_v3(target_mat, trans->to_max_rot);
+
+ /* TODO(sebpa): This does not support euler order, but doing so will make this way more complex.
+ * For now we have decided to not support all corner cases and advanced setups. */
+
+ /* Helper variables to denote the axis in trans->map */
+ const char X = 0;
+ const char Y = 1;
+ const char Z = 2;
+
+ switch (trans->to) {
+ case TRANS_SCALE:
+ copy_v3_v3(temp_vec, trans->to_max_scale);
+
+ for (int i = 0; i < 3; i++) {
+ if ((trans->from == TRANS_LOCATION && trans->map[i] == X) ||
+ (trans->from == TRANS_ROTATION && trans->map[i] != X)) {
+ /* X Loc to X/Y/Z Scale: Min/Max Flipped */
+ /* Y Rot to X/Y/Z Scale: Min/Max Flipped */
+ /* Z Rot to X/Y/Z Scale: Min/Max Flipped */
+ trans->to_max_scale[i] = trans->to_min_scale[i];
+ trans->to_min_scale[i] = temp_vec[i];
+ }
+ }
+ break;
+ case TRANS_LOCATION:
+ /* Invert the X location */
+ trans->to_min[0] *= -1;
+ trans->to_max[0] *= -1;
+
+ copy_v3_v3(temp_vec, trans->to_max);
+
+ for (int i = 0; i < 3; i++) {
+ if ((trans->from == TRANS_LOCATION && trans->map[i] == X) ||
+ (trans->from == TRANS_ROTATION && trans->map[i] != X)) {
+ /* X Loc to X/Y/Z Loc: Min/Max Flipped (and Inverted)
+ * Y Rot to X/Y/Z Loc: Min/Max Flipped
+ * Z Rot to X/Y/Z Loc: Min/Max Flipped */
+ trans->to_max[i] = trans->to_min[i];
+ trans->to_min[i] = temp_vec[i];
+ }
+ }
+ break;
+ case TRANS_ROTATION:
+ /* Invert the Z rotation */
+ trans->to_min_rot[2] *= -1;
+ trans->to_max_rot[2] *= -1;
+
+ if ((trans->from == TRANS_LOCATION && trans->map[1] != X) ||
+ (trans->from == TRANS_ROTATION && trans->map[1] != Y) || trans->from == TRANS_SCALE) {
+ /* Invert the Y rotation */
+ trans->to_min_rot[1] *= -1;
+ trans->to_max_rot[1] *= -1;
+ }
+
+ copy_v3_v3(temp_vec, trans->to_max_rot);
+
+ for (int i = 0; i < 3; i++) {
+ if ((trans->from == TRANS_LOCATION && trans->map[i] == X && i != 1) ||
+ (trans->from == TRANS_ROTATION && trans->map[i] == Y && i != 1) ||
+ (trans->from == TRANS_ROTATION && trans->map[i] == Z)) {
+ /* X Loc to X/Z Rot: Flipped
+ * Y Rot to X/Z Rot: Flipped
+ * Z Rot to X/Y/Z rot: Flipped */
+ trans->to_max_rot[i] = trans->to_min_rot[i];
+ trans->to_min_rot[i] = temp_vec[i];
+ }
+ }
+ break;
}
+ /* convert back to the settings space */
+ mul_m4_v3(imat, trans->to_min);
+ mul_m4_v3(imat, trans->to_max);
+ mul_m4_v3(imat_rot, trans->to_min_rot);
+ mul_m4_v3(imat_rot, trans->to_max_rot);
+ mul_m4_v3(imat, trans->to_min_scale);
+ mul_m4_v3(imat, trans->to_max_scale);
+}
- ED_armature_ebone_unique_name(editbones, eBone->name, NULL);
- BLI_addtail(editbones, eBone);
+static void updateDuplicateConstraintSettings(EditBone *dup_bone, EditBone *orig_bone, Object *ob)
+{
+ /* If an edit bone has been duplicated, lets update it's constraints if the
+ * subtarget they point to has also been duplicated.
+ */
+ bPoseChannel *pchan;
+ bConstraint *curcon;
+ ListBase *conlist;
+ if ((pchan = BKE_pose_channel_verify(ob->pose, dup_bone->name)) == NULL ||
+ (conlist = &pchan->constraints) == NULL) {
+ return;
+ }
+
+ for (curcon = conlist->first; curcon; curcon = curcon->next) {
+ switch (curcon->type) {
+ case CONSTRAINT_TYPE_ACTION:
+ updateDuplicateActionConstraintSettings(dup_bone, orig_bone, ob, curcon);
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ updateDuplicateKinematicConstraintSettings(curcon);
+ break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ updateDuplicateLocRotConstraintSettings(ob, pchan, curcon);
+ break;
+ case CONSTRAINT_TYPE_TRANSFORM:
+ updateDuplicateTransformConstraintSettings(ob, pchan, curcon);
+ break;
+ }
+ }
+}
+
+static void updateDuplicateCustomBoneShapes(bContext *C, EditBone *dup_bone, Object *ob)
+{
+ if (ob->pose == NULL) {
+ return;
+ }
+ bPoseChannel *pchan;
+ pchan = BKE_pose_channel_verify(ob->pose, dup_bone->name);
+
+ if (pchan->custom != NULL) {
+ Main *bmain = CTX_data_main(C);
+ char name_flip[MAX_ID_NAME - 2];
+
+ /* Skip the first two chars in the object name as those are used to store object type */
+ BLI_string_flip_side_name(name_flip, pchan->custom->id.name + 2, false, sizeof(name_flip));
+ Object *shape_ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name_flip);
+
+ if (shape_ob != NULL) {
+ /* A flipped shape object exists, use it! */
+ pchan->custom = shape_ob;
+ }
+ }
+}
+
+static void copy_pchan(EditBone *src_bone, EditBone *dst_bone, Object *src_ob, Object *dst_ob)
+{
/* copy the ID property */
- if (curBone->prop) {
- eBone->prop = IDP_CopyProperty(curBone->prop);
+ if (src_bone->prop) {
+ dst_bone->prop = IDP_CopyProperty(src_bone->prop);
}
/* Lets duplicate the list of constraints that the
@@ -466,25 +880,46 @@ EditBone *duplicateEditBoneObjects(
if (src_ob->pose) {
bPoseChannel *chanold, *channew;
- chanold = BKE_pose_channel_verify(src_ob->pose, curBone->name);
+ chanold = BKE_pose_channel_verify(src_ob->pose, src_bone->name);
if (chanold) {
/* WARNING: this creates a new posechannel, but there will not be an attached bone
* yet as the new bones created here are still 'EditBones' not 'Bones'.
*/
- channew = BKE_pose_channel_verify(dst_ob->pose, eBone->name);
+ channew = BKE_pose_channel_verify(dst_ob->pose, dst_bone->name);
if (channew) {
BKE_pose_channel_copy_data(channew, chanold);
}
}
}
+}
- return eBone;
+EditBone *duplicateEditBoneObjects(
+ EditBone *cur_bone, const char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
+{
+ EditBone *e_bone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
+
+ /* Copy data from old bone to new bone */
+ memcpy(e_bone, cur_bone, sizeof(EditBone));
+
+ cur_bone->temp.ebone = e_bone;
+ e_bone->temp.ebone = cur_bone;
+
+ if (name != NULL) {
+ BLI_strncpy(e_bone->name, name, sizeof(e_bone->name));
+ }
+
+ ED_armature_ebone_unique_name(editbones, e_bone->name, NULL);
+ BLI_addtail(editbones, e_bone);
+
+ copy_pchan(cur_bone, e_bone, src_ob, dst_ob);
+
+ return e_bone;
}
-EditBone *duplicateEditBone(EditBone *curBone, const char *name, ListBase *editbones, Object *ob)
+EditBone *duplicateEditBone(EditBone *cur_bone, const char *name, ListBase *editbones, Object *ob)
{
- return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
+ return duplicateEditBoneObjects(cur_bone, name, editbones, ob, ob);
}
static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
@@ -538,8 +973,8 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
BLI_string_flip_side_name(
new_bone_name_buff, ebone_iter->name, false, sizeof(new_bone_name_buff));
- /* Only use flipped name if not yet in use. Otherwise we'd get again inconsistent namings
- * (different numbers), better keep default behavior in this case. */
+ /* Only use flipped name if not yet in use. Otherwise we'd get again inconsistent
+ * namings (different numbers), better keep default behavior in this case. */
if (ED_armature_ebone_find_name(arm->edbo, new_bone_name_buff) == NULL) {
new_bone_name = new_bone_name_buff;
}
@@ -567,13 +1002,13 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
}
else if (ebone_iter->parent->temp.ebone) {
/* If this bone has a parent that was duplicated,
- * Set the duplicate->parent to the curBone->parent->temp
+ * Set the duplicate->parent to the cur_bone->parent->temp
*/
ebone->parent = ebone_iter->parent->temp.ebone;
}
else {
/* If this bone has a parent that IS not selected,
- * Set the duplicate->parent to the curBone->parent
+ * Set the duplicate->parent to the cur_bone->parent
*/
ebone->parent = (EditBone *)ebone_iter->parent;
ebone->flag &= ~BONE_CONNECTED;
@@ -590,7 +1025,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
/* Lets try to fix any constraint subtargets that might
* have been duplicated
*/
- updateDuplicateSubtarget(ebone, arm->edbo, ob);
+ updateDuplicateSubtarget(ebone, arm->edbo, ob, false);
}
}
@@ -616,6 +1051,8 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
}
MEM_freeN(objects);
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+
return OPERATOR_FINISHED;
}
@@ -742,12 +1179,24 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
}
}
- /* Find the selected bones and duplicate them as needed, with mirrored name */
+ /* Find the selected bones and duplicate them as needed, with mirrored name. */
for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
ebone_iter = ebone_iter->next) {
- if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED) &&
- /* will be set if the mirror bone already exists (no need to make a new one) */
- (ebone_iter->temp.ebone == NULL)) {
+ if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
+ if (ebone_iter->temp.ebone != NULL) {
+ /* This will be set if the mirror bone already exists (no need to make a new one)
+ * but we do need to make sure that the 'pchan' settings (constraints etc)
+ * is synchronized. */
+ bPoseChannel *pchan;
+ /* Make sure we clean up the old data before overwriting it */
+ pchan = BKE_pose_channel_verify(obedit->pose, ebone_iter->temp.ebone->name);
+ BKE_pose_channel_free(pchan);
+ /* Sync pchan data */
+ copy_pchan(ebone_iter, ebone_iter->temp.ebone, obedit, obedit);
+ /* Sync scale mode */
+ ebone_iter->temp.ebone->inherit_scale_mode = ebone_iter->inherit_scale_mode;
+ continue;
+ }
char name_flip[MAXBONENAME];
BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
@@ -765,7 +1214,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
}
}
- /* Run through the list and fix the pointers */
+ /* Run through the list and fix the pointers. */
for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
ebone_iter = ebone_iter->next) {
if (ebone_iter->temp.ebone) {
@@ -793,7 +1242,12 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
* then we can assume the parent has no L/R but is a center bone.
* So just use the same parent for both.
*/
- ebone->flag &= ~BONE_CONNECTED;
+
+ if (ebone->head[axis] != 0.0f) {
+ /* The mirrored bone doesn't start on the mirror axis, so assume that this one should
+ * not be connected to the old parent */
+ ebone->flag &= ~BONE_CONNECTED;
+ }
}
ebone->parent = ebone_parent;
@@ -803,10 +1257,19 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
ebone->bbone_prev = get_symmetrized_bone(arm, ebone_iter->bbone_prev);
ebone->bbone_next = get_symmetrized_bone(arm, ebone_iter->bbone_next);
+ /* Sync bbone handle types */
+ ebone->bbone_prev_type = ebone_iter->bbone_prev_type;
+ ebone->bbone_next_type = ebone_iter->bbone_next_type;
+
/* Lets try to fix any constraint subtargets that might
* have been duplicated
*/
- updateDuplicateSubtarget(ebone, arm->edbo, obedit);
+ updateDuplicateSubtarget(ebone, arm->edbo, obedit, true);
+ /* Try to update constraint options so that they are mirrored as well
+ * (need to supply bone_iter as well in case we are working with existing bones) */
+ updateDuplicateConstraintSettings(ebone, ebone_iter, obedit);
+ /* Mirror bone shapes if possible */
+ updateDuplicateCustomBoneShapes(C, ebone, obedit);
}
}
@@ -1062,7 +1525,13 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
}
MEM_freeN(objects);
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ if (!changed_multi) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_extrude(wmOperatorType *ot)
@@ -1116,7 +1585,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
ED_armature_edit_deselect_all(obedit);
- /* Create a bone */
+ /* Create a bone. */
bone = ED_armature_ebone_add(obedit->data, name);
copy_v3_v3(bone->head, curs);
@@ -1133,6 +1602,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
DEG_id_tag_update(&obedit->id, ID_RECALC_SELECT);
+ ED_outliner_select_sync_from_edit_bone_tag(C);
return OPERATOR_FINISHED;
}
@@ -1223,6 +1693,7 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
DEG_id_tag_update(&obedit->id, ID_RECALC_SELECT);
+ ED_outliner_select_sync_from_edit_bone_tag(C);
return OPERATOR_FINISHED;
}
@@ -1232,7 +1703,7 @@ void ARMATURE_OT_subdivide(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "Subdivide Multi";
+ ot->name = "Subdivide";
ot->idname = "ARMATURE_OT_subdivide";
ot->description = "Break selected bones into chains of smaller bones";
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 4ca0cd117b6..a7a705a6202 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -34,18 +34,18 @@
#include "BLT_translation.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLI_ghash.h"
+#include "BLI_math.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
-#include "BKE_layer.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
-#include "BKE_report.h"
#include "BKE_object.h"
+#include "BKE_report.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -54,6 +54,7 @@
#include "WM_types.h"
#include "ED_armature.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -61,7 +62,10 @@
#include "armature_intern.h"
-/* ************************** Object Tools Exports ******************************* */
+/* -------------------------------------------------------------------- */
+/** \name Object Tools Public API
+ * \{ */
+
/* NOTE: these functions are exported to the Object module to be called from the tools there */
/**
@@ -178,7 +182,11 @@ void ED_armature_origin_set(
}
}
-/* ********************************* Roll ******************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bone Roll Calculate Operator
+ * \{ */
/* adjust bone roll to align Z axis with vector
* vec is in local space and is normalized
@@ -343,7 +351,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
sub_v3_v3v3(dir_a, ebone->tail, ebone->head);
normalize_v3(dir_a);
- /* find the first bone in the chane with a different direction */
+ /* find the first bone in the chain with a different direction */
do {
sub_v3_v3v3(dir_b, ebone_other->head, ebone_other->tail);
normalize_v3(dir_b);
@@ -492,7 +500,7 @@ static int armature_roll_clear_exec(bContext *C, wmOperator *op)
bArmature *arm = ob->data;
bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
/* Roll func is a callback which assumes that all is well. */
ebone->roll = roll;
@@ -501,7 +509,7 @@ static int armature_roll_clear_exec(bContext *C, wmOperator *op)
}
if (arm->flag & ARM_MIRROR_EDIT) {
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
@@ -549,7 +557,11 @@ void ARMATURE_OT_roll_clear(wmOperatorType *ot)
DEG2RADF(360.0f));
}
-/* ******************************** Chain-Based Tools ********************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Chain-Based Tool Utilities
+ * \{ */
/* temporary data-structure for merge/fill bones */
typedef struct EditBonePoint {
@@ -616,7 +628,11 @@ static void chains_find_tips(ListBase *edbo, ListBase *list)
}
}
-/* --------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Fill Operator
+ * \{ */
static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
{
@@ -871,216 +887,15 @@ void ARMATURE_OT_fill(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* --------------------- */
-
-/* this function merges between two bones, removes them and those in-between,
- * and adjusts the parent relationships for those in-between
- */
-static void bones_merge(
- Object *obedit, EditBone *start, EditBone *end, EditBone *endchild, ListBase *chains)
-{
- bArmature *arm = obedit->data;
- EditBone *ebo, *ebone, *newbone;
- LinkData *chain;
- float head[3], tail[3];
-
- /* check if same bone */
- if (start == end) {
- if (G.debug & G_DEBUG) {
- printf("Error: same bone!\n");
- printf("\tstart = %s, end = %s\n", start->name, end->name);
- }
- }
-
- /* step 1: add a new bone
- * - head = head/tail of start (default head)
- * - tail = head/tail of end (default tail)
- * - parent = parent of start
- */
- if ((start->flag & BONE_TIPSEL) && (start->flag & BONE_SELECTED) == 0) {
- copy_v3_v3(head, start->tail);
- }
- else {
- copy_v3_v3(head, start->head);
- }
- if ((end->flag & BONE_ROOTSEL) && (end->flag & BONE_SELECTED) == 0) {
- copy_v3_v3(tail, end->head);
- }
- else {
- copy_v3_v3(tail, end->tail);
- }
- newbone = add_points_bone(obedit, head, tail);
- newbone->parent = start->parent;
-
- /* TODO, copy more things to the new bone */
- newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_CYCLICOFFSET |
- BONE_NO_LOCAL_LOCATION | BONE_DONE);
-
- newbone->inherit_scale_mode = start->inherit_scale_mode;
-
- /* Step 2a: reparent any side chains which may be parented to any bone in the chain
- * of bones to merge - potentially several tips for side chains leading to some tree exist.
- */
- for (chain = chains->first; chain; chain = chain->next) {
- /* Traverse down chain until we hit the bottom or if we run into the tip of the chain of bones
- * we're merging (need to stop in this case to avoid corrupting this chain too!).
- */
- for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) {
- short found = 0;
-
- /* Check if this bone is parented to one in the merging chain
- * ! WATCHIT: must only go check until end of checking chain
- */
- for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) {
- /* side-chain found? --> remap parent to new bone, then we're done with this chain :) */
- if (ebone->parent == ebo) {
- ebone->parent = newbone;
- found = 1;
- break;
- }
- }
-
- /* carry on to the next tip now */
- if (found) {
- break;
- }
- }
- }
-
- /* step 2b: parent child of end to newbone (child from this chain) */
- if (endchild) {
- endchild->parent = newbone;
- }
-
- /* step 3: delete all bones between and including start and end */
- for (ebo = end; ebo; ebo = ebone) {
- ebone = (ebo == start) ? (NULL) : (ebo->parent);
- bone_free(arm, ebo);
- }
-
- newbone->flag |= (BONE_ROOTSEL | BONE_TIPSEL | BONE_SELECTED);
- ED_armature_edit_sync_selection(arm->edbo);
-}
-
-static int armature_merge_exec(bContext *C, wmOperator *op)
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const short type = RNA_enum_get(op->ptr, "type");
-
- 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);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- bArmature *arm = obedit->data;
-
- /* for now, there's only really one type of merging that's performed... */
- if (type == 1) {
- /* go down chains, merging bones */
- ListBase chains = {NULL, NULL};
- LinkData *chain, *nchain;
- EditBone *ebo;
-
- armature_tag_select_mirrored(arm);
-
- /* get chains (ends on chains) */
- chains_find_tips(arm->edbo, &chains);
- if (BLI_listbase_is_empty(&chains)) {
- continue;
- }
-
- /* each 'chain' is the last bone in the chain (with no children) */
- for (chain = chains.first; chain; chain = nchain) {
- EditBone *bstart = NULL, *bend = NULL;
- EditBone *bchild = NULL, *child = NULL;
-
- /* temporarily remove chain from list of chains */
- nchain = chain->next;
- BLI_remlink(&chains, chain);
-
- /* only consider bones that are visible and selected */
- for (ebo = chain->data; ebo; child = ebo, ebo = ebo->parent) {
- /* check if visible + selected */
- if (EBONE_VISIBLE(arm, ebo) && ((ebo->flag & BONE_CONNECTED) || (ebo->parent == NULL)) &&
- (ebo->flag & BONE_SELECTED)) {
- /* set either end or start (end gets priority, unless it is already set) */
- if (bend == NULL) {
- bend = ebo;
- bchild = child;
- }
- else {
- bstart = ebo;
- }
- }
- else {
- /* chain is broken... merge any continuous segments then clear */
- if (bstart && bend) {
- bones_merge(obedit, bstart, bend, bchild, &chains);
- }
-
- bstart = NULL;
- bend = NULL;
- bchild = NULL;
- }
- }
-
- /* merge from bstart to bend if something not merged */
- if (bstart && bend) {
- bones_merge(obedit, bstart, bend, bchild, &chains);
- }
-
- /* put back link */
- BLI_insertlinkbefore(&chains, nchain, chain);
- }
-
- armature_tag_unselect(arm);
-
- BLI_freelistN(&chains);
- }
-
- /* 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);
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_merge(wmOperatorType *ot)
-{
- static const EnumPropertyItem merge_types[] = {
- {1, "WITHIN_CHAIN", 0, "Within Chains", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Merge Bones";
- ot->idname = "ARMATURE_OT_merge";
- ot->description = "Merge continuous chains of selected bones";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_merge_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", merge_types, 0, "Type", "");
-}
-
-/* --------------------- */
+/** \} */
-/* Switch Direction operator:
+/* -------------------------------------------------------------------- */
+/** \name Switch Direction Operator
+ *
* Currently, this does not use context loops, as context loops do not make it
* easy to retrieve any hierarchical/chain relationships which are necessary for
* this to be done easily.
- */
+ * \{ */
/* helper to clear BONE_TRANSFORM flags */
static void armature_clear_swap_done_flags(bArmature *arm)
@@ -1210,7 +1025,11 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************************* Align ******************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Align Operator
+ * \{ */
/* helper to fix a ebone position if its parent has moved due to alignment*/
static void fix_connected_bone(EditBone *ebone)
@@ -1354,7 +1173,11 @@ void ARMATURE_OT_align(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************************* Split ******************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split Operator
+ * \{ */
static int armature_split_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1367,13 +1190,13 @@ static int armature_split_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = objects[ob_index];
bArmature *arm = ob->data;
- for (EditBone *bone = arm->edbo->first; bone; bone = bone->next) {
+ LISTBASE_FOREACH (EditBone *, bone, arm->edbo) {
if (bone->parent && (bone->flag & BONE_SELECTED) != (bone->parent->flag & BONE_SELECTED)) {
bone->parent = NULL;
bone->flag &= ~BONE_CONNECTED;
}
}
- for (EditBone *bone = arm->edbo->first; bone; bone = bone->next) {
+ LISTBASE_FOREACH (EditBone *, bone, arm->edbo) {
ED_armature_ebone_select_set(bone, (bone->flag & BONE_SELECTED) != 0);
}
@@ -1400,7 +1223,11 @@ void ARMATURE_OT_split(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************************* Delete ******************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Operator
+ * \{ */
static bool armature_delete_ebone_cb(const char *bone_name, void *arm_p)
{
@@ -1457,6 +1284,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
BKE_pose_tag_recalc(CTX_data_main(C), obedit->pose);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
+ ED_outliner_select_sync_from_edit_bone_tag(C);
}
}
MEM_freeN(objects);
@@ -1632,6 +1460,7 @@ static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op))
ED_armature_edit_refresh_layer_used(arm);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
+ ED_outliner_select_sync_from_edit_bone_tag(C);
}
}
MEM_freeN(objects);
@@ -1658,7 +1487,11 @@ void ARMATURE_OT_dissolve(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************************* Show/Hide ******************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hide Operator
+ * \{ */
static int armature_hide_exec(bContext *C, wmOperator *op)
{
@@ -1678,7 +1511,7 @@ static int armature_hide_exec(bContext *C, wmOperator *op)
bArmature *arm = obedit->data;
bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_VISIBLE(arm, ebone)) {
if ((ebone->flag & BONE_SELECTED) != invert) {
ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
@@ -1719,6 +1552,12 @@ void ARMATURE_OT_hide(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Reveal Operator
+ * \{ */
+
static int armature_reveal_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1731,7 +1570,7 @@ static int armature_reveal_exec(bContext *C, wmOperator *op)
bArmature *arm = obedit->data;
bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (arm->layer & ebone->layer) {
if (ebone->flag & BONE_HIDDEN_A) {
if (!(ebone->flag & BONE_UNSELECTABLE)) {
@@ -1771,3 +1610,5 @@ void ARMATURE_OT_reveal(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
+
+/** \} */
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index fa562ab0f44..08d82bf13c9 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -59,6 +59,7 @@ void ARMATURE_OT_select_mirror(struct wmOperatorType *ot);
void ARMATURE_OT_select_more(struct wmOperatorType *ot);
void ARMATURE_OT_select_less(struct wmOperatorType *ot);
void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot);
+void ARMATURE_OT_select_linked_pick(struct wmOperatorType *ot);
void ARMATURE_OT_select_linked(struct wmOperatorType *ot);
void ARMATURE_OT_select_similar(struct wmOperatorType *ot);
void ARMATURE_OT_shortest_path_pick(struct wmOperatorType *ot);
@@ -72,7 +73,6 @@ void ARMATURE_OT_hide(struct wmOperatorType *ot);
void ARMATURE_OT_reveal(struct wmOperatorType *ot);
void ARMATURE_OT_click_extrude(struct wmOperatorType *ot);
void ARMATURE_OT_fill(struct wmOperatorType *ot);
-void ARMATURE_OT_merge(struct wmOperatorType *ot);
void ARMATURE_OT_separate(struct wmOperatorType *ot);
void ARMATURE_OT_split(struct wmOperatorType *ot);
@@ -104,6 +104,7 @@ void POSE_OT_select_all(struct wmOperatorType *ot);
void POSE_OT_select_parent(struct wmOperatorType *ot);
void POSE_OT_select_hierarchy(struct wmOperatorType *ot);
void POSE_OT_select_linked(struct wmOperatorType *ot);
+void POSE_OT_select_linked_pick(struct wmOperatorType *ot);
void POSE_OT_select_constraint_target(struct wmOperatorType *ot);
void POSE_OT_select_grouped(struct wmOperatorType *ot);
void POSE_OT_select_mirror(struct wmOperatorType *ot);
@@ -232,9 +233,6 @@ struct EditBone *duplicateEditBone(struct EditBone *curBone,
const char *name,
struct ListBase *editbones,
struct Object *ob);
-void updateDuplicateSubtarget(struct EditBone *dupBone,
- struct ListBase *editbones,
- struct Object *ob);
/* duplicate method (cross objects) */
/* editbones is the target list */
@@ -244,12 +242,6 @@ struct EditBone *duplicateEditBoneObjects(struct EditBone *curBone,
struct Object *src_ob,
struct Object *dst_ob);
-/* editbones is the source list */
-void updateDuplicateSubtargetObjects(struct EditBone *dupBone,
- struct ListBase *editbones,
- struct Object *src_ob,
- struct Object *dst_ob);
-
EditBone *add_points_bone(struct Object *obedit, float head[3], float tail[3]);
void bone_free(struct bArmature *arm, struct EditBone *bone);
@@ -258,16 +250,40 @@ void armature_select_mirrored_ex(struct bArmature *arm, const int flag);
void armature_select_mirrored(struct bArmature *arm);
void armature_tag_unselect(struct bArmature *arm);
-void *get_nearest_bone(struct bContext *C, const int xy[2], bool findunsel, struct Base **r_base);
-
-void *get_bone_from_selectbuffer(struct Base **bases,
- uint bases_len,
- bool is_editmode,
- const unsigned int *buffer,
- short hits,
+EditBone *ED_armature_pick_ebone(struct bContext *C,
+ const int xy[2],
bool findunsel,
- bool do_nearest,
struct Base **r_base);
+struct bPoseChannel *ED_armature_pick_pchan(struct bContext *C,
+ const int xy[2],
+ bool findunsel,
+ struct Base **r_base);
+struct Bone *ED_armature_pick_bone(struct bContext *C,
+ const int xy[2],
+ bool findunsel,
+ struct Base **r_base);
+
+struct EditBone *ED_armature_pick_ebone_from_selectbuffer(struct Base **bases,
+ uint bases_len,
+ const uint *buffer,
+ short hits,
+ bool findunsel,
+ bool do_nearest,
+ struct Base **r_base);
+struct bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(struct Base **bases,
+ uint bases_len,
+ const uint *buffer,
+ short hits,
+ bool findunsel,
+ bool do_nearest,
+ struct Base **r_base);
+struct Bone *ED_armature_pick_bone_from_selectbuffer(struct Base **bases,
+ uint bases_len,
+ const uint *buffer,
+ short hits,
+ bool findunsel,
+ bool do_nearest,
+ struct Base **r_base);
int bone_looper(struct Object *ob,
struct Bone *bone,
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 9a1582679a4..544d86d4c47 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -20,6 +20,8 @@
/** \file
* \ingroup edarmature
+ *
+ * This file contains functions/API's for renaming bones and/or working with them.
*/
#include <string.h>
@@ -28,9 +30,9 @@
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
-#include "DNA_object_types.h"
-#include "DNA_gpencil_types.h"
#include "DNA_gpencil_modifier_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
@@ -39,16 +41,16 @@
#include "BLT_translation.h"
-#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
-#include "BKE_gpencil_modifier.h"
#include "DEG_depsgraph.h"
@@ -63,12 +65,11 @@
#include "armature_intern.h"
-/* This file contains functions/API's for renaming bones and/or working with them */
-
-/* ************************************************** */
-/* EditBone Names */
+/* -------------------------------------------------------------------- */
+/** \name Unique Bone Name Utility (Edit Mode)
+ * \{ */
-/* note: there's a unique_bone_name() too! */
+/* note: there's a ed_armature_bone_unique_name() too! */
static bool editbone_unique_check(void *arg, const char *name)
{
struct {
@@ -79,6 +80,7 @@ static bool editbone_unique_check(void *arg, const char *name)
return dupli && dupli != data->bone;
}
+/* If bone is already in list, pass it as param to ignore it. */
void ED_armature_ebone_unique_name(ListBase *edbo, char *name, EditBone *bone)
{
struct {
@@ -91,20 +93,29 @@ void ED_armature_ebone_unique_name(ListBase *edbo, char *name, EditBone *bone)
BLI_uniquename_cb(editbone_unique_check, &data, DATA_("Bone"), '.', name, sizeof(bone->name));
}
-/* ************************************************** */
-/* Bone Renaming - API */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Unique Bone Name Utility (Object Mode)
+ * \{ */
static bool bone_unique_check(void *arg, const char *name)
{
return BKE_armature_find_bone_name((bArmature *)arg, name) != NULL;
}
-static void unique_bone_name(bArmature *arm, char *name)
+static void ed_armature_bone_unique_name(bArmature *arm, char *name)
{
BLI_uniquename_cb(
bone_unique_check, (void *)arm, DATA_("Bone"), '.', name, sizeof(((Bone *)NULL)->name));
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bone Renaming (Object & Edit Mode API)
+ * \{ */
+
/* helper call for armature_bone_rename */
static void constraint_bone_name_fix(Object *ob,
ListBase *conlist,
@@ -179,7 +190,7 @@ void ED_armature_bone_rename(Main *bmain,
Bone *bone = BKE_armature_find_bone_name(arm, oldname);
if (bone) {
- unique_bone_name(arm, newname);
+ ed_armature_bone_unique_name(arm, newname);
if (arm->bonehash) {
BLI_assert(BLI_ghash_haskey(arm->bonehash, bone->name));
@@ -254,8 +265,8 @@ void ED_armature_bone_rename(Main *bmain,
}
}
- if (modifiers_usesArmature(ob, arm)) {
- bDeformGroup *dg = defgroup_find_name(ob, oldname);
+ if (BKE_modifiers_uses_armature(ob, arm)) {
+ bDeformGroup *dg = BKE_object_defgroup_find_name(ob, oldname);
if (dg) {
BLI_strncpy(dg->name, newname, MAXBONENAME);
}
@@ -298,7 +309,7 @@ void ED_armature_bone_rename(Main *bmain,
if (ob->type == OB_GPENCIL) {
bGPdata *gpd = (bGPdata *)ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if ((gpl->parent != NULL) && (gpl->parent->data == arm)) {
if (STREQ(gpl->parsubstr, oldname)) {
BLI_strncpy(gpl->parsubstr, newname, MAXBONENAME);
@@ -306,13 +317,12 @@ void ED_armature_bone_rename(Main *bmain,
}
}
- for (GpencilModifierData *gp_md = ob->greasepencil_modifiers.first; gp_md;
- gp_md = gp_md->next) {
+ LISTBASE_FOREACH (GpencilModifierData *, gp_md, &ob->greasepencil_modifiers) {
switch (gp_md->type) {
case eGpencilModifierType_Armature: {
ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)gp_md;
if (mmd->object && mmd->object->data == arm) {
- bDeformGroup *dg = defgroup_find_name(ob, oldname);
+ bDeformGroup *dg = BKE_object_defgroup_find_name(ob, oldname);
if (dg) {
BLI_strncpy(dg->name, newname, MAXBONENAME);
}
@@ -351,16 +361,16 @@ void ED_armature_bone_rename(Main *bmain,
{
bScreen *screen;
for (screen = bmain->screens.first; screen; screen = screen->id.next) {
- ScrArea *sa;
+ ScrArea *area;
/* add regions */
- for (sa = screen->areabase.first; sa; sa = sa->next) {
+ for (area = screen->areabase.first; area; area = area->next) {
SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ for (sl = area->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
- if (v3d->ob_centre && v3d->ob_centre->data == arm) {
- if (STREQ(v3d->ob_centre_bone, oldname)) {
- BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
+ if (v3d->ob_center && v3d->ob_center->data == arm) {
+ if (STREQ(v3d->ob_center_bone, oldname)) {
+ BLI_strncpy(v3d->ob_center_bone, newname, MAXBONENAME);
}
}
}
@@ -371,6 +381,12 @@ void ED_armature_bone_rename(Main *bmain,
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bone Flipping (Object & Edit Mode API)
+ * \{ */
+
typedef struct BoneFlipNameData {
struct BoneFlipNameData *next, *prev;
char *name;
@@ -398,7 +414,7 @@ void ED_armature_bones_flip_names(Main *bmain,
/* First pass: generate flip names, and blindly rename.
* If rename did not yield expected result,
* store both bone's name and expected flipped one into temp list for second pass. */
- for (LinkData *link = bones_names->first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, bones_names) {
char name_flip[MAXBONENAME];
char *name = link->data;
@@ -425,8 +441,11 @@ void ED_armature_bones_flip_names(Main *bmain,
}
}
-/* ************************************************** */
-/* Bone Renaming - EditMode */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Flip Bone Names (Edit Mode Operator)
+ * \{ */
static int armature_flip_names_exec(bContext *C, wmOperator *op)
{
@@ -450,7 +469,7 @@ static int armature_flip_names_exec(bContext *C, wmOperator *op)
ListBase bones_names = {NULL};
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_VISIBLE(arm, ebone)) {
if (ebone->flag & BONE_SELECTED) {
BLI_addtail(&bones_names, BLI_genericNodeN(ebone->name));
@@ -510,6 +529,12 @@ void ARMATURE_OT_flip_names(wmOperatorType *ot)
"(WARNING: may result in incoherent naming in some cases)");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bone Auto Side Names (Edit Mode Operator)
+ * \{ */
+
static int armature_autoside_names_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -531,7 +556,7 @@ static int armature_autoside_names_exec(bContext *C, wmOperator *op)
continue;
}
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_EDITABLE(ebone)) {
/* We first need to do the flipped bone, then the original one.
@@ -598,3 +623,5 @@ void ARMATURE_OT_autoside_names(wmOperatorType *ot)
/* settings */
ot->prop = RNA_def_enum(ot->srna, "type", axis_items, 0, "Axis", "Axis tag names with");
}
+
+/** \} */
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index a29d0f5f158..da1b29307b1 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -56,6 +56,7 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(ARMATURE_OT_select_less);
WM_operatortype_append(ARMATURE_OT_select_hierarchy);
WM_operatortype_append(ARMATURE_OT_select_linked);
+ WM_operatortype_append(ARMATURE_OT_select_linked_pick);
WM_operatortype_append(ARMATURE_OT_select_similar);
WM_operatortype_append(ARMATURE_OT_shortest_path_pick);
@@ -68,7 +69,6 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(ARMATURE_OT_reveal);
WM_operatortype_append(ARMATURE_OT_click_extrude);
WM_operatortype_append(ARMATURE_OT_fill);
- WM_operatortype_append(ARMATURE_OT_merge);
WM_operatortype_append(ARMATURE_OT_separate);
WM_operatortype_append(ARMATURE_OT_split);
@@ -100,6 +100,7 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(POSE_OT_select_parent);
WM_operatortype_append(POSE_OT_select_hierarchy);
WM_operatortype_append(POSE_OT_select_linked);
+ WM_operatortype_append(POSE_OT_select_linked_pick);
WM_operatortype_append(POSE_OT_select_constraint_target);
WM_operatortype_append(POSE_OT_select_grouped);
WM_operatortype_append(POSE_OT_select_mirror);
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index c2c7d7e5ee7..5f3b876efaf 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -37,11 +37,12 @@
#include "BLT_translation.h"
#include "BKE_action.h"
+#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
-#include "BKE_fcurve.h"
+#include "BKE_fcurve_driver.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -57,6 +58,7 @@
#include "ED_armature.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -280,7 +282,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
float mat[4][4], oimat[4][4];
bool ok = false;
- /* Ensure we're not in editmode and that the active object is an armature*/
+ /* Ensure we're not in edit-mode and that the active object is an armature. */
if (!ob_active || ob_active->type != OB_ARMATURE) {
return OPERATOR_CANCELLED;
}
@@ -568,7 +570,7 @@ static void separate_armature_bones(Main *bmain, Object *ob, const bool is_selec
if (is_select == (EBONE_VISIBLE(arm, curbone) && (curbone->flag & BONE_SELECTED))) {
/* clear the bone->parent var of any bone that had this as its parent */
- for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
if (ebo->parent == curbone) {
ebo->parent = NULL;
/* this is needed to prevent random crashes with in ED_armature_from_edit */
@@ -578,7 +580,7 @@ static void separate_armature_bones(Main *bmain, Object *ob, const bool is_selec
}
/* clear the pchan->parent var of any pchan that had this as its parent */
- for (bPoseChannel *pchn = ob->pose->chanbase.first; pchn; pchn = pchn->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchn, &ob->pose->chanbase) {
if (pchn->parent == pchan) {
pchn->parent = NULL;
}
@@ -629,7 +631,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
bArmature *arm_old = ob_old->data;
bool has_selected_bone = false;
bool has_selected_any = false;
- for (EditBone *ebone = arm_old->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm_old->edbo) {
if (EBONE_VISIBLE(arm_old, ebone)) {
if (ebone->flag & BONE_SELECTED) {
has_selected_bone = true;
@@ -639,14 +641,14 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
has_selected_any = true;
}
}
- if (has_selected_bone == false) {
- if (has_selected_any) {
- /* Without this, we may leave head/tail selected
- * which isn't expected after separating. */
- ED_armature_edit_deselect_all(ob_old);
- }
- continue;
+ }
+ if (has_selected_bone == false) {
+ if (has_selected_any) {
+ /* Without this, we may leave head/tail selected
+ * which isn't expected after separating. */
+ ED_armature_edit_deselect_all(ob_old);
}
+ continue;
}
}
@@ -667,8 +669,10 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
/* 2) duplicate base */
- /* only duplicate linked armature */
- Base *base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, USER_DUP_ARM);
+ /* Only duplicate linked armature but take into account
+ * user preferences for duplicating actions. */
+ short dupflag = USER_DUP_ARM | (U.dupflag & USER_DUP_ACT);
+ Base *base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, dupflag);
Object *ob_new = base_new->object;
DEG_relations_tag_update(bmain);
@@ -704,6 +708,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
if (ok) {
BKE_report(op->reports, RPT_INFO, "Separated bones");
+ ED_outliner_select_sync_from_object_tag(C);
}
return OPERATOR_FINISHED;
@@ -833,7 +838,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
bool is_active_only_selected = false;
if (actbone->flag & BONE_SELECTED) {
is_active_only_selected = true;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_EDITABLE(ebone) && (ebone->flag & BONE_SELECTED)) {
if (ebone != actbone) {
is_active_only_selected = false;
@@ -865,7 +870,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
*/
/* Parent selected bones to the active one. */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_EDITABLE(ebone) && (ebone->flag & BONE_SELECTED)) {
if (ebone != actbone) {
bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
@@ -899,7 +904,7 @@ static int armature_parent_set_invoke(bContext *C,
Object *ob = CTX_data_edit_object(C);
bArmature *arm = ob->data;
EditBone *actbone = arm->act_edbone;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_EDITABLE(ebone) && (ebone->flag & BONE_SELECTED)) {
if (ebone != actbone) {
if (ebone->parent != actbone) {
@@ -981,7 +986,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op)
bArmature *arm = ob->data;
bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_EDITABLE(ebone)) {
changed = true;
break;
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 0f288c0d8b8..b946c19dbe5 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -30,13 +30,14 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_rect.h"
#include "BLI_string_utils.h"
-#include "BKE_context.h"
#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_report.h"
-#include "BKE_layer.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -59,7 +60,9 @@
#define EBONE_PREV_FLAG_GET(ebone) ((void)0, (ebone)->temp.i)
#define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp.i = val)
-/* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
+/* -------------------------------------------------------------------- */
+/** \name Select Buffer Queries for PoseMode & EditMode
+ * \{ */
Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
uint bases_len,
@@ -109,14 +112,14 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
return ob;
}
-Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
- uint bases_len,
- int hit,
- Bone **r_bone)
+Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
+ uint bases_len,
+ int hit,
+ bPoseChannel **r_pchan)
{
const uint hit_object = hit & 0xFFFF;
Base *base = NULL;
- Bone *bone = NULL;
+ bPoseChannel *pchan = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
for (uint base_index = 0; base_index < bases_len; base_index++) {
if (bases[base_index]->object->runtime.select_id == hit_object) {
@@ -127,30 +130,53 @@ Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
if (base != NULL) {
if (base->object->pose != NULL) {
const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
- bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
- bone = pchan ? pchan->bone : NULL;
+ /* pchan may be NULL. */
+ pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
}
}
- *r_bone = bone;
+ *r_pchan = pchan;
return base;
}
+/* For callers that don't need the pose channel. */
+Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
+ uint bases_len,
+ int hit,
+ Bone **r_bone)
+{
+ bPoseChannel *pchan = NULL;
+ Base *base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hit, &pchan);
+ *r_bone = pchan ? pchan->bone : NULL;
+ return base;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cursor Pick from Select Buffer API
+ *
+ * Internal #ed_armature_pick_bone_from_selectbuffer_impl is exposed as:
+ * - #ED_armature_pick_ebone_from_selectbuffer
+ * - #ED_armature_pick_pchan_from_selectbuffer
+ * - #ED_armature_pick_bone_from_selectbuffer
+ * \{ */
+
/* See if there are any selected bones in this buffer */
/* only bones from base are checked on */
-void *get_bone_from_selectbuffer(Base **bases,
- uint bases_len,
- bool is_editmode,
- const unsigned int *buffer,
- short hits,
- bool findunsel,
- bool do_nearest,
- Base **r_base)
+static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode,
+ Base **bases,
+ uint bases_len,
+ const uint *buffer,
+ short hits,
+ bool findunsel,
+ bool do_nearest,
+ Base **r_base)
{
- Bone *bone;
+ bPoseChannel *pchan;
EditBone *ebone;
void *firstunSel = NULL, *firstSel = NULL, *data;
Base *firstunSel_base = NULL, *firstSel_base = NULL;
- unsigned int hitresult;
+ uint hitresult;
short i;
bool takeNext = false;
int minsel = 0xffffffff, minunsel = 0xffffffff;
@@ -166,16 +192,17 @@ void *get_bone_from_selectbuffer(Base **bases,
hitresult &= ~(BONESEL_ANY);
/* Determine what the current bone is */
if (is_editmode == false) {
- base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, hitresult, &bone);
- if (bone != NULL) {
+ base = ED_armature_base_and_pchan_from_select_buffer(
+ bases, bases_len, hitresult, &pchan);
+ if (pchan != NULL) {
if (findunsel) {
- sel = (bone->flag & BONE_SELECTED);
+ sel = (pchan->bone->flag & BONE_SELECTED);
}
else {
- sel = !(bone->flag & BONE_SELECTED);
+ sel = !(pchan->bone->flag & BONE_SELECTED);
}
- data = bone;
+ data = pchan;
}
else {
data = NULL;
@@ -246,22 +273,74 @@ void *get_bone_from_selectbuffer(Base **bases,
}
}
-/* used by posemode as well editmode */
-/* only checks scene->basact! */
-/* x and y are mouse coords (area space) */
-void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
+EditBone *ED_armature_pick_ebone_from_selectbuffer(Base **bases,
+ uint bases_len,
+ const uint *buffer,
+ short hits,
+ bool findunsel,
+ bool do_nearest,
+ Base **r_base)
+{
+ const bool is_editmode = true;
+ return ed_armature_pick_bone_from_selectbuffer_impl(
+ is_editmode, bases, bases_len, buffer, hits, findunsel, do_nearest, r_base);
+}
+
+bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(Base **bases,
+ uint bases_len,
+ const uint *buffer,
+ short hits,
+ bool findunsel,
+ bool do_nearest,
+ Base **r_base)
+{
+ const bool is_editmode = false;
+ return ed_armature_pick_bone_from_selectbuffer_impl(
+ is_editmode, bases, bases_len, buffer, hits, findunsel, do_nearest, r_base);
+}
+
+Bone *ED_armature_pick_bone_from_selectbuffer(Base **bases,
+ uint bases_len,
+ const uint *buffer,
+ short hits,
+ bool findunsel,
+ bool do_nearest,
+ Base **r_base)
+{
+ bPoseChannel *pchan = ED_armature_pick_pchan_from_selectbuffer(
+ bases, bases_len, buffer, hits, findunsel, do_nearest, r_base);
+ return pchan ? pchan->bone : NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cursor Pick API
+ *
+ * Internal #ed_armature_pick_bone_impl is exposed as:
+ * - #ED_armature_pick_ebone
+ * - #ED_armature_pick_pchan
+ * - #ED_armature_pick_bone
+ * \{ */
+
+/**
+ * \param xy: Cursor coordinates (area space).
+ * \return An #EditBone when is_editmode, otherwise a #bPoseChannel.
+ * \note Only checks objects in the current mode (edit-mode or pose-mode).
+ */
+static void *ed_armature_pick_bone_impl(
+ const bool is_editmode, bContext *C, const int xy[2], bool findunsel, Base **r_base)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
rcti rect;
- unsigned int buffer[MAXPICKBUF];
+ uint buffer[MAXPICKBUF];
short hits;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
+ BLI_assert((vc.obedit != NULL) == is_editmode);
- // rect.xmin = ... mouseco!
- rect.xmin = rect.xmax = xy[0];
- rect.ymin = rect.ymax = xy[1];
+ BLI_rcti_init_pt_radius(&rect, xy, 0);
hits = view3d_opengl_select(
&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
@@ -284,123 +363,287 @@ void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel, Base **r_ba
bases = BKE_object_pose_base_array_get(vc.view_layer, vc.v3d, &bases_len);
}
- void *bone = get_bone_from_selectbuffer(
- bases, bases_len, vc.obedit != NULL, buffer, hits, findunsel, true, r_base);
+ void *bone = ed_armature_pick_bone_from_selectbuffer_impl(
+ is_editmode, bases, bases_len, buffer, hits, findunsel, true, r_base);
MEM_freeN(bases);
+
return bone;
}
return NULL;
}
-/* **************** EditMode stuff ********************** */
+EditBone *ED_armature_pick_ebone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
+{
+ const bool is_editmode = true;
+ return ed_armature_pick_bone_impl(is_editmode, C, xy, findunsel, r_base);
+}
-static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+bPoseChannel *ED_armature_pick_pchan(bContext *C, const int xy[2], bool findunsel, Base **r_base)
{
- bArmature *arm;
- EditBone *bone, *curBone, *next;
- const bool sel = !RNA_boolean_get(op->ptr, "deselect");
+ const bool is_editmode = false;
+ return ed_armature_pick_bone_impl(is_editmode, C, xy, findunsel, r_base);
+}
- view3d_operator_needs_opengl(C);
- BKE_object_update_select_id(CTX_data_main(C));
+Bone *ED_armature_pick_bone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
+{
+ bPoseChannel *pchan = ED_armature_pick_pchan(C, xy, findunsel, r_base);
+ return pchan ? pchan->bone : NULL;
+}
- Base *base = NULL;
- bone = get_nearest_bone(C, event->mval, true, &base);
+/** \} */
- if (!bone) {
- return OPERATOR_CANCELLED;
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Implementation
+ *
+ * Shared logic for select linked all/pick.
+ *
+ * Use #BONE_DONE flag to select linked.
+ * \{ */
+
+/**
+ * \param all_forks: Control how chains are stepped over.
+ * true: select all connected bones traveling up & down forks.
+ * false: select all parents and all children, but not the children of the root bone.
+ */
+static bool armature_select_linked_impl(Object *ob, const bool select, const bool all_forks)
+{
+ bool changed = false;
+ bArmature *arm = ob->data;
+
+ /* Implementation note, this flood-fills selected bones with the 'TOUCH' flag,
+ * even though this is a loop-within a loop, walking up the parent chain only touches new bones.
+ * Bones that have been touched are skipped, so the complexity is OK. */
+
+ enum {
+ /* Bone has been walked over, it's LINK value can be read. */
+ TOUCH = (1 << 0),
+ /* When TOUCH has been set, this flag can be checked to see if the bone is connected. */
+ LINK = (1 << 1),
+ };
+
+#define CHECK_PARENT(ebone) \
+ (((ebone)->flag & BONE_CONNECTED) && \
+ ((ebone)->parent ? EBONE_SELECTABLE(arm, (ebone)->parent) : false))
+
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
+ ebone->temp.i = 0;
}
- arm = base->object->data;
+ /* Select parents. */
+ LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
+ if (ebone_iter->temp.i & TOUCH) {
+ continue;
+ }
+ if ((ebone_iter->flag & BONE_DONE) == 0) {
+ continue;
+ }
+
+ ebone_iter->temp.i |= TOUCH | LINK;
+
+ /* We have an un-touched link. */
+ for (EditBone *ebone = ebone_iter; ebone; ebone = CHECK_PARENT(ebone) ? ebone->parent : NULL) {
+ ED_armature_ebone_select_set(ebone, select);
+ changed = true;
- /* Select parents */
- for (curBone = bone; curBone; curBone = next) {
- if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
- if (sel) {
- curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if (all_forks) {
+ ebone->temp.i |= (TOUCH | LINK);
}
else {
- curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ ebone->temp.i |= TOUCH;
+ }
+ /* Don't walk onto links (messes up 'all_forks' logic). */
+ if (ebone->parent && ebone->parent->temp.i & LINK) {
+ break;
}
}
+ }
- if (curBone->flag & BONE_CONNECTED) {
- next = curBone->parent;
+ /* Select children. */
+ LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
+ /* No need to 'touch' this bone as it won't be walked over when scanning up the chain. */
+ if (!CHECK_PARENT(ebone_iter)) {
+ continue;
}
- else {
- next = NULL;
+ if (ebone_iter->temp.i & TOUCH) {
+ continue;
}
- }
- /* Select children */
- while (bone) {
- for (curBone = arm->edbo->first; curBone; curBone = next) {
- next = curBone->next;
- if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE) == 0) {
- if (curBone->flag & BONE_CONNECTED) {
- if (sel) {
- curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- bone = curBone;
- break;
- }
- else {
- bone = NULL;
- break;
+ /* First check if we're marked. */
+ EditBone *ebone_touched_parent = NULL;
+ for (EditBone *ebone = ebone_iter; ebone; ebone = CHECK_PARENT(ebone) ? ebone->parent : NULL) {
+ if (ebone->temp.i & TOUCH) {
+ ebone_touched_parent = ebone;
+ break;
+ }
+ ebone->temp.i |= TOUCH;
+ }
+
+ if ((ebone_touched_parent != NULL) && (ebone_touched_parent->temp.i & LINK)) {
+ for (EditBone *ebone = ebone_iter; ebone != ebone_touched_parent; ebone = ebone->parent) {
+ if ((ebone->temp.i & LINK) == 0) {
+ ebone->temp.i |= LINK;
+ ED_armature_ebone_select_set(ebone, select);
+ changed = true;
}
}
}
- if (!curBone) {
- bone = NULL;
+ }
+
+#undef CHECK_PARENT
+
+ if (changed) {
+ ED_armature_edit_sync_selection(arm->edbo);
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, ob);
+ }
+
+ return changed;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Operator
+ * \{ */
+
+static int armature_select_linked_exec(bContext *C, wmOperator *op)
+{
+ const bool all_forks = RNA_boolean_get(op->ptr, "all_forks");
+
+ bool changed_multi = false;
+ 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);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+
+ bool found = false;
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
+ if (EBONE_VISIBLE(arm, ebone) &&
+ (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL))) {
+ ebone->flag |= BONE_DONE;
+ found = true;
+ }
+ else {
+ ebone->flag &= ~BONE_DONE;
+ }
+ }
+
+ if (found) {
+ if (armature_select_linked_impl(ob, true, all_forks)) {
+ changed_multi = true;
+ }
}
}
+ MEM_freeN(objects);
- ED_outliner_select_sync_from_edit_bone_tag(C);
+ if (changed_multi) {
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+ }
+ return OPERATOR_FINISHED;
+}
- ED_armature_edit_sync_selection(arm->edbo);
+void ARMATURE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked All";
+ ot->idname = "ARMATURE_OT_select_linked";
+ ot->description = "Select all bones linked by parent/child connections to the current selection";
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ /* api callbacks */
+ ot->exec = armature_select_linked_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Leave disabled by default as this matches pose mode. */
+ RNA_def_boolean(ot->srna, "all_forks", 0, "All Forks", "Follow forks in the parents chain");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked (Cursor Pick) Operator
+ * \{ */
+
+static int armature_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+ const bool all_forks = RNA_boolean_get(op->ptr, "all_forks");
+
+ view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
+
+ Base *base = NULL;
+ EditBone *ebone_active = ED_armature_pick_ebone(C, event->mval, true, &base);
+
+ if (ebone_active == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bArmature *arm = base->object->data;
+ if (!EBONE_SELECTABLE(arm, ebone_active)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Initialize flags. */
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
+ ebone->flag &= ~BONE_DONE;
+ }
+ ebone_active->flag |= BONE_DONE;
+
+ if (armature_select_linked_impl(base->object, select, all_forks)) {
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+ }
return OPERATOR_FINISHED;
}
-static bool armature_select_linked_poll(bContext *C)
+static bool armature_select_linked_pick_poll(bContext *C)
{
return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
}
-void ARMATURE_OT_select_linked(wmOperatorType *ot)
+void ARMATURE_OT_select_linked_pick(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Connected";
- ot->idname = "ARMATURE_OT_select_linked";
- ot->description = "Select bones related to selected ones by parent/child relationships";
+ ot->name = "Select Linked";
+ ot->idname = "ARMATURE_OT_select_linked_pick";
+ ot->description = "(De)select bones linked by parent/child connections under the mouse cursor";
/* api callbacks */
/* leave 'exec' unset */
- ot->invoke = armature_select_linked_invoke;
- ot->poll = armature_select_linked_poll;
+ ot->invoke = armature_select_linked_pick_invoke;
+ ot->poll = armature_select_linked_pick_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ /* Leave disabled by default as this matches pose mode. */
+ RNA_def_boolean(ot->srna, "all_forks", 0, "All Forks", "Follow forks in the parents chain");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Buffer Queries EditMode
+ * \{ */
+
/* utility function for get_nearest_editbonepoint */
-static int selectbuffer_ret_hits_12(unsigned int *UNUSED(buffer), const int hits12)
+static int selectbuffer_ret_hits_12(uint *UNUSED(buffer), const int hits12)
{
return hits12;
}
-static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits12, const int hits5)
+static int selectbuffer_ret_hits_5(uint *buffer, const int hits12, const int hits5)
{
const int offs = 4 * hits12;
- memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
+ memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(uint));
return hits5;
}
@@ -414,45 +657,28 @@ static EditBone *get_nearest_editbonepoint(
uint hitresult;
Base *base;
EditBone *ebone;
- } best = {
- .hitresult = BONESEL_NOSEL,
- .base = NULL,
- .ebone = NULL,
- };
+ } *result = NULL,
+
+ result_cycle = {.hitresult = BONESEL_NOSEL, .base = NULL, .ebone = NULL},
+ result_bias = {.hitresult = BONESEL_NOSEL, .base = NULL, .ebone = NULL};
/* find the bone after the current active bone, so as to bump up its chances in selection.
* this way overlapping bones will cycle selection state as with objects. */
- EditBone *ebone_next_act = ((bArmature *)vc->obedit->data)->act_edbone;
- {
- bArmature *arm = (bArmature *)vc->obedit->data;
- if (ebone_next_act && EBONE_VISIBLE(arm, ebone_next_act) &&
- ebone_next_act->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
- ebone_next_act = ebone_next_act->next ? ebone_next_act->next : arm->edbo->first;
- }
- else {
- ebone_next_act = NULL;
- }
+ Object *obedit_orig = vc->obedit;
+ EditBone *ebone_active_orig = ((bArmature *)obedit_orig->data)->act_edbone;
+ if (ebone_active_orig == NULL) {
+ use_cycle = false;
}
- bool do_nearest = false;
-
- /* define if we use solid nearest select or not */
if (use_cycle) {
static int last_mval[2] = {-100, -100};
-
- if (!XRAY_ACTIVE(vc->v3d)) {
- do_nearest = true;
- if (len_manhattan_v2v2_int(vc->mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
- do_nearest = false;
- }
+ if ((len_manhattan_v2v2_int(vc->mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) == 0) {
+ use_cycle = false;
}
copy_v2_v2_int(last_mval, vc->mval);
}
- else {
- if (!XRAY_ACTIVE(vc->v3d)) {
- do_nearest = true;
- }
- }
+
+ const bool do_nearest = !(XRAY_ACTIVE(vc->v3d) || use_cycle);
/* matching logic from 'mixed_bones_object_selectbuffer' */
int hits = 0;
@@ -507,13 +733,45 @@ cache_end:
if (hits > 0) {
if (hits == 1) {
if (!(buffer[3] & BONESEL_NOSEL)) {
- best.hitresult = buffer[3];
- best.base = ED_armature_base_and_ebone_from_select_buffer(
- bases, bases_len, best.hitresult, &best.ebone);
+ result_bias.hitresult = buffer[3];
+ result_bias.base = ED_armature_base_and_ebone_from_select_buffer(
+ bases, bases_len, result_bias.hitresult, &result_bias.ebone);
}
}
else {
- int dep_min = 5;
+ int bias_max = INT_MIN;
+
+ /* Track Cycle Variables
+ * - Offset is always set to the active bone.
+ * - The object & bone indices subtracted by the 'offset.as_u32' value.
+ * Unsigned subtraction wrapping means we always select the next bone in the cycle.
+ */
+ struct {
+ union {
+ uint32_t as_u32;
+ struct {
+#ifdef __BIG_ENDIAN__
+ uint16_t ob;
+ uint16_t bone;
+#else
+ uint16_t bone;
+ uint16_t ob;
+#endif
+ };
+ } offset, test, best;
+ } cycle_order;
+
+ if (use_cycle) {
+ bArmature *arm = obedit_orig->data;
+ int ob_index = obedit_orig->runtime.select_id & 0xFFFF;
+ int bone_index = BLI_findindex(arm->edbo, ebone_active_orig);
+ /* Offset from the current active bone, so we cycle onto the next. */
+ cycle_order.offset.ob = ob_index;
+ cycle_order.offset.bone = bone_index;
+ /* The value of the active bone (with offset subtracted, a signal to always overwrite). */
+ cycle_order.best.as_u32 = 0;
+ }
+
for (int i = 0; i < hits; i++) {
const uint hitresult = buffer[3 + (i * 4)];
if (!(hitresult & BONESEL_NOSEL)) {
@@ -524,69 +782,98 @@ cache_end:
/* If this fails, selection code is setting the selection ID's incorrectly. */
BLI_assert(base && ebone);
- int dep;
- /* clicks on bone points get advantage */
- if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
- /* but also the unselected one */
- if (findunsel) {
- if ((hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0) {
- dep = 1;
- }
- else if ((hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0) {
- dep = 1;
+ /* Prioritized selection. */
+ {
+ int bias;
+ /* clicks on bone points get advantage */
+ if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
+ /* but also the unselected one */
+ if (findunsel) {
+ if ((hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0) {
+ bias = 4;
+ }
+ else if ((hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0) {
+ bias = 4;
+ }
+ else {
+ bias = 3;
+ }
}
else {
- dep = 2;
+ bias = 4;
}
}
else {
- dep = 1;
- }
- }
- else {
- /* bone found */
- if (findunsel) {
- if ((ebone->flag & BONE_SELECTED) == 0) {
- dep = 3;
+ /* bone found */
+ if (findunsel) {
+ if ((ebone->flag & BONE_SELECTED) == 0) {
+ bias = 2;
+ }
+ else {
+ bias = 1;
+ }
}
else {
- dep = 4;
+ bias = 2;
}
}
- else {
- dep = 3;
- }
- }
- if (ebone == ebone_next_act) {
- dep -= 1;
+ if (bias > bias_max) {
+ bias_max = bias;
+
+ result_bias.hitresult = hitresult;
+ result_bias.base = base;
+ result_bias.ebone = ebone;
+ }
}
- if (dep < dep_min) {
- dep_min = dep;
- best.hitresult = hitresult;
- best.base = base;
- best.ebone = ebone;
+ /* Cycle selected items (objects & bones). */
+ if (use_cycle) {
+ cycle_order.test.ob = hitresult & 0xFFFF;
+ cycle_order.test.bone = (hitresult & ~BONESEL_ANY) >> 16;
+ if (ebone == ebone_active_orig) {
+ BLI_assert(cycle_order.test.ob == cycle_order.offset.ob);
+ BLI_assert(cycle_order.test.bone == cycle_order.offset.bone);
+ }
+ /* Subtraction as a single value is needed to support cycling through bones
+ * from multiple objects. So once the last bone is selected,
+ * the bits for the bone index wrap into the object,
+ * causing the next object to be stepped onto. */
+ cycle_order.test.as_u32 -= cycle_order.offset.as_u32;
+
+ /* Even though this logic avoids stepping onto the active bone,
+ * always set the 'best' value for the first time.
+ * Otherwise ensure the value is the smallest it can be,
+ * relative to the active bone, as long as it's not the active bone. */
+ if ((cycle_order.best.as_u32 == 0) ||
+ (cycle_order.test.as_u32 && (cycle_order.test.as_u32 < cycle_order.best.as_u32))) {
+ cycle_order.best = cycle_order.test;
+ result_cycle.hitresult = hitresult;
+ result_cycle.base = base;
+ result_cycle.ebone = ebone;
+ }
}
}
}
}
- if (!(best.hitresult & BONESEL_NOSEL)) {
- *r_base = best.base;
+ result = (use_cycle && result_cycle.ebone) ? &result_cycle : &result_bias;
+
+ if (!(result->hitresult & BONESEL_NOSEL)) {
+ *r_base = result->base;
*r_selmask = 0;
- if (best.hitresult & BONESEL_ROOT) {
+ if (result->hitresult & BONESEL_ROOT) {
*r_selmask |= BONE_ROOTSEL;
}
- if (best.hitresult & BONESEL_TIP) {
+ if (result->hitresult & BONESEL_TIP) {
*r_selmask |= BONE_TIPSEL;
}
- if (best.hitresult & BONESEL_BONE) {
+ if (result->hitresult & BONESEL_BONE) {
*r_selmask |= BONE_SELECTED;
}
MEM_freeN(bases);
- return best.ebone;
+ return result->ebone;
}
}
*r_selmask = 0;
@@ -595,11 +882,17 @@ cache_end:
return NULL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Utility Functions
+ * \{ */
+
bool ED_armature_edit_deselect_all(Object *obedit)
{
bArmature *arm = obedit->data;
bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
changed = true;
@@ -612,7 +905,7 @@ bool ED_armature_edit_deselect_all_visible(Object *obedit)
{
bArmature *arm = obedit->data;
bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
/* first and foremost, bone must be visible and selected */
if (EBONE_VISIBLE(arm, ebone)) {
if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
@@ -661,17 +954,11 @@ bool ED_armature_edit_deselect_all_visible_multi(bContext *C)
return changed_multi;
}
-/* accounts for connected parents */
-static int ebone_select_flag(EditBone *ebone)
-{
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) |
- (ebone->flag & (BONE_SELECTED | BONE_TIPSEL));
- }
- else {
- return ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- }
-}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Cursor Pick API
+ * \{ */
/* context: editmode armature in view3d */
bool ED_armature_edit_select_pick(
@@ -784,7 +1071,7 @@ bool ED_armature_edit_select_pick(
ED_armature_edit_sync_selection(arm->edbo);
/* then now check for active status */
- if (ebone_select_flag(nearBone)) {
+ if (ED_armature_ebone_selectflag_get(nearBone)) {
arm->act_edbone = nearBone;
}
@@ -800,6 +1087,8 @@ bool ED_armature_edit_select_pick(
return false;
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Select Op From Tagged
*
@@ -893,7 +1182,7 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
/* Initialize flags. */
{
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
/* Flush the parent flag to this bone
* so we don't need to check the parent when adjusting the selection. */
@@ -915,7 +1204,7 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
}
/* Apply selection from bone selection flags. */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (ebone->temp.i != 0) {
int is_ignore_flag = ((ebone->temp.i << 16) & (BONESEL_ROOT | BONESEL_TIP));
int is_inside_flag = (ebone->temp.i & (BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE));
@@ -935,7 +1224,7 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
if (changed) {
/* Cleanup flags. */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (ebone->flag & BONE_DONE) {
SWAP(int, ebone->temp.i, ebone->flag);
ebone->flag |= BONE_DONE;
@@ -948,7 +1237,7 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
}
}
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (ebone->flag & BONE_DONE) {
if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
bool is_parent_tip_changed = (ebone->parent->flag & BONE_TIPSEL) !=
@@ -984,7 +1273,9 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
/** \} */
-/* **************** Selections ******************/
+/* -------------------------------------------------------------------- */
+/** \name (De)Select All Operator
+ * \{ */
static int armature_de_select_all_exec(bContext *C, wmOperator *op)
{
@@ -1003,7 +1294,7 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
}
- /* Set the flags */
+ /* Set the flags. */
CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) {
/* ignore bone if selection can't change */
switch (action) {
@@ -1063,7 +1354,11 @@ void ARMATURE_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-/**************** Select more/less **************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More/Less Implementation
+ * \{ */
static void armature_select_more(bArmature *arm, EditBone *ebone)
{
@@ -1150,6 +1445,12 @@ static void armature_select_more_less(Object *ob, bool more)
ED_armature_edit_sync_selection(arm->edbo);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More Operator
+ * \{ */
+
static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1183,6 +1484,12 @@ void ARMATURE_OT_select_more(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Less Operator
+ * \{ */
+
static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1216,6 +1523,12 @@ void ARMATURE_OT_select_less(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Similar
+ * \{ */
+
enum {
SIMEDBONE_CHILDREN = 1,
SIMEDBONE_CHILDREN_IMMEDIATE,
@@ -1270,7 +1583,7 @@ static void select_similar_length(bContext *C, const float thresh)
bArmature *arm = ob->data;
bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_SELECTABLE(arm, ebone)) {
const float len_iter = bone_length_squared_worldspace_get(ob, ebone);
if ((len_iter > len_min) && (len_iter < len_max)) {
@@ -1318,7 +1631,7 @@ static void select_similar_direction(bContext *C, const float thresh)
bArmature *arm = ob->data;
bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_SELECTABLE(arm, ebone)) {
float dir[3];
bone_direction_worldspace_get(ob, ebone, dir);
@@ -1352,7 +1665,7 @@ static void select_similar_layer(bContext *C)
bArmature *arm = ob->data;
bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_SELECTABLE(arm, ebone)) {
if (ebone->layer & ebone_act->layer) {
ED_armature_ebone_select_set(ebone, true);
@@ -1392,7 +1705,7 @@ static void select_similar_prefix(bContext *C)
bool changed = false;
/* Find matches */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_SELECTABLE(arm, ebone)) {
char prefix_other[MAXBONENAME];
BLI_string_split_prefix(ebone->name, prefix_other, body_tmp, sizeof(ebone->name));
@@ -1434,7 +1747,7 @@ static void select_similar_suffix(bContext *C)
bool changed = false;
/* Find matches */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_SELECTABLE(arm, ebone)) {
char suffix_other[MAXBONENAME];
BLI_string_split_suffix(ebone->name, body_tmp, suffix_other, sizeof(ebone->name));
@@ -1461,8 +1774,15 @@ static void select_similar_data_pchan(bContext *C, const size_t bytes_size, cons
EditBone *ebone_act = CTX_data_active_bone(C);
const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obedit->pose, ebone_act->name);
+
+ /* This will mostly happen for corner cases where the user tried to access this
+ * before having any valid pose data for the armature. */
+ if (pchan_active == NULL) {
+ return;
+ }
+
const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset);
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (EBONE_SELECTABLE(arm, ebone)) {
const bPoseChannel *pchan = BKE_pose_channel_find_name(obedit->pose, ebone->name);
if (pchan) {
@@ -1497,11 +1817,11 @@ static void select_similar_children(bContext *C)
bArmature *arm = obedit->data;
EditBone *ebone_act = CTX_data_active_bone(C);
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
ebone_iter->temp.ebone = ebone_iter->parent;
}
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
is_ancestor(ebone_iter, ebone_act);
if (ebone_iter->temp.ebone == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
@@ -1519,7 +1839,7 @@ static void select_similar_children_immediate(bContext *C)
bArmature *arm = obedit->data;
EditBone *ebone_act = CTX_data_active_bone(C);
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
if (ebone_iter->parent == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
ED_armature_ebone_select_set(ebone_iter, true);
}
@@ -1539,7 +1859,7 @@ static void select_similar_siblings(bContext *C)
return;
}
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
if (ebone_iter->parent == ebone_act->parent && EBONE_SELECTABLE(arm, ebone_iter)) {
ED_armature_ebone_select_set(ebone_iter, true);
}
@@ -1624,7 +1944,11 @@ void ARMATURE_OT_select_similar(wmOperatorType *ot)
RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
}
-/* ********************* select hierarchy operator ************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Hierarchy Operator
+ * \{ */
/* No need to convert to multi-objects. Just like we keep the non-active bones
* selected we then keep the non-active objects untouched (selected/unselected). */
@@ -1730,7 +2054,11 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
-/****************** Mirror Select ****************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Mirror Operator
+ * \{ */
/**
* \note clone of #pose_select_mirror_exec keep in sync
@@ -1815,7 +2143,11 @@ void ARMATURE_OT_select_mirror(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
-/****************** Select Path ****************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Path Operator
+ * \{ */
static bool armature_shortest_path_select(
bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child, bool use_parent, bool is_test)
@@ -1859,7 +2191,7 @@ static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const
BKE_object_update_select_id(CTX_data_main(C));
ebone_src = arm->act_edbone;
- ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst);
+ ebone_dst = ED_armature_pick_ebone(C, event->mval, false, &base_dst);
/* fallback to object selection */
if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
@@ -1941,3 +2273,5 @@ void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/** \} */
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index c772590ed21..61d8856afbc 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -23,8 +23,8 @@
* \ingroup edarmature
*/
-#include "DNA_mesh_types.h"
#include "DNA_armature_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -121,7 +121,7 @@ static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
* If such a vertex group already exist the routine exits.
*/
if (!(bone->flag & BONE_NO_DEFORM)) {
- if (!defgroup_find_name(ob, bone->name)) {
+ if (!BKE_object_defgroup_find_name(ob, bone->name)) {
BKE_object_defgroup_add_name(ob, bone->name);
return 1;
}
@@ -175,7 +175,7 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
}
if (!data->is_weight_paint || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
- if (!(defgroup = defgroup_find_name(ob, bone->name))) {
+ if (!(defgroup = BKE_object_defgroup_find_name(ob, bone->name))) {
defgroup = BKE_object_defgroup_add_name(ob, bone->name);
}
else if (defgroup->flag & DG_LOCK_WEIGHT) {
@@ -401,7 +401,7 @@ static void add_verts_to_dgroups(ReportList *reports,
char name_flip[MAXBONENAME];
BLI_string_flip_side_name(name_flip, dgroup->name, false, sizeof(name_flip));
- dgroupflip[j] = defgroup_find_name(ob, name_flip);
+ dgroupflip[j] = BKE_object_defgroup_find_name(ob, name_flip);
}
}
@@ -418,7 +418,7 @@ static void add_verts_to_dgroups(ReportList *reports,
BKE_mesh_foreach_mapped_vert_coords_get(me_eval, verts, mesh->totvert);
vertsfilled = 1;
}
- else if (modifiers_findByType(ob, eModifierType_Subsurf)) {
+ else if (BKE_modifiers_findby_type(ob, eModifierType_Subsurf)) {
/* is subsurf on? Lets use the verts on the limit surface then.
* = same amount of vertices as mesh, but vertices moved to the
* subsurfed position, like for 'optimal'. */
@@ -459,7 +459,7 @@ static void add_verts_to_dgroups(ReportList *reports,
}
/* only generated in some cases but can call anyway */
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
+ ED_mesh_mirror_spatial_table_end(ob);
/* free the memory allocated */
MEM_freeN(bonelist);
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 451148ed936..cf7f6699e5e 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -92,7 +92,7 @@ void ED_armature_edit_validate_active(struct bArmature *arm)
void ED_armature_edit_refresh_layer_used(bArmature *arm)
{
arm->layer_used = 0;
- for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
arm->layer_used |= ebo->layer;
}
}
@@ -142,7 +142,7 @@ void bone_free(bArmature *arm, EditBone *bone)
}
/* Clear references from other edit bones. */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (ebone->bbone_next == bone) {
ebone->bbone_next = NULL;
}
@@ -196,13 +196,12 @@ bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebon
* \param ebone_child_tot: Size of the ebone_child array
* \return The shared parent or NULL.
*/
-EditBone *ED_armature_ebone_find_shared_parent(EditBone *ebone_child[],
- const unsigned int ebone_child_tot)
+EditBone *ED_armature_ebone_find_shared_parent(EditBone *ebone_child[], const uint ebone_child_tot)
{
- unsigned int i;
+ uint i;
EditBone *ebone_iter;
-#define EBONE_TEMP_UINT(ebone) (*((unsigned int *)(&((ebone)->temp))))
+#define EBONE_TEMP_UINT(ebone) (*((uint *)(&((ebone)->temp))))
/* clear all */
for (i = 0; i < ebone_child_tot; i++) {
@@ -473,7 +472,7 @@ void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bo
void ED_armature_edit_transform_mirror_update(Object *obedit)
{
bArmature *arm = obedit->data;
- for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
ED_armature_ebone_transform_mirror_update(arm, ebo, true);
}
}
@@ -482,10 +481,10 @@ void ED_armature_edit_transform_mirror_update(Object *obedit)
/* Armature EditMode Conversions */
/* converts Bones to EditBone list, used for tools as well */
-static EditBone *make_boneList_rec(ListBase *edbo,
- ListBase *bones,
- EditBone *parent,
- Bone *actBone)
+static EditBone *make_boneList_recursive(ListBase *edbo,
+ ListBase *bones,
+ EditBone *parent,
+ Bone *actBone)
{
EditBone *eBone;
EditBone *eBoneAct = NULL;
@@ -562,9 +561,9 @@ static EditBone *make_boneList_rec(ListBase *edbo,
BLI_addtail(edbo, eBone);
- /* Add children if necessary */
+ /* Add children if necessary. */
if (curBone->childbase.first) {
- eBoneTest = make_boneList_rec(edbo, &curBone->childbase, eBone, actBone);
+ eBoneTest = make_boneList_recursive(edbo, &curBone->childbase, eBone, actBone);
if (eBoneTest) {
eBoneAct = eBoneTest;
}
@@ -581,7 +580,7 @@ static EditBone *make_boneList_rec(ListBase *edbo,
static EditBone *find_ebone_link(ListBase *edbo, Bone *link)
{
if (link != NULL) {
- for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, edbo) {
if (ebone->temp.bone == link) {
return ebone;
}
@@ -595,9 +594,9 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, struct Bone *actBone)
{
BLI_assert(!edbo->first && !edbo->last);
- EditBone *active = make_boneList_rec(edbo, bones, NULL, actBone);
+ EditBone *active = make_boneList_recursive(edbo, bones, NULL, actBone);
- for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, edbo) {
Bone *bone = ebone->temp.bone;
/* Convert custom B-Bone handle links. */
@@ -677,7 +676,7 @@ static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelis
curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
- /* and set restposition again */
+ /* And set rest-position again. */
BKE_armature_where_is_bone(curBone, curBone->parent, false);
break;
}
@@ -704,7 +703,8 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
for (eBone = arm->edbo->first; eBone; eBone = neBone) {
float len_sq = len_squared_v3v3(eBone->head, eBone->tail);
neBone = eBone->next;
- if (len_sq <= SQUARE(0.000001f)) { /* FLT_EPSILON is too large? */
+ /* TODO(sergey): How to ensure this is a constexpr? */
+ if (len_sq <= square_f(0.000001f)) { /* FLT_EPSILON is too large? */
EditBone *fBone;
/* Find any bones that refer to this bone */
@@ -720,7 +720,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
}
}
- /* Copy the bones from the editData into the armature */
+ /* Copy the bones from the edit-data into the armature. */
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
newBone = MEM_callocN(sizeof(Bone), "bone");
eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */
@@ -818,7 +818,7 @@ void ED_armature_edit_free(struct bArmature *arm)
{
EditBone *eBone;
- /* Clear the editbones list */
+ /* Clear the edit-bones list. */
if (arm->edbo) {
if (arm->edbo->first) {
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c
index 4e3ab11a9f7..a3a73f8d509 100644
--- a/source/blender/editors/armature/editarmature_undo.c
+++ b/source/blender/editors/armature/editarmature_undo.c
@@ -29,6 +29,7 @@
#include "DNA_object_types.h"
#include "BLI_array_utils.h"
+#include "BLI_listbase.h"
#include "BKE_context.h"
#include "BKE_layer.h"
@@ -42,8 +43,8 @@
#include "ED_undo.h"
#include "ED_util.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
/** We only need this locally. */
static CLG_LogRef LOG = {"ed.undo.armature"};
@@ -94,7 +95,7 @@ static void *undoarm_from_editarm(UndoArmature *uarm, bArmature *arm)
ED_armature_ebone_listbase_temp_clear(&uarm->lb);
- for (EditBone *ebone = uarm->lb.first; ebone; ebone = ebone->next) {
+ LISTBASE_FOREACH (EditBone *, ebone, &uarm->lb) {
uarm->undo_size += sizeof(EditBone);
}
@@ -108,7 +109,8 @@ static void undoarm_free_data(UndoArmature *uarm)
static Object *editarm_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
if (obedit && obedit->type == OB_ARMATURE) {
bArmature *arm = obedit->data;
if (arm->edbo != NULL) {
@@ -151,8 +153,7 @@ static bool armature_undosys_step_encode(struct bContext *C, struct Main *bmain,
* outside of this list will be moved out of edit-mode when reading back undo steps. */
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, NULL, &objects_len);
+ Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
us->elems_len = objects_len;
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 6bf507df421..d8a6a22a7df 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -21,16 +21,16 @@
#include "MEM_guardedalloc.h"
-#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
+#include "BLI_alloca.h"
#include "BLI_edgehash.h"
+#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_string.h"
-#include "BLI_alloca.h"
#include "BLT_translation.h"
@@ -39,8 +39,8 @@
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
-#include "ED_mesh.h"
#include "ED_armature.h"
+#include "ED_mesh.h"
#include "DEG_depsgraph.h"
@@ -1549,7 +1549,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
}
}
else {
- modifier_setError(&mmd->modifier, "Failed to find bind solution (increase precision?)");
+ BKE_modifier_set_error(&mmd->modifier, "Failed to find bind solution (increase precision?)");
error("Mesh Deform: failed to find bind solution.");
break;
}
@@ -1753,7 +1753,7 @@ void ED_mesh_deform_bind_callback(MeshDeformModifierData *mmd,
int totvert,
float cagemat[4][4])
{
- MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)modifier_get_original(
+ MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)BKE_modifier_get_original(
&mmd->modifier);
MeshDeformBind mdb;
MVert *mvert;
@@ -1799,7 +1799,7 @@ void ED_mesh_deform_bind_callback(MeshDeformModifierData *mmd,
MEM_freeN(mdb.vertexcos);
/* compact weights */
- modifier_mdef_compact_influences((ModifierData *)mmd_orig);
+ BKE_modifier_mdef_compact_influences((ModifierData *)mmd_orig);
end_progress_bar();
waitcursor(0);
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index ad115896a43..daab945c106 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -24,24 +24,24 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_action.h"
-#include "BKE_anim.h"
+#include "BKE_anim_visualization.h"
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
-#include "BKE_layer.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
@@ -57,8 +57,8 @@
#include "ED_anim_api.h"
#include "ED_armature.h"
#include "ED_keyframing.h"
-#include "ED_screen.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "ED_view3d.h"
#include "UI_interface.h"
@@ -75,12 +75,12 @@
/* matches logic with ED_operator_posemode_context() */
Object *ED_pose_object_from_context(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Object *ob;
/* Since this call may also be used from the buttons window,
* we need to check for where to get the object. */
- if (sa && sa->spacetype == SPACE_PROPERTIES) {
+ if (area && area->spacetype == SPACE_PROPERTIES) {
ob = ED_object_context(C);
}
else {
@@ -280,7 +280,7 @@ static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEven
/* show popup dialog to allow editing of range... */
// FIXME: hardcoded dimensions here are just arbitrary
- return WM_operator_props_dialog_popup(C, op, 200, 200);
+ return WM_operator_props_dialog_popup(C, op, 200);
}
/* For the object with pose/action: create path curves for selected bones
@@ -665,6 +665,11 @@ static int pose_bone_rotmode_exec(bContext *C, wmOperator *op)
/* set rotation mode of selected bones */
CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob) {
+ /* use API Method for conversions... */
+ BKE_rotMode_change_values(
+ pchan->quat, pchan->eul, pchan->rotAxis, &pchan->rotAngle, pchan->rotmode, (short)mode);
+
+ /* finally, set the new rotation type */
pchan->rotmode = mode;
if (prev_ob != ob) {
diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c
index 3ae9976c948..c10e204e3a4 100644
--- a/source/blender/editors/armature/pose_group.c
+++ b/source/blender/editors/armature/pose_group.c
@@ -31,8 +31,8 @@
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
-#include "BKE_armature.h"
#include "BKE_action.h"
+#include "BKE_armature.h"
#include "BKE_context.h"
#include "DEG_depsgraph.h"
@@ -44,6 +44,7 @@
#include "WM_types.h"
#include "ED_armature.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -484,6 +485,7 @@ static int pose_group_select_exec(bContext *C, wmOperator *UNUSED(op))
bArmature *arm = ob->data;
DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ ED_outliner_select_sync_from_pose_bone_tag(C);
return OPERATOR_FINISHED;
}
@@ -518,6 +520,7 @@ static int pose_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
bArmature *arm = ob->data;
DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ ED_outliner_select_sync_from_pose_bone_tag(C);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 4cda7f264aa..aa57fb5844d 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -21,8 +21,8 @@
* \ingroup edarmature
*/
-#include <string.h>
#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -41,7 +41,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
@@ -63,10 +63,10 @@
#include "ED_anim_api.h"
#include "ED_armature.h"
#include "ED_keyframes_draw.h"
-#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
-#include "ED_screen.h"
+#include "ED_keyframing.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "armature_intern.h"
@@ -161,16 +161,16 @@ static TimeMarker *poselib_get_active_pose(bAction *act)
/* XXX C can be zero */
static Object *get_poselib_object(bContext *C)
{
- ScrArea *sa;
+ ScrArea *area;
/* sanity check */
if (C == NULL) {
return NULL;
}
- sa = CTX_wm_area(C);
+ area = CTX_wm_area(C);
- if (sa && (sa->spacetype == SPACE_PROPERTIES)) {
+ if (area && (area->spacetype == SPACE_PROPERTIES)) {
return ED_object_context(C);
}
else {
@@ -626,7 +626,7 @@ static int poselib_remove_exec(bContext *C, wmOperator *op)
/* remove relevant keyframes */
for (fcu = act->curves.first; fcu; fcu = fcu->next) {
BezTriple *bezt;
- unsigned int i;
+ uint i;
if (fcu->bezt) {
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
@@ -870,7 +870,7 @@ typedef struct tPoseLib_PreviewData {
/** active scene. */
Scene *scene;
/** active area. */
- ScrArea *sa;
+ ScrArea *area;
/** RNA-Pointer to Object 'ob' .*/
PointerRNA rna_ptr;
@@ -1171,7 +1171,7 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
/* do header print - if interactively previewing */
if (pld->state == PL_PREVIEW_RUNNING) {
if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
- ED_area_status_text(pld->sa, TIP_("PoseLib Previewing Pose: [Showing Original Pose]"));
+ ED_area_status_text(pld->area, TIP_("PoseLib Previewing Pose: [Showing Original Pose]"));
ED_workspace_status_text(C, TIP_("Use Tab to start previewing poses again"));
}
else if (pld->searchstr[0]) {
@@ -1200,7 +1200,7 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
"Current Pose - \"%s\""),
tempstr,
markern);
- ED_area_status_text(pld->sa, pld->headerstr);
+ ED_area_status_text(pld->area, pld->headerstr);
ED_workspace_status_text(C, TIP_("Use ScrollWheel or PageUp/Down to change pose"));
}
else {
@@ -1208,7 +1208,7 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
sizeof(pld->headerstr),
TIP_("PoseLib Previewing Pose: \"%s\""),
pld->marker->name);
- ED_area_status_text(pld->sa, pld->headerstr);
+ ED_area_status_text(pld->area, pld->headerstr);
ED_workspace_status_text(C, NULL);
}
}
@@ -1323,13 +1323,11 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
}
/* specially handle events for searching */
-static void poselib_preview_handle_search(tPoseLib_PreviewData *pld,
- unsigned short event,
- char ascii)
+static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, ushort event, char ascii)
{
/* try doing some form of string manipulation first */
switch (event) {
- case BACKSPACEKEY:
+ case EVT_BACKSPACEKEY:
if (pld->searchstr[0] && pld->search_cursor) {
short len = strlen(pld->searchstr);
short index = pld->search_cursor;
@@ -1347,7 +1345,7 @@ static void poselib_preview_handle_search(tPoseLib_PreviewData *pld,
}
break;
- case DELKEY:
+ case EVT_DELKEY:
if (pld->searchstr[0] && pld->searchstr[1]) {
short len = strlen(pld->searchstr);
short index = pld->search_cursor;
@@ -1414,16 +1412,16 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
switch (event->type) {
/* exit - cancel */
- case ESCKEY:
+ case EVT_ESCKEY:
case RIGHTMOUSE:
pld->state = PL_PREVIEW_CANCEL;
break;
/* exit - confirm */
case LEFTMOUSE:
- case RETKEY:
- case PADENTER:
- case SPACEKEY:
+ case EVT_RETKEY:
+ case EVT_PADENTER:
+ case EVT_SPACEKEY:
pld->state = PL_PREVIEW_CONFIRM;
break;
@@ -1431,18 +1429,18 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
/* we add pass through here, so that the operators responsible for these can still run,
* even though we still maintain control (as RUNNING_MODAL flag is still set too)
*/
- case PAD0:
- case PAD1:
- case PAD2:
- case PAD3:
- case PAD4:
- case PAD5:
- case PAD6:
- case PAD7:
- case PAD8:
- case PAD9:
- case PADPLUSKEY:
- case PADMINUS:
+ case EVT_PAD0:
+ case EVT_PAD1:
+ case EVT_PAD2:
+ case EVT_PAD3:
+ case EVT_PAD4:
+ case EVT_PAD5:
+ case EVT_PAD6:
+ case EVT_PAD7:
+ case EVT_PAD8:
+ case EVT_PAD9:
+ case EVT_PADPLUSKEY:
+ case EVT_PADMINUS:
case MIDDLEMOUSE:
case MOUSEMOVE:
// pld->redraw = PL_PREVIEW_REDRAWHEADER;
@@ -1450,7 +1448,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
break;
/* quicky compare to original */
- case TABKEY:
+ case EVT_TABKEY:
pld->flag &= ~PL_PREVIEW_SHOWORIGINAL;
pld->redraw = PL_PREVIEW_REDRAWALL;
break;
@@ -1464,53 +1462,53 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
/* searching takes priority over normal activity */
switch (event->type) {
/* exit - cancel */
- case ESCKEY:
+ case EVT_ESCKEY:
case RIGHTMOUSE:
pld->state = PL_PREVIEW_CANCEL;
break;
/* exit - confirm */
case LEFTMOUSE:
- case RETKEY:
- case PADENTER:
- case SPACEKEY:
+ case EVT_RETKEY:
+ case EVT_PADENTER:
+ case EVT_SPACEKEY:
pld->state = PL_PREVIEW_CONFIRM;
break;
/* toggle between original pose and poselib pose*/
- case TABKEY:
+ case EVT_TABKEY:
pld->flag |= PL_PREVIEW_SHOWORIGINAL;
pld->redraw = PL_PREVIEW_REDRAWALL;
break;
/* change to previous pose (cyclic) */
- case PAGEUPKEY:
+ case EVT_PAGEUPKEY:
case WHEELUPMOUSE:
poselib_preview_get_next(pld, -1);
pld->redraw = PL_PREVIEW_REDRAWALL;
break;
/* change to next pose (cyclic) */
- case PAGEDOWNKEY:
+ case EVT_PAGEDOWNKEY:
case WHEELDOWNMOUSE:
poselib_preview_get_next(pld, 1);
pld->redraw = PL_PREVIEW_REDRAWALL;
break;
/* jump 5 poses (cyclic, back) */
- case DOWNARROWKEY:
+ case EVT_DOWNARROWKEY:
poselib_preview_get_next(pld, -5);
pld->redraw = PL_PREVIEW_REDRAWALL;
break;
/* jump 5 poses (cyclic, forward) */
- case UPARROWKEY:
+ case EVT_UPARROWKEY:
poselib_preview_get_next(pld, 5);
pld->redraw = PL_PREVIEW_REDRAWALL;
break;
/* change to next pose or searching cursor control */
- case RIGHTARROWKEY:
+ case EVT_RIGHTARROWKEY:
if (pld->searchstr[0]) {
/* move text-cursor to the right */
if (pld->search_cursor < strlen(pld->searchstr)) {
@@ -1526,7 +1524,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
break;
/* change to next pose or searching cursor control */
- case LEFTARROWKEY:
+ case EVT_LEFTARROWKEY:
if (pld->searchstr[0]) {
/* move text-cursor to the left */
if (pld->search_cursor) {
@@ -1542,7 +1540,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
break;
/* change to first pose or start of searching string */
- case HOMEKEY:
+ case EVT_HOMEKEY:
if (pld->searchstr[0]) {
pld->search_cursor = 0;
pld->redraw = PL_PREVIEW_REDRAWHEADER;
@@ -1557,7 +1555,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
break;
/* change to last pose or start of searching string */
- case ENDKEY:
+ case EVT_ENDKEY:
if (pld->searchstr[0]) {
pld->search_cursor = strlen(pld->searchstr);
pld->redraw = PL_PREVIEW_REDRAWHEADER;
@@ -1582,18 +1580,18 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
break;
/* view manipulation, or searching */
- case PAD0:
- case PAD1:
- case PAD2:
- case PAD3:
- case PAD4:
- case PAD5:
- case PAD6:
- case PAD7:
- case PAD8:
- case PAD9:
- case PADPLUSKEY:
- case PADMINUS:
+ case EVT_PAD0:
+ case EVT_PAD1:
+ case EVT_PAD2:
+ case EVT_PAD3:
+ case EVT_PAD4:
+ case EVT_PAD5:
+ case EVT_PAD6:
+ case EVT_PAD7:
+ case EVT_PAD8:
+ case EVT_PAD9:
+ case EVT_PADPLUSKEY:
+ case EVT_PADMINUS:
if (pld->searchstr[0]) {
/* searching... */
poselib_preview_handle_search(pld, event->type, event->ascii);
@@ -1633,7 +1631,7 @@ static void poselib_preview_init_data(bContext *C, wmOperator *op)
pld->act = (ob) ? (ob->poselib) : NULL;
pld->scene = CTX_data_scene(C);
- pld->sa = CTX_wm_area(C);
+ pld->area = CTX_wm_area(C);
/* get starting pose based on RNA-props for this operator */
if (pose_index == -1) {
@@ -1704,7 +1702,7 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op)
TimeMarker *marker = pld->marker;
/* redraw the header so that it doesn't show any of our stuff anymore */
- ED_area_status_text(pld->sa, NULL);
+ ED_area_status_text(pld->area, NULL);
ED_workspace_status_text(C, NULL);
/* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 0c359b2a757..9525fcf2154 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -37,10 +37,10 @@
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
-#include "BKE_object.h"
-#include "BKE_report.h"
#include "BKE_layer.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
#include "DEG_depsgraph.h"
@@ -141,7 +141,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
View3D *v3d,
Base *base,
- const unsigned int *buffer,
+ const uint *buffer,
short hits,
bool extend,
bool deselect,
@@ -156,12 +156,12 @@ bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
}
Object *ob_act = OBACT(view_layer);
- Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ BLI_assert(OBEDIT_FROM_VIEW_LAYER(view_layer) == NULL);
/* Callers happen to already get the active base */
Base *base_dummy = NULL;
- nearBone = get_bone_from_selectbuffer(
- &base, 1, obedit != NULL, buffer, hits, 1, do_nearest, &base_dummy);
+ nearBone = ED_armature_pick_bone_from_selectbuffer(
+ &base, 1, buffer, hits, 1, do_nearest, &base_dummy);
/* if the bone cannot be affected, don't do anything */
if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
@@ -263,7 +263,7 @@ void ED_armature_pose_select_in_wpaint_mode(ViewLayer *view_layer, Base *base_se
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);
+ ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob_active, &virtualModifierData);
for (; md; md = md->next) {
if (md->type == eModifierType_Armature) {
ArmatureModifierData *amd = (ArmatureModifierData *)md;
@@ -323,7 +323,7 @@ bool ED_pose_deselect_all(Object *ob, int select_mode, const bool ignore_visibil
static bool ed_pose_is_any_selected(Object *ob, bool ignore_visibility)
{
bArmature *arm = ob->data;
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
if (pchan->bone->flag & BONE_SELECTED) {
return true;
@@ -413,7 +413,7 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
view3d_operator_needs_opengl(C);
Base *base = NULL;
- bone = get_nearest_bone(C, event->mval, !extend, &base);
+ bone = ED_armature_pick_bone(C, event->mval, !extend, &base);
if (!bone) {
return OPERATOR_CANCELLED;
@@ -443,7 +443,7 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
}
/* Select children */
- for (curBone = bone->childbase.first; curBone; curBone = next) {
+ for (curBone = bone->childbase.first; curBone; curBone = curBone->next) {
selectconnected_posebonechildren(base->object, curBone, extend);
}
@@ -454,22 +454,22 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
return OPERATOR_FINISHED;
}
-static bool pose_select_linked_poll(bContext *C)
+static bool pose_select_linked_pick_poll(bContext *C)
{
return (ED_operator_view3d_active(C) && ED_operator_posemode(C));
}
-void POSE_OT_select_linked(wmOperatorType *ot)
+void POSE_OT_select_linked_pick(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select Connected";
- ot->idname = "POSE_OT_select_linked";
- ot->description = "Select bones related to selected ones by parent/child relationships";
+ ot->idname = "POSE_OT_select_linked_pick";
+ ot->description = "Select bones linked by parent/child connections under the mouse cursor";
/* callbacks */
/* leave 'exec' unset */
ot->invoke = pose_select_connected_invoke;
- ot->poll = pose_select_linked_poll;
+ ot->poll = pose_select_linked_pick_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -482,6 +482,62 @@ void POSE_OT_select_linked(wmOperatorType *ot)
"Extend selection instead of deselecting everything first");
}
+static int pose_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Bone *curBone, *next = NULL;
+
+ CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
+ if ((pchan->bone->flag & BONE_SELECTED) == 0) {
+ continue;
+ }
+
+ bArmature *arm = ob->data;
+
+ /* Select parents */
+ for (curBone = pchan->bone; curBone; curBone = next) {
+ if (PBONE_SELECTABLE(arm, curBone)) {
+ curBone->flag |= BONE_SELECTED;
+
+ if (curBone->flag & BONE_CONNECTED) {
+ next = curBone->parent;
+ }
+ else {
+ next = NULL;
+ }
+ }
+ else {
+ next = NULL;
+ }
+ }
+
+ /* Select children */
+ for (curBone = pchan->bone->childbase.first; curBone; curBone = curBone->next) {
+ selectconnected_posebonechildren(ob, curBone, false);
+ }
+ ED_pose_bone_select_tag_update(ob);
+ }
+ CTX_DATA_END;
+
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Connected";
+ ot->idname = "POSE_OT_select_linked";
+ ot->description = "Select all bones linked by parent/child connections to the current selection";
+
+ /* callbacks */
+ ot->exec = pose_select_linked_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* -------------------------------------- */
static int pose_de_select_all_exec(bContext *C, wmOperator *op)
@@ -497,7 +553,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
Object *ob_prev = NULL;
- /* Set the flags */
+ /* Set the flags. */
CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
bArmature *arm = ob->data;
pose_do_bone_select(pchan, action);
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 7ed41b5b4d0..481282d6df3 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -23,9 +23,9 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_dlrbTree.h"
+#include "BLI_math.h"
#include "BLT_translation.h"
@@ -86,9 +86,9 @@ typedef struct tPoseSlideOp {
/** current scene */
Scene *scene;
/** area that we're operating in (needed for modal()) */
- ScrArea *sa;
+ ScrArea *area;
/** region that we're operating in (needed for modal()) */
- ARegion *ar;
+ ARegion *region;
/** len of the PoseSlideObject array. */
uint objects_len;
@@ -197,8 +197,8 @@ static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
/* get info from context */
pso->scene = CTX_data_scene(C);
- pso->sa = CTX_wm_area(C); /* only really needed when doing modal() */
- pso->ar = CTX_wm_region(C); /* only really needed when doing modal() */
+ pso->area = CTX_wm_area(C); /* only really needed when doing modal() */
+ pso->region = CTX_wm_region(C); /* only really needed when doing modal() */
pso->cframe = pso->scene->r.cfra;
pso->mode = mode;
@@ -544,71 +544,56 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
/* only if all channels exist, proceed */
if (fcu_w && fcu_x && fcu_y && fcu_z) {
- float quat_prev[4], quat_prev_orig[4];
- float quat_next[4], quat_next_orig[4];
- float quat_curr[4], quat_curr_orig[4];
float quat_final[4];
- copy_qt_qt(quat_curr_orig, pchan->quat);
-
- /* get 2 quats */
- quat_prev_orig[0] = evaluate_fcurve(fcu_w, prevFrameF);
- quat_prev_orig[1] = evaluate_fcurve(fcu_x, prevFrameF);
- quat_prev_orig[2] = evaluate_fcurve(fcu_y, prevFrameF);
- quat_prev_orig[3] = evaluate_fcurve(fcu_z, prevFrameF);
-
- quat_next_orig[0] = evaluate_fcurve(fcu_w, nextFrameF);
- quat_next_orig[1] = evaluate_fcurve(fcu_x, nextFrameF);
- quat_next_orig[2] = evaluate_fcurve(fcu_y, nextFrameF);
- quat_next_orig[3] = evaluate_fcurve(fcu_z, nextFrameF);
-
- normalize_qt_qt(quat_prev, quat_prev_orig);
- normalize_qt_qt(quat_next, quat_next_orig);
- normalize_qt_qt(quat_curr, quat_curr_orig);
-
/* perform blending */
if (pso->mode == POSESLIDE_BREAKDOWN) {
/* 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);
- }
- else if (pso->mode == POSESLIDE_PUSH) {
- float quat_diff[4];
+ float quat_prev[4];
+ float quat_next[4];
+
+ quat_prev[0] = evaluate_fcurve(fcu_w, prevFrameF);
+ quat_prev[1] = evaluate_fcurve(fcu_x, prevFrameF);
+ quat_prev[2] = evaluate_fcurve(fcu_y, prevFrameF);
+ quat_prev[3] = evaluate_fcurve(fcu_z, prevFrameF);
- /* calculate the delta transform from the previous to the current */
- /* TODO: investigate ways to favour one transform more? */
- sub_qt_qtqt(quat_diff, quat_curr, quat_prev);
+ quat_next[0] = evaluate_fcurve(fcu_w, nextFrameF);
+ quat_next[1] = evaluate_fcurve(fcu_x, nextFrameF);
+ quat_next[2] = evaluate_fcurve(fcu_y, nextFrameF);
+ quat_next[3] = evaluate_fcurve(fcu_z, nextFrameF);
- /* increase the original by the delta transform, by an amount determined by percentage */
- add_qt_qtqt(quat_final, quat_curr, quat_diff, pso->percentage);
+ normalize_qt(quat_prev);
+ normalize_qt(quat_next);
- normalize_qt(quat_final);
+ interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage);
}
else {
- BLI_assert(pso->mode == POSESLIDE_RELAX);
- float quat_interp[4], quat_final_prev[4];
- /* TODO: maybe a sensitivity ctrl on top of this is needed */
- int iters = (int)ceil(10.0f * pso->percentage);
+ /* POSESLIDE_PUSH and POSESLIDE_RELAX. */
+ float quat_breakdown[4];
+ float quat_curr[4];
- copy_qt_qt(quat_final, quat_curr);
+ copy_qt_qt(quat_curr, pchan->quat);
- /* perform this blending several times until a satisfactory result is reached */
- while (iters-- > 0) {
- /* calculate the interpolation between the endpoints */
- interp_qt_qtqt(quat_interp,
- quat_prev,
- quat_next,
- (cframe - pso->prevFrame) / (pso->nextFrame - pso->prevFrame));
+ quat_breakdown[0] = evaluate_fcurve(fcu_w, cframe);
+ quat_breakdown[1] = evaluate_fcurve(fcu_x, cframe);
+ quat_breakdown[2] = evaluate_fcurve(fcu_y, cframe);
+ quat_breakdown[3] = evaluate_fcurve(fcu_z, cframe);
- normalize_qt_qt(quat_final_prev, quat_final);
+ normalize_qt(quat_breakdown);
+ normalize_qt(quat_curr);
- /* tricky interpolations - blending between original and new */
- interp_qt_qtqt(quat_final, quat_final_prev, quat_interp, 1.0f / 6.0f);
+ if (pso->mode == POSESLIDE_PUSH) {
+ interp_qt_qtqt(quat_final, quat_breakdown, quat_curr, 1.0f + pso->percentage);
+ }
+ else {
+ BLI_assert(pso->mode == POSESLIDE_RELAX);
+ interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, pso->percentage);
}
}
/* Apply final to the pose bone, keeping compatible for similar keyframe positions. */
- quat_to_compatible_quat(pchan->quat, quat_final, quat_curr_orig);
+ quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat);
}
/* free the path now */
@@ -904,7 +889,7 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
limits_str);
}
- ED_area_status_text(pso->sa, status_str);
+ ED_area_status_text(pso->area, status_str);
}
/* common code for invoke() methods */
@@ -1004,7 +989,7 @@ static void pose_slide_mouse_update_percentage(tPoseSlideOp *pso,
wmOperator *op,
const wmEvent *event)
{
- pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
+ pso->percentage = (event->x - pso->region->winrct.xmin) / ((float)pso->region->winx);
RNA_float_set(op->ptr, "percentage", pso->percentage);
}
@@ -1067,11 +1052,11 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case LEFTMOUSE: /* confirm */
- case RETKEY:
- case PADENTER: {
+ case EVT_RETKEY:
+ case EVT_PADENTER: {
if (event->val == KM_PRESS) {
/* return to normal cursor and header status */
- ED_area_status_text(pso->sa, NULL);
+ ED_area_status_text(pso->area, NULL);
WM_cursor_modal_restore(win);
/* insert keyframes as required... */
@@ -1084,11 +1069,11 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
- case ESCKEY: /* cancel */
+ case EVT_ESCKEY: /* cancel */
case RIGHTMOUSE: {
if (event->val == KM_PRESS) {
/* return to normal cursor and header status */
- ED_area_status_text(pso->sa, NULL);
+ ED_area_status_text(pso->area, NULL);
WM_cursor_modal_restore(win);
/* reset transforms back to original state */
@@ -1141,31 +1126,31 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
/* Transform Channel Limits */
/* XXX: Replace these hardcoded hotkeys with a modalmap that can be customised */
- case GKEY: /* Location */
+ case EVT_GKEY: /* Location */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_LOC);
do_pose_update = true;
break;
}
- case RKEY: /* Rotation */
+ case EVT_RKEY: /* Rotation */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_ROT);
do_pose_update = true;
break;
}
- case SKEY: /* Scale */
+ case EVT_SKEY: /* Scale */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_SIZE);
do_pose_update = true;
break;
}
- case BKEY: /* Bendy Bones */
+ case EVT_BKEY: /* Bendy Bones */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_BBONE_SHAPE);
do_pose_update = true;
break;
}
- case CKEY: /* Custom Properties */
+ case EVT_CKEY: /* Custom Properties */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_PROPS);
do_pose_update = true;
@@ -1174,19 +1159,19 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Axis Locks */
/* XXX: Hardcoded... */
- case XKEY: {
+ case EVT_XKEY: {
if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_X)) {
do_pose_update = true;
}
break;
}
- case YKEY: {
+ case EVT_YKEY: {
if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Y)) {
do_pose_update = true;
}
break;
}
- case ZKEY: {
+ case EVT_ZKEY: {
if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) {
do_pose_update = true;
}
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index d366978ba2b..1d2bf152777 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -207,12 +207,12 @@ typedef struct ApplyArmature_ParentState {
} ApplyArmature_ParentState;
/* Recursive walk for Apply To Selected mode; pstate NULL unless child of an applied bone. */
-static void applyarmature_process_selected_rec(bArmature *arm,
- bPose *pose,
- bPose *pose_eval,
- Bone *bone,
- ListBase *selected,
- ApplyArmature_ParentState *pstate)
+static void applyarmature_process_selected_recursive(bArmature *arm,
+ bPose *pose,
+ bPose *pose_eval,
+ Bone *bone,
+ ListBase *selected,
+ ApplyArmature_ParentState *pstate)
{
bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(pose_eval, bone->name);
@@ -333,8 +333,8 @@ static void applyarmature_process_selected_rec(bArmature *arm,
pstate = &new_pstate;
}
- for (Bone *child = bone->childbase.first; child; child = child->next) {
- applyarmature_process_selected_rec(arm, pose, pose_eval, child, selected, pstate);
+ LISTBASE_FOREACH (Bone *, child, &bone->childbase) {
+ applyarmature_process_selected_recursive(arm, pose, pose_eval, child, selected, pstate);
}
}
@@ -389,8 +389,9 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
if (use_selected) {
/* The selected only mode requires a recursive walk to handle parent-child relations. */
- for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
- applyarmature_process_selected_rec(arm, pose, ob_eval->pose, bone, &selected_bones, NULL);
+ LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
+ applyarmature_process_selected_recursive(
+ arm, pose, ob_eval->pose, bone, &selected_bones, NULL);
}
BLI_freelistN(&selected_bones);
@@ -710,6 +711,8 @@ static int pose_copy_exec(bContext *C, wmOperator *op)
* any datablock expansion?
*/
Main *temp_bmain = BKE_main_new();
+ STRNCPY(temp_bmain->name, BKE_main_blendfile_path_from_global());
+
Object ob_copy = *ob;
ob_copy.adt = NULL;
bArmature arm_copy = *((bArmature *)ob->data);
@@ -723,7 +726,7 @@ static int pose_copy_exec(bContext *C, wmOperator *op)
* existing on it's own.
*/
BKE_copybuffer_tag_ID(&ob_copy.id);
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer_pose.blend");
+ BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend");
BKE_copybuffer_save(temp_bmain, str, op->reports);
/* We clear the lists so no datablocks gets freed,
* This is required because objects in temp bmain shares same pointers
@@ -773,7 +776,9 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
/* Read copy buffer .blend file. */
char str[FILE_MAX];
Main *tmp_bmain = BKE_main_new();
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer_pose.blend");
+ STRNCPY(tmp_bmain->name, BKE_main_blendfile_path_from_global());
+
+ BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend");
if (!BKE_copybuffer_read(tmp_bmain, str, op->reports, FILTER_ID_OB)) {
BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty");
BKE_main_free(tmp_bmain);
@@ -1235,7 +1240,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
workob.adt = ob->adt;
workob.pose = dummyPose;
- BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false);
+ BKE_animsys_evaluate_animdata(&workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false);
/* copy back values, but on selected bones only */
for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index 8d2d7d790d2..e2038bdd2a3 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -23,8 +23,8 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -32,7 +32,7 @@
#include "DNA_scene_types.h"
#include "BKE_action.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_armature.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index 8c9309055c8..ff80c47baa8 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -40,6 +40,7 @@ set(SRC
editcurve.c
editcurve_add.c
editcurve_paint.c
+ editcurve_query.c
editcurve_select.c
editcurve_undo.c
editfont.c
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index 201ba2560dc..7d0a2e5edbc 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -142,14 +142,6 @@ void CURVE_OT_match_texture_space(struct wmOperatorType *ot);
struct GHash *ED_curve_keyindex_hash_duplicate(struct GHash *keyindex);
void ED_curve_keyindex_update_nurb(struct EditNurb *editnurb, struct Nurb *nu, struct Nurb *newnu);
-bool ED_curve_pick_vert(struct ViewContext *vc,
- short sel,
- struct Nurb **r_nurb,
- struct BezTriple **r_bezt,
- struct BPoint **r_bp,
- short *r_handle,
- struct Base **r_base);
-
/* helper functions */
void ed_editnurb_translate_flag(struct ListBase *editnurb, short flag, const float vec[3]);
bool ed_editnurb_extrude_flag(struct EditNurb *editnurb, const short flag);
@@ -189,6 +181,17 @@ void SURFACE_OT_primitive_nurbs_surface_cylinder_add(struct wmOperatorType *ot);
void SURFACE_OT_primitive_nurbs_surface_sphere_add(struct wmOperatorType *ot);
void SURFACE_OT_primitive_nurbs_surface_torus_add(struct wmOperatorType *ot);
+/* editcurve_query.c */
+bool ED_curve_pick_vert(struct ViewContext *vc,
+ short sel,
+ struct Nurb **r_nurb,
+ struct BezTriple **r_bezt,
+ struct BPoint **r_bp,
+ short *r_handle,
+ struct Base **r_base);
+void ED_curve_nurb_vert_selected_find(
+ Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp);
+
/* editcurve_paint.c */
void CURVE_OT_draw(struct wmOperatorType *ot);
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index 81c9c759188..02cb1ee8e1c 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -21,8 +21,8 @@
* \ingroup edcurve
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index e7803fdaafb..d6256f67066 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -21,22 +21,22 @@
* \ingroup edcurve
*/
+#include "DNA_anim_types.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_anim_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_array_utils.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLI_ghash.h"
+#include "BLI_math.h"
#include "BLT_translation.h"
#include "BKE_action.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
@@ -44,7 +44,7 @@
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_report.h"
@@ -56,13 +56,14 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_curve.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_transform_snap_object_context.h"
#include "ED_types.h"
#include "ED_view3d.h"
-#include "ED_curve.h"
#include "curve_intern.h"
@@ -81,6 +82,10 @@ static void adduplicateflagNurb(
static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split);
static bool curve_delete_vertices(Object *obedit, View3D *v3d);
+/* -------------------------------------------------------------------- */
+/** \name Utility Functions
+ * \{ */
+
ListBase *object_editcurve_get(Object *ob)
{
if (ob && ELEM(ob->type, OB_CURVE, OB_SURF)) {
@@ -90,7 +95,11 @@ ListBase *object_editcurve_get(Object *ob)
return NULL;
}
-/* ******************* PRINTS ********************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Debug Printing
+ * \{ */
#if 0
void printknots(Object *obedit)
@@ -118,7 +127,11 @@ void printknots(Object *obedit)
}
#endif
-/* ********************* Shape keys *************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Shape keys
+ * \{ */
static CVKeyIndex *init_cvKeyIndex(
void *cv, int key_index, int nu_index, int pt_index, int vertex_index)
@@ -897,7 +910,11 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
}
}
-/* ********************* Amimation data *************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Animation Data
+ * \{ */
static bool curve_is_animated(Curve *cu)
{
@@ -1114,7 +1131,11 @@ int ED_curve_updateAnimPaths(Main *bmain, Curve *cu)
return 1;
}
-/* ********************* LOAD and MAKE *************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Edit Mode Conversion (Make & Load)
+ * \{ */
static int *initialize_index_map(Object *obedit, int *r_old_totvert)
{
@@ -1354,7 +1375,11 @@ void ED_curve_editnurb_free(Object *obedit)
BKE_curve_editNurb_free(cu);
}
-/******************** separate operator ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Separate Operator
+ * \{ */
static int separate_exec(bContext *C, wmOperator *op)
{
@@ -1405,12 +1430,11 @@ static int separate_exec(bContext *C, wmOperator *op)
}
/* 2. Duplicate the object and data. */
- newbase = ED_object_add_duplicate(bmain,
- scene,
- view_layer,
- oldbase,
- /* 0 = fully linked. */
- 0);
+
+ /* Take into account user preferences for duplicating actions. */
+ short dupflag = (U.dupflag & USER_DUP_ACT);
+
+ newbase = ED_object_add_duplicate(bmain, scene, view_layer, oldbase, dupflag);
DEG_relations_tag_update(bmain);
newob = newbase->object;
@@ -1477,6 +1501,8 @@ static int separate_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
@@ -1496,7 +1522,11 @@ void CURVE_OT_separate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/******************** split operator ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split Operator
+ * \{ */
static int curve_split_exec(bContext *C, wmOperator *op)
{
@@ -1564,7 +1594,11 @@ void CURVE_OT_split(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************* FLAGS ********************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Flag Utility Functions
+ * \{ */
static bool isNurbselUV(const Nurb *nu, int flag, int *r_u, int *r_v)
{
@@ -2533,7 +2567,11 @@ static void adduplicateflagNurb(
}
}
-/**************** switch direction operator ***************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Switch Direction Operator
+ * \{ */
static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -2592,7 +2630,11 @@ void CURVE_OT_switch_direction(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/****************** set weight operator *******************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Weight Operator
+ * \{ */
static int set_goal_weight_exec(bContext *C, wmOperator *op)
{
@@ -2655,7 +2697,11 @@ void CURVE_OT_spline_weight_set(wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f);
}
-/******************* set radius operator ******************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Radius Operator
+ * \{ */
static int set_radius_exec(bContext *C, wmOperator *op)
{
@@ -2719,7 +2765,11 @@ void CURVE_OT_radius_set(wmOperatorType *ot)
ot->srna, "radius", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.0001f, 10.0f);
}
-/********************* smooth operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Smooth Vertices Operator
+ * \{ */
static void smooth_single_bezt(BezTriple *bezt,
const BezTriple *bezt_orig_prev,
@@ -2876,12 +2926,15 @@ void CURVE_OT_smooth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Smooth radius/weight/tilt
+/** \name Smooth Operator (Radius/Weight/Tilt) Utilities
*
- * TODO: make smoothing distance based
- * TODO: support cyclic curves
- */
+ * To do:
+ * - Make smoothing distance based.
+ * - Support cyclic curves.
+ * \{ */
static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, const int bp_offset)
{
@@ -3060,6 +3113,12 @@ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, cons
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Smooth Weight Operator
+ * \{ */
+
static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -3097,6 +3156,12 @@ void CURVE_OT_smooth_weight(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Smooth Radius Operator
+ * \{ */
+
static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -3134,6 +3199,12 @@ void CURVE_OT_smooth_radius(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Smooth Tilt Operator
+ * \{ */
+
static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -3171,7 +3242,11 @@ void CURVE_OT_smooth_tilt(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/********************** hide operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hide Operator
+ * \{ */
static int hide_exec(bContext *C, wmOperator *op)
{
@@ -3270,7 +3345,11 @@ void CURVE_OT_hide(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
}
-/********************** reveal operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Reveal Operator
+ * \{ */
static int reveal_exec(bContext *C, wmOperator *op)
{
@@ -3346,7 +3425,11 @@ void CURVE_OT_reveal(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
-/********************** subdivide operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Subdivide Operator
+ * \{ */
/**
* Divide the line segments associated with the currently selected
@@ -3509,6 +3592,7 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts)
memcpy(bpn, nextbp, sizeof(BPoint));
interp_v4_v4v4(bpn->vec, bp->vec, nextbp->vec, factor);
+ bpn->radius = interpf(bp->radius, nextbp->radius, factor);
bpn++;
}
}
@@ -3801,179 +3885,11 @@ void CURVE_OT_subdivide(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/******************** find nearest ************************/
-
-static void ED_curve_pick_vert__doClosest(
- void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
-{
- struct {
- BPoint *bp;
- BezTriple *bezt;
- Nurb *nurb;
- float dist;
- int hpoint, select;
- float mval_fl[2];
- bool is_changed;
- } *data = userData;
-
- short flag;
- float dist_test;
-
- if (bp) {
- flag = bp->f1;
- }
- else {
- if (beztindex == 0) {
- flag = bezt->f1;
- }
- else if (beztindex == 1) {
- flag = bezt->f2;
- }
- else {
- flag = bezt->f3;
- }
- }
-
- dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
- if ((flag & SELECT) == data->select) {
- dist_test += 5.0f;
- }
- if (bezt && beztindex == 1) {
- dist_test += 3.0f; /* middle points get a small disadvantage */
- }
-
- if (dist_test < data->dist) {
- data->dist = dist_test;
+/** \} */
- data->bp = bp;
- data->bezt = bezt;
- data->nurb = nu;
- data->hpoint = bezt ? beztindex : 0;
- data->is_changed = true;
- }
-}
-
-bool ED_curve_pick_vert(ViewContext *vc,
- short sel,
- Nurb **r_nurb,
- BezTriple **r_bezt,
- BPoint **r_bp,
- short *r_handle,
- Base **r_base)
-{
- /* (sel == 1): selected gets a disadvantage */
- /* in nurb and bezt or bp the nearest is written */
- /* return 0 1 2: handlepunt */
- struct {
- BPoint *bp;
- BezTriple *bezt;
- Nurb *nurb;
- float dist;
- int hpoint, select;
- float mval_fl[2];
- bool is_changed;
- } data = {NULL};
-
- data.dist = ED_view3d_select_dist_px();
- data.hpoint = 0;
- data.select = sel;
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
-
- uint bases_len;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
- vc->view_layer, vc->v3d, &bases_len);
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base = bases[base_index];
- data.is_changed = false;
-
- ED_view3d_viewcontext_init_object(vc, base->object);
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- nurbs_foreachScreenVert(vc, ED_curve_pick_vert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
- if (r_base && data.is_changed) {
- *r_base = base;
- }
- }
- MEM_freeN(bases);
-
- *r_nurb = data.nurb;
- *r_bezt = data.bezt;
- *r_bp = data.bp;
-
- if (r_handle) {
- *r_handle = data.hpoint;
- }
-
- return (data.bezt || data.bp);
-}
-
-static void findselectedNurbvert(
- Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp)
-{
- /* in nu and (bezt or bp) selected are written if there's 1 sel. */
- /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */
- ListBase *editnurb = &cu->editnurb->nurbs;
- Nurb *nu1;
- BezTriple *bezt1;
- BPoint *bp1;
- int a;
-
- *r_nu = NULL;
- *r_bezt = NULL;
- *r_bp = NULL;
-
- for (nu1 = editnurb->first; nu1; nu1 = nu1->next) {
- if (nu1->type == CU_BEZIER) {
- bezt1 = nu1->bezt;
- a = nu1->pntsu;
- while (a--) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1)) {
- if (*r_nu != NULL && *r_nu != nu1) {
- *r_nu = NULL;
- *r_bp = NULL;
- *r_bezt = NULL;
- return;
- }
- else if (*r_bezt || *r_bp) {
- *r_bp = NULL;
- *r_bezt = NULL;
- }
- else {
- *r_bezt = bezt1;
- *r_nu = nu1;
- }
- }
- bezt1++;
- }
- }
- else {
- bp1 = nu1->bp;
- a = nu1->pntsu * nu1->pntsv;
- while (a--) {
- if (bp1->f1 & SELECT) {
- if (*r_nu != NULL && *r_nu != nu1) {
- *r_bp = NULL;
- *r_bezt = NULL;
- *r_nu = NULL;
- return;
- }
- else if (*r_bezt || *r_bp) {
- *r_bp = NULL;
- *r_bezt = NULL;
- }
- else {
- *r_bp = bp1;
- *r_nu = nu1;
- }
- }
- bp1++;
- }
- }
- }
-}
-
-/***************** set spline type operator *******************/
+/* -------------------------------------------------------------------- */
+/** \name Set Spline Type Operator
+ * \{ */
static int set_spline_type_exec(bContext *C, wmOperator *op)
{
@@ -4002,14 +3918,15 @@ static int set_spline_type_exec(bContext *C, wmOperator *op)
for (nu = editnurb->first; nu; nu = nu->next) {
if (ED_curve_nurb_select_check(v3d, nu)) {
const int pntsu_prev = nu->pntsu;
- if (BKE_nurb_type_convert(nu, type, use_handles)) {
+ const char *err_msg = NULL;
+ if (BKE_nurb_type_convert(nu, type, use_handles, &err_msg)) {
changed = true;
if (pntsu_prev != nu->pntsu) {
changed_size = true;
}
}
else {
- BKE_report(op->reports, RPT_ERROR, "No conversion possible");
+ BKE_report(op->reports, RPT_ERROR, err_msg);
}
}
}
@@ -4069,7 +3986,11 @@ void CURVE_OT_spline_type_set(wmOperatorType *ot)
"Use handles when converting bezier curves into polygons");
}
-/***************** set handle type operator *******************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Handle Type Operator
+ * \{ */
static int set_handle_type_exec(bContext *C, wmOperator *op)
{
@@ -4127,7 +4048,11 @@ void CURVE_OT_handle_type_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
}
-/***************** recalculate handles operator **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Recalculate Handles Operator
+ * \{ */
static int curve_normals_make_consistent_exec(bContext *C, wmOperator *op)
{
@@ -4175,9 +4100,13 @@ void CURVE_OT_normals_make_consistent(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "calc_length", false, "Length", "Recalculate handle length");
}
-/***************** make segment operator **********************/
+/** \} */
-/* ******************** SKINNING LOFTING!!! ******************** */
+/* -------------------------------------------------------------------- */
+/** \name Make Segment Operator
+ *
+ * Also handles skinning & lofting.
+ * \{ */
static void switchdirection_knots(float *base, int tot)
{
@@ -4271,10 +4200,7 @@ typedef struct NurbSort {
float vec[3];
} NurbSort;
-static ListBase nsortbase = {NULL, NULL};
-/* static NurbSort *nusmain; */ /* this var seems to go unused... at least in this file */
-
-static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb)
+static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb, ListBase *nsortbase)
{
ListBase nbase = {NULL, NULL};
NurbSort *nus, *nustest, *headdo, *taildo;
@@ -4303,7 +4229,7 @@ static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb)
/* just add the first one */
nus = nbase.first;
BLI_remlink(&nbase, nus);
- BLI_addtail(&nsortbase, nus);
+ BLI_addtail(nsortbase, nus);
/* now add, either at head or tail, the closest one */
while (nbase.first) {
@@ -4313,13 +4239,13 @@ static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb)
nustest = nbase.first;
while (nustest) {
- dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase.first)->vec);
+ dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase->first)->vec);
if (dist < headdist) {
headdist = dist;
headdo = nustest;
}
- dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase.last)->vec);
+ dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase->last)->vec);
if (dist < taildist) {
taildist = dist;
@@ -4330,11 +4256,11 @@ static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb)
if (headdist < taildist) {
BLI_remlink(&nbase, headdo);
- BLI_addhead(&nsortbase, headdo);
+ BLI_addhead(nsortbase, headdo);
}
else {
BLI_remlink(&nbase, taildo);
- BLI_addtail(&nsortbase, taildo);
+ BLI_addtail(nsortbase, taildo);
}
}
}
@@ -4511,8 +4437,9 @@ static int merge_nurb(View3D *v3d, Object *obedit)
ListBase *editnurb = object_editcurve_get(obedit);
NurbSort *nus1, *nus2;
bool ok = true;
+ ListBase nsortbase = {NULL, NULL};
- make_selection_list_nurb(v3d, editnurb);
+ make_selection_list_nurb(v3d, editnurb, &nsortbase);
if (nsortbase.first == nsortbase.last) {
BLI_freelistN(&nsortbase);
@@ -4877,7 +4804,11 @@ void CURVE_OT_make_segment(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/***************** pick select from 3d view **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pick Select from 3D View
+ * \{ */
bool ED_curve_editnurb_select_pick(
bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
@@ -5033,7 +4964,11 @@ bool ED_curve_editnurb_select_pick(
return false;
}
-/******************** spin operator ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Spin Operator
+ * \{ */
/* 'cent' is in object space and 'dvec' in worldspace.
*/
@@ -5213,13 +5148,14 @@ void CURVE_OT_spin(wmOperatorType *ot)
ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
}
-/***************** extrude vertex operator **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Extrude Vertex Operator
+ * \{ */
static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb, View3D *v3d)
{
- Nurb *nu = NULL;
- Nurb *nu_last = NULL;
-
bool changed = false;
Nurb *cu_actnu;
@@ -5234,216 +5170,238 @@ static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb, View3D *v3d)
}
BKE_curve_nurb_vert_active_get(cu, &cu_actnu, &cu_actvert.p);
- BKE_curve_nurb_vert_active_set(cu, NULL, NULL);
-
- /* first pass (endpoints) */
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
-
- if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
- continue;
- }
+ int act_offset = 0;
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
+ BLI_assert(nu->pntsu > 0);
+ int i;
+ int pnt_len = nu->pntsu;
+ int new_points = 0;
+ int offset = 0;
+ bool is_prev_selected = false;
+ bool duplic_first = false;
+ bool duplic_last = false;
if (nu->type == CU_BEZIER) {
-
- /* Check to see if the first bezier point is selected */
- if (nu->pntsu > 0 && nu->bezt != NULL) {
- BezTriple *nu_bezt_old = nu->bezt;
- BezTriple *bezt = nu->bezt;
-
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- BezTriple *bezt_new;
- BEZT_DESEL_ALL(bezt);
-
- bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__);
- ED_curve_beztcpy(editnurb, bezt_new + 1, bezt, nu->pntsu);
- *bezt_new = *bezt;
-
- MEM_freeN(nu->bezt);
- nu->bezt = bezt_new;
-
- nu->pntsu += 1;
-
- if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) {
- cu_actvert.bezt = (cu_actvert.bezt == bezt) ?
- bezt_new :
- &nu->bezt[(cu_actvert.bezt - nu_bezt_old) + 1];
- BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt);
- }
-
- BEZT_SEL_ALL(bezt_new);
- changed = true;
- }
+ BezTriple *bezt, *bezt_prev = NULL;
+ BezTriple bezt_stack;
+ bool is_cyclic = false;
+ if (pnt_len == 1) {
+ /* Single point extrusion.
+ * Keep `is_prev_selected` false to force extrude. */
+ bezt_prev = &nu->bezt[0];
+ }
+ else if (nu->flagu & CU_NURB_CYCLIC) {
+ is_cyclic = true;
+ bezt_prev = &nu->bezt[pnt_len - 1];
+ is_prev_selected = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt_prev);
}
+ else {
+ duplic_first = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu->bezt[0]) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu->bezt[1]);
- /* Check to see if the last bezier point is selected */
- if (nu->pntsu > 1) {
- BezTriple *nu_bezt_old = nu->bezt;
- BezTriple *bezt = &nu->bezt[nu->pntsu - 1];
-
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- BezTriple *bezt_new;
- BEZT_DESEL_ALL(bezt);
-
- bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__);
- ED_curve_beztcpy(editnurb, bezt_new, nu->bezt, nu->pntsu);
- bezt_new[nu->pntsu] = *bezt;
-
- MEM_freeN(nu->bezt);
- nu->bezt = bezt_new;
-
- bezt_new += nu->pntsu;
- nu->pntsu += 1;
-
- if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) {
- cu_actvert.bezt = (cu_actvert.bezt == bezt) ? bezt_new :
- &nu->bezt[cu_actvert.bezt - nu_bezt_old];
- BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt);
- }
+ duplic_last = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu->bezt[pnt_len - 2]) &&
+ BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu->bezt[pnt_len - 1]);
- BEZT_SEL_ALL(bezt_new);
- changed = true;
+ if (duplic_first) {
+ bezt_stack = nu->bezt[0];
+ BEZT_DESEL_ALL(&bezt_stack);
+ bezt_prev = &bezt_stack;
+ }
+ if (duplic_last) {
+ new_points++;
}
}
- }
- else {
-
- /* Check to see if the first bpoint is selected */
- if (nu->pntsu > 0 && nu->bp != NULL) {
- BPoint *nu_bp_old = nu->bp;
- BPoint *bp = nu->bp;
-
- if (bp->f1 & SELECT) {
- BPoint *bp_new;
- bp->f1 &= ~SELECT;
-
- bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__);
- ED_curve_bpcpy(editnurb, bp_new + 1, bp, nu->pntsu);
- *bp_new = *bp;
-
- MEM_freeN(nu->bp);
- nu->bp = bp_new;
-
- nu->pntsu += 1;
- BKE_nurb_knot_calc_u(nu);
-
- if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) {
- cu_actvert.bp = (cu_actvert.bp == bp) ? bp_new :
- &nu->bp[(cu_actvert.bp - nu_bp_old) + 1];
- BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp);
- }
-
- bp_new->f1 |= SELECT;
- changed = true;
+ i = pnt_len;
+ for (bezt = &nu->bezt[0]; i--; bezt++) {
+ bool is_selected = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt);
+ if (bezt_prev && is_prev_selected != is_selected) {
+ new_points++;
+ }
+ if (bezt == cu_actvert.bezt) {
+ act_offset = new_points;
}
+ bezt_prev = bezt;
+ is_prev_selected = is_selected;
}
- /* Check to see if the last bpoint is selected */
- if (nu->pntsu > 1) {
- BPoint *nu_bp_old = nu->bp;
- BPoint *bp = &nu->bp[nu->pntsu - 1];
-
- if (bp->f1 & SELECT) {
- BPoint *bp_new;
- bp->f1 &= ~SELECT;
-
- bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__);
- ED_curve_bpcpy(editnurb, bp_new, nu->bp, nu->pntsu);
- bp_new[nu->pntsu] = *bp;
-
- MEM_freeN(nu->bp);
- nu->bp = bp_new;
+ if (new_points) {
+ if (pnt_len == 1) {
+ /* Single point extrusion.
+ * Set `is_prev_selected` as false to force extrude. */
+ BLI_assert(bezt_prev == &nu->bezt[0]);
+ is_prev_selected = false;
+ }
+ else if (is_cyclic) {
+ BLI_assert(bezt_prev == &nu->bezt[pnt_len - 1]);
+ BLI_assert(is_prev_selected == BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt_prev));
+ }
+ else if (duplic_first) {
+ bezt_prev = &bezt_stack;
+ is_prev_selected = false;
+ }
+ else {
+ bezt_prev = NULL;
+ }
+ BezTriple *bezt_src, *bezt_dst, *bezt_src_iter, *bezt_dst_iter;
+ const int new_len = pnt_len + new_points;
- bp_new += nu->pntsu;
- nu->pntsu += 1;
+ bezt_src = nu->bezt;
+ bezt_dst = MEM_mallocN(new_len * sizeof(BezTriple), __func__);
+ bezt_src_iter = &bezt_src[0];
+ bezt_dst_iter = &bezt_dst[0];
+ i = 0;
+ for (bezt = &nu->bezt[0]; i < pnt_len; i++, bezt++) {
+ bool is_selected = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt);
+ /* While this gets de-selected, selecting here ensures newly created verts are selected.
+ * without this, the vertices are copied but only the handles are transformed.
+ * which seems buggy from a user perspective. */
+ if (is_selected) {
+ bezt->f2 |= SELECT;
+ }
+ if (bezt_prev && is_prev_selected != is_selected) {
+ int count = i - offset + 1;
+ if (is_prev_selected) {
+ ED_curve_beztcpy(editnurb, bezt_dst_iter, bezt_src_iter, count - 1);
+ ED_curve_beztcpy(editnurb, &bezt_dst_iter[count - 1], bezt_prev, 1);
+ }
+ else {
+ ED_curve_beztcpy(editnurb, bezt_dst_iter, bezt_src_iter, count);
+ }
+ ED_curve_beztcpy(editnurb, &bezt_dst_iter[count], bezt, 1);
+ BEZT_DESEL_ALL(&bezt_dst_iter[count - 1]);
- if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) {
- cu_actvert.bp = (cu_actvert.bp == bp) ? bp_new : &nu->bp[cu_actvert.bp - nu_bp_old];
- BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp);
+ bezt_dst_iter += count + 1;
+ bezt_src_iter += count;
+ offset = i + 1;
}
+ bezt_prev = bezt;
+ is_prev_selected = is_selected;
+ }
- BKE_nurb_knot_calc_u(nu);
-
- bp_new->f1 |= SELECT;
- changed = true;
+ int remain = pnt_len - offset;
+ if (remain) {
+ ED_curve_beztcpy(editnurb, bezt_dst_iter, bezt_src_iter, remain);
}
- }
- }
- }
- /* second pass (interior points) */
- nu_last = editnurb->nurbs.last;
- for (nu = editnurb->nurbs.first; (nu != nu_last->next); nu = nu->next) {
- int i, i_end;
+ if (duplic_last) {
+ ED_curve_beztcpy(editnurb, &bezt_dst[new_len - 1], &bezt_src[pnt_len - 1], 1);
+ BEZT_DESEL_ALL(&bezt_dst[new_len - 1]);
+ }
- if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
- /* all points are interior */
- i = 0;
- i_end = nu->pntsu;
+ MEM_freeN(nu->bezt);
+ nu->bezt = bezt_dst;
+ nu->pntsu += new_points;
+ changed = true;
+ }
}
else {
- /* skip endpoints */
- i = 1;
- i_end = nu->pntsu - 1;
- }
+ BPoint *bp, *bp_prev = NULL;
+ BPoint bp_stack;
+ if (pnt_len == 1) {
+ /* Single point extrusion.
+ * Reference a `prev_bp` to force extrude. */
+ bp_prev = &nu->bp[0];
+ }
+ else {
+ duplic_first = (nu->bp[0].f1 & SELECT) && (nu->bp[1].f1 & SELECT);
+ duplic_last = (nu->bp[pnt_len - 2].f1 & SELECT) && (nu->bp[pnt_len - 1].f1 & SELECT);
+ if (duplic_first) {
+ bp_stack = nu->bp[0];
+ bp_stack.f1 &= ~SELECT;
+ bp_prev = &bp_stack;
+ }
+ if (duplic_last) {
+ new_points++;
+ }
+ }
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt;
+ i = pnt_len;
+ for (bp = &nu->bp[0]; i--; bp++) {
+ bool is_selected = (bp->f1 & SELECT) != 0;
+ if (bp_prev && is_prev_selected != is_selected) {
+ new_points++;
+ }
+ if (bp == cu_actvert.bp) {
+ act_offset = new_points;
+ }
+ bp_prev = bp;
+ is_prev_selected = is_selected;
+ }
- for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- Nurb *nurb_new;
- BezTriple *bezt_new;
+ if (new_points) {
+ BPoint *bp_src, *bp_dst, *bp_src_iter, *bp_dst_iter;
+ const int new_len = pnt_len + new_points;
- BEZT_DESEL_ALL(bezt);
- nurb_new = BKE_nurb_copy(nu, 1, 1);
- nurb_new->flagu &= ~CU_NURB_CYCLIC;
- BLI_addtail(&editnurb->nurbs, nurb_new);
- bezt_new = nurb_new->bezt;
- ED_curve_beztcpy(editnurb, bezt_new, bezt, 1);
- BEZT_SEL_ALL(bezt_new);
+ is_prev_selected = false;
+ if (pnt_len == 1) {
+ /* Single point extrusion.
+ * Keep `is_prev_selected` false to force extrude. */
+ BLI_assert(bp_prev == &nu->bp[0]);
+ }
+ else if (duplic_first) {
+ bp_prev = &bp_stack;
+ is_prev_selected = false;
+ }
+ else {
+ bp_prev = NULL;
+ }
+ bp_src = nu->bp;
+ bp_dst = MEM_mallocN(new_len * sizeof(BPoint), __func__);
+ bp_src_iter = &bp_src[0];
+ bp_dst_iter = &bp_dst[0];
+ i = 0;
+ for (bp = &nu->bp[0]; i < pnt_len; i++, bp++) {
+ bool is_selected = (bp->f1 & SELECT) != 0;
+ if (bp_prev && is_prev_selected != is_selected) {
+ int count = i - offset + 1;
+ if (is_prev_selected) {
+ ED_curve_bpcpy(editnurb, bp_dst_iter, bp_src_iter, count - 1);
+ ED_curve_bpcpy(editnurb, &bp_dst_iter[count - 1], bp_prev, 1);
+ }
+ else {
+ ED_curve_bpcpy(editnurb, bp_dst_iter, bp_src_iter, count);
+ }
+ ED_curve_bpcpy(editnurb, &bp_dst_iter[count], bp, 1);
+ bp_dst_iter[count - 1].f1 &= ~SELECT;
- if (cu_actvert.bezt == bezt || cu_actnu == NULL) {
- BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new);
+ bp_dst_iter += count + 1;
+ bp_src_iter += count;
+ offset = i + 1;
}
-
- changed = true;
+ bp_prev = bp;
+ is_prev_selected = is_selected;
}
- }
- }
- else {
- BPoint *bp;
- for (bp = &nu->bp[i]; i < i_end; i++, bp++) {
- if (bp->f1 & SELECT) {
- Nurb *nurb_new;
- BPoint *bp_new;
+ int remain = pnt_len - offset;
+ if (remain) {
+ ED_curve_bpcpy(editnurb, bp_dst_iter, bp_src_iter, remain);
+ }
- bp->f1 &= ~SELECT;
- nurb_new = BKE_nurb_copy(nu, 1, 1);
- nurb_new->flagu &= ~CU_NURB_CYCLIC;
- BLI_addtail(&editnurb->nurbs, nurb_new);
- bp_new = nurb_new->bp;
- ED_curve_bpcpy(editnurb, bp_new, bp, 1);
- bp_new->f1 |= SELECT;
+ if (duplic_last) {
+ ED_curve_bpcpy(editnurb, &bp_dst[new_len - 1], &bp_src[pnt_len - 1], 1);
+ bp_dst[new_len - 1].f1 &= ~SELECT;
+ }
- if (cu_actvert.bp == bp || cu_actnu == NULL) {
- BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new);
- }
+ MEM_freeN(nu->bp);
+ nu->bp = bp_dst;
+ nu->pntsu += new_points;
- changed = true;
- }
+ BKE_nurb_knot_calc_u(nu);
+ changed = true;
}
}
}
- if (changed == false) {
- BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p);
- }
+ cu->actvert += act_offset;
return changed;
}
-/***************** add vertex operator **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Vertex Operator
+ * \{ */
static int ed_editcurve_addvert(Curve *cu,
EditNurb *editnurb,
@@ -5659,7 +5617,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
cu = vc.obedit->data;
- findselectedNurbvert(cu, vc.v3d, &nu, &bezt, &bp);
+ ED_curve_nurb_vert_selected_find(cu, vc.v3d, &nu, &bezt, &bp);
if (bezt) {
mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]);
@@ -5671,16 +5629,17 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
copy_v3_v3(location, vc.scene->cursor.location);
}
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, location, event->mval, location);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.region, location, event->mval, location);
if (use_proj) {
const float mval[2] = {UNPACK2(event->mval)};
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- vc.bmain, vc.scene, vc.depsgraph, 0, vc.ar, vc.v3d);
+ vc.bmain, vc.scene, 0, vc.region, vc.v3d);
ED_transform_snap_object_project_view3d(
snap_context,
+ vc.depsgraph,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = (vc.obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL,
@@ -5759,7 +5718,11 @@ void CURVE_OT_vertex_add(wmOperatorType *ot)
1.0e4f);
}
-/***************** extrude operator **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Extrude Operator
+ * \{ */
static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -5830,7 +5793,11 @@ void CURVE_OT_extrude(wmOperatorType *ot)
RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
}
-/***************** make cyclic operator **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Make Cyclic Operator
+ * \{ */
static bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction)
{
@@ -5996,7 +5963,11 @@ void CURVE_OT_cyclic_toggle(wmOperatorType *ot)
"Direction to make surface cyclic in");
}
-/********************** add duplicate operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Duplicate Operator
+ * \{ */
static int duplicate_exec(bContext *C, wmOperator *op)
{
@@ -6052,7 +6023,11 @@ void CURVE_OT_duplicate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/********************** delete operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Operator
+ * \{ */
static bool curve_delete_vertices(Object *obedit, View3D *v3d)
{
@@ -6598,6 +6573,12 @@ void CURVE_OT_delete(wmOperatorType *ot)
ot->prop = prop;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Dissolve Vertices
+ * \{ */
+
static bool test_bezt_is_sel_any(const void *bezt_v, void *user_data)
{
View3D *v3d = user_data;
@@ -6627,8 +6608,8 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
for (nu = editnurb->first; nu; nu = nu->next) {
if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) {
- unsigned int span_step[2] = {nu->pntsu, nu->pntsu};
- unsigned int span_len;
+ uint span_step[2] = {nu->pntsu, nu->pntsu};
+ uint span_len;
while (BLI_array_iter_span(nu->bezt,
nu->pntsu,
@@ -6642,9 +6623,9 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
BezTriple *bezt_next = &nu->bezt[mod_i(span_step[1] + 1, nu->pntsu)];
int i_span_edge_len = span_len + 1;
- const unsigned int dims = 3;
+ const uint dims = 3;
- const unsigned int points_len = ((cu->resolu - 1) * i_span_edge_len) + 1;
+ const uint points_len = ((cu->resolu - 1) * i_span_edge_len) + 1;
float *points = MEM_mallocN(points_len * dims * sizeof(float), __func__);
float *points_stride = points;
const int points_stride_len = (cu->resolu - 1);
@@ -6669,7 +6650,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
BLI_assert(points_stride + dims == points + (points_len * dims));
float tan_l[3], tan_r[3], error_sq_dummy;
- unsigned int error_index_dummy;
+ uint error_index_dummy;
sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]);
normalize_v3(tan_l);
@@ -6730,6 +6711,12 @@ void CURVE_OT_dissolve_verts(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Decimate Operator
+ * \{ */
+
static bool nurb_bezt_flag_any(const Nurb *nu, const char flag_test)
{
BezTriple *bezt = nu->bezt;
@@ -6823,7 +6810,11 @@ void CURVE_OT_decimate(wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f);
}
-/********************** shade smooth/flat operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Shade Smooth/Flat Operator
+ * \{ */
static int shade_smooth_exec(bContext *C, wmOperator *op)
{
@@ -6843,7 +6834,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
continue;
}
- for (Nurb *nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (ED_curve_nurb_select_check(v3d, nu)) {
if (!clear) {
nu->flag |= CU_SMOOTH;
@@ -6894,8 +6885,16 @@ void CURVE_OT_shade_flat(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/************** join operator, to be used externally? ****************/
-/* TODO: shape keys - as with meshes */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Join Operator
+ * \{ */
+
+/**
+ * This is used externally, by #OBJECT_OT_join.
+ * TODO: shape keys - as with meshes.
+ */
int join_curve_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -6995,7 +6994,11 @@ int join_curve_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/***************** clear tilt operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Tilt Operator
+ * \{ */
static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -7076,28 +7079,11 @@ void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count)
keyIndex_updateBP(editnurb, src, dst, count);
}
-bool ED_curve_active_center(Curve *cu, float center[3])
-{
- Nurb *nu = NULL;
- void *vert = NULL;
-
- if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
- return false;
- }
-
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt = (BezTriple *)vert;
- copy_v3_v3(center, bezt->vec[1]);
- }
- else {
- BPoint *bp = (BPoint *)vert;
- copy_v3_v3(center, bp->vec);
- }
-
- return true;
-}
+/** \} */
-/******************** Match texture space operator ***********************/
+/* -------------------------------------------------------------------- */
+/** \name Match Texture Space Operator
+ * \{ */
static bool match_texture_space_poll(bContext *C)
{
@@ -7167,3 +7153,5 @@ void CURVE_OT_match_texture_space(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/** \} */
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index d97223de9b8..91d5ea58361 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -21,9 +21,9 @@
* \ingroup edcurve
*/
+#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_anim_types.h"
#include "MEM_guardedalloc.h"
@@ -42,10 +42,10 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_curve.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_curve.h"
#include "curve_intern.h"
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 5486d60d5d7..748bf040fbb 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -37,10 +37,10 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_space_api.h"
+#include "ED_curve.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "ED_view3d.h"
-#include "ED_curve.h"
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
@@ -187,7 +187,7 @@ static bool stroke_elem_project(const struct CurveDrawData *cdd,
float r_location_world[3],
float r_normal_world[3])
{
- ARegion *ar = cdd->vc.ar;
+ ARegion *region = cdd->vc.region;
RegionView3D *rv3d = cdd->vc.rv3d;
bool is_location_world_set = false;
@@ -195,7 +195,8 @@ static bool stroke_elem_project(const struct CurveDrawData *cdd,
/* project to 'location_world' */
if (cdd->project.use_plane) {
/* get the view vector to 'location' */
- if (ED_view3d_win_to_3d_on_plane(ar, cdd->project.plane, mval_fl, true, r_location_world)) {
+ if (ED_view3d_win_to_3d_on_plane(
+ region, cdd->project.plane, mval_fl, true, r_location_world)) {
if (r_normal_world) {
zero_v3(r_normal_world);
}
@@ -204,10 +205,10 @@ static bool stroke_elem_project(const struct CurveDrawData *cdd,
}
else {
const ViewDepths *depths = rv3d->depths;
- if (depths && ((unsigned int)mval_i[0] < depths->w) && ((unsigned int)mval_i[1] < depths->h)) {
+ if (depths && ((uint)mval_i[0] < depths->w) && ((uint)mval_i[1] < depths->h)) {
const double depth = (double)ED_view3d_depth_read_cached(&cdd->vc, mval_i);
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (ED_view3d_depth_unproject(ar, mval_i, depth, r_location_world)) {
+ if (ED_view3d_depth_unproject(region, mval_i, depth, r_location_world)) {
is_location_world_set = true;
if (r_normal_world) {
zero_v3(r_normal_world);
@@ -252,7 +253,7 @@ static bool stroke_elem_project_fallback(const struct CurveDrawData *cdd,
cdd, mval_i, mval_fl, surface_offset, radius, r_location_world, r_normal_world);
if (is_depth_found == false) {
ED_view3d_win_to_3d(
- cdd->vc.v3d, cdd->vc.ar, location_fallback_depth, mval_fl, r_location_world);
+ cdd->vc.v3d, cdd->vc.region, location_fallback_depth, mval_fl, r_location_world);
zero_v3(r_normal_local);
}
mul_v3_m4v3(r_location_local, cdd->vc.obedit->imat, r_location_world);
@@ -345,7 +346,9 @@ static void curve_draw_stroke_from_operator(wmOperator *op)
/** \name Operator Callbacks & Helpers
* \{ */
-static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+static void curve_draw_stroke_3d(const struct bContext *UNUSED(C),
+ ARegion *UNUSED(region),
+ void *arg)
{
wmOperator *op = arg;
struct CurveDrawData *cdd = op->customdata;
@@ -478,7 +481,7 @@ static void curve_draw_event_add(wmOperator *op, const wmEvent *event)
if (cdd->sample.use_substeps && cdd->prev.selem) {
const struct StrokeElem selem_target = *selem;
struct StrokeElem *selem_new_last = selem;
- if (len_sq >= SQUARE(STROKE_SAMPLE_DIST_MAX_PX)) {
+ if (len_sq >= square_f(STROKE_SAMPLE_DIST_MAX_PX)) {
int n = (int)ceil(sqrt((double)len_sq)) / STROKE_SAMPLE_DIST_MAX_PX;
for (int i = 1; i < n; i++) {
@@ -502,7 +505,7 @@ static void curve_draw_event_add(wmOperator *op, const wmEvent *event)
cdd->prev.selem = selem;
- ED_region_tag_redraw(cdd->vc.ar);
+ ED_region_tag_redraw(cdd->vc.region);
}
static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event)
@@ -572,7 +575,7 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
if (is_invoke) {
ED_view3d_viewcontext_init(C, &cdd->vc, depsgraph);
- if (ELEM(NULL, cdd->vc.ar, cdd->vc.rv3d, cdd->vc.v3d, cdd->vc.win, cdd->vc.scene)) {
+ if (ELEM(NULL, cdd->vc.region, cdd->vc.rv3d, cdd->vc.v3d, cdd->vc.win, cdd->vc.scene)) {
MEM_freeN(cdd);
BKE_report(op->reports, RPT_ERROR, "Unable to access 3D viewport");
return false;
@@ -610,7 +613,7 @@ static void curve_draw_exit(wmOperator *op)
struct CurveDrawData *cdd = op->customdata;
if (cdd) {
if (cdd->draw_handle_view) {
- ED_region_draw_cb_exit(cdd->vc.ar->type, cdd->draw_handle_view);
+ ED_region_draw_cb_exit(cdd->vc.region->type, cdd->draw_handle_view);
WM_cursor_modal_restore(cdd->vc.win);
}
@@ -682,7 +685,7 @@ static void curve_draw_exec_precalc(wmOperator *op)
}
if (len_squared_v2v2(selem_first->mval, selem_last->mval) <=
- SQUARE(STROKE_CYCLIC_DIST_PX * U.pixelsize)) {
+ square_f(STROKE_CYCLIC_DIST_PX * U.pixelsize)) {
use_cyclic = true;
}
}
@@ -795,7 +798,7 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
float *coords = MEM_mallocN(sizeof(*coords) * stroke_len * dims, __func__);
float *cubic_spline = NULL;
- unsigned int cubic_spline_len = 0;
+ uint cubic_spline_len = 0;
/* error in object local space */
const int fit_method = RNA_enum_get(op->ptr, "fit_method");
@@ -824,14 +827,14 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
}
}
- unsigned int *corners = NULL;
- unsigned int corners_len = 0;
+ uint *corners = NULL;
+ uint corners_len = 0;
if ((fit_method == CURVE_PAINT_FIT_METHOD_SPLIT) && (corner_angle < (float)M_PI)) {
/* this could be configurable... */
const float corner_radius_min = error_threshold / 8;
const float corner_radius_max = error_threshold * 2;
- const unsigned int samples_max = 16;
+ const uint samples_max = 16;
curve_fit_corners_detect_fl(coords,
stroke_len,
@@ -844,9 +847,9 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
&corners_len);
}
- unsigned int *corners_index = NULL;
- unsigned int corners_index_len = 0;
- unsigned int calc_flag = CURVE_FIT_CALC_HIGH_QUALIY;
+ uint *corners_index = NULL;
+ uint corners_index_len = 0;
+ uint calc_flag = CURVE_FIT_CALC_HIGH_QUALIY;
if ((stroke_len > 2) && use_cyclic) {
calc_flag |= CURVE_FIT_CALC_CYCLIC;
@@ -916,14 +919,14 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
if (corners_index) {
/* ignore the first and last */
- unsigned int i_start = 0, i_end = corners_index_len;
+ uint i_start = 0, i_end = corners_index_len;
if ((corners_index_len >= 2) && (calc_flag & CURVE_FIT_CALC_CYCLIC) == 0) {
i_start += 1;
i_end -= 1;
}
- for (unsigned int i = i_start; i < i_end; i++) {
+ for (uint i = i_start; i < i_end; i++) {
bezt = &nu->bezt[corners_index[i]];
bezt->h1 = bezt->h2 = HD_FREE;
}
@@ -1052,12 +1055,12 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const float mval_fl[2] = {UNPACK2(event->mval)};
float center[3];
negate_v3_v3(center, cdd->vc.rv3d->ofs);
- ED_view3d_win_to_3d(cdd->vc.v3d, cdd->vc.ar, center, mval_fl, cdd->prev.location_world);
+ ED_view3d_win_to_3d(cdd->vc.v3d, cdd->vc.region, center, mval_fl, cdd->prev.location_world);
copy_v3_v3(cdd->prev.location_world_valid, cdd->prev.location_world);
}
cdd->draw_handle_view = ED_region_draw_cb_activate(
- cdd->vc.ar->type, curve_draw_stroke_3d, op, REGION_DRAW_POST_VIEW);
+ cdd->vc.region->type, curve_draw_stroke_3d, op, REGION_DRAW_POST_VIEW);
WM_cursor_modal_set(cdd->vc.win, WM_CURSOR_PAINT_BRUSH);
{
@@ -1080,13 +1083,13 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
- ED_view3d_autodist_init(cdd->vc.depsgraph, cdd->vc.ar, cdd->vc.v3d, 0);
+ ED_view3d_autodist_init(cdd->vc.depsgraph, cdd->vc.region, cdd->vc.v3d, 0);
if (cdd->vc.rv3d->depths) {
cdd->vc.rv3d->depths->damaged = true;
}
- ED_view3d_depth_update(cdd->vc.ar);
+ ED_view3d_depth_update(cdd->vc.region);
if (cdd->vc.rv3d->depths != NULL) {
cdd->project.use_depth = true;
@@ -1140,7 +1143,7 @@ static int curve_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event->type == cdd->init_event_type) {
if (event->val == KM_RELEASE) {
- ED_region_tag_redraw(cdd->vc.ar);
+ ED_region_tag_redraw(cdd->vc.region);
curve_draw_exec_precalc(op);
@@ -1151,8 +1154,8 @@ static int curve_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
}
- else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
- ED_region_tag_redraw(cdd->vc.ar);
+ else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
+ ED_region_tag_redraw(cdd->vc.region);
curve_draw_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -1164,7 +1167,7 @@ static int curve_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
if (cdd->state == CURVE_DRAW_PAINTING) {
const float mval_fl[2] = {UNPACK2(event->mval)};
- if (len_squared_v2v2(mval_fl, cdd->prev.mouse) > SQUARE(STROKE_SAMPLE_DIST_MIN_PX)) {
+ if (len_squared_v2v2(mval_fl, cdd->prev.mouse) > square_f(STROKE_SAMPLE_DIST_MIN_PX)) {
curve_draw_event_add(op, event);
}
}
diff --git a/source/blender/editors/curve/editcurve_query.c b/source/blender/editors/curve/editcurve_query.c
new file mode 100644
index 00000000000..0b15d9e55b9
--- /dev/null
+++ b/source/blender/editors/curve/editcurve_query.c
@@ -0,0 +1,244 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edcurve
+ */
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "BKE_curve.h"
+#include "BKE_fcurve.h"
+#include "BKE_layer.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+#include "ED_curve.h"
+#include "ED_view3d.h"
+
+#include "curve_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Cursor Picking API
+ * \{ */
+
+static void ED_curve_pick_vert__do_closest(
+ void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
+{
+ struct {
+ BPoint *bp;
+ BezTriple *bezt;
+ Nurb *nurb;
+ float dist;
+ int hpoint, select;
+ float mval_fl[2];
+ bool is_changed;
+ } *data = userData;
+
+ short flag;
+ float dist_test;
+
+ if (bp) {
+ flag = bp->f1;
+ }
+ else {
+ if (beztindex == 0) {
+ flag = bezt->f1;
+ }
+ else if (beztindex == 1) {
+ flag = bezt->f2;
+ }
+ else {
+ flag = bezt->f3;
+ }
+ }
+
+ dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
+ if ((flag & SELECT) == data->select) {
+ dist_test += 5.0f;
+ }
+ if (bezt && beztindex == 1) {
+ dist_test += 3.0f; /* middle points get a small disadvantage */
+ }
+
+ if (dist_test < data->dist) {
+ data->dist = dist_test;
+
+ data->bp = bp;
+ data->bezt = bezt;
+ data->nurb = nu;
+ data->hpoint = bezt ? beztindex : 0;
+ data->is_changed = true;
+ }
+}
+
+bool ED_curve_pick_vert(ViewContext *vc,
+ short sel,
+ Nurb **r_nurb,
+ BezTriple **r_bezt,
+ BPoint **r_bp,
+ short *r_handle,
+ Base **r_base)
+{
+ /* (sel == 1): selected gets a disadvantage */
+ /* in nurb and bezt or bp the nearest is written */
+ /* return 0 1 2: handlepunt */
+ struct {
+ BPoint *bp;
+ BezTriple *bezt;
+ Nurb *nurb;
+ float dist;
+ int hpoint, select;
+ float mval_fl[2];
+ bool is_changed;
+ } data = {NULL};
+
+ data.dist = ED_view3d_select_dist_px();
+ data.hpoint = 0;
+ data.select = sel;
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc->view_layer, vc->v3d, &bases_len);
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base = bases[base_index];
+ data.is_changed = false;
+
+ ED_view3d_viewcontext_init_object(vc, base->object);
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ nurbs_foreachScreenVert(vc, ED_curve_pick_vert__do_closest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ if (r_base && data.is_changed) {
+ *r_base = base;
+ }
+ }
+ MEM_freeN(bases);
+
+ *r_nurb = data.nurb;
+ *r_bezt = data.bezt;
+ *r_bp = data.bp;
+
+ if (r_handle) {
+ *r_handle = data.hpoint;
+ }
+
+ return (data.bezt || data.bp);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Selection Queries
+ * \{ */
+
+void ED_curve_nurb_vert_selected_find(
+ Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp)
+{
+ /* in nu and (bezt or bp) selected are written if there's 1 sel. */
+ /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */
+ ListBase *editnurb = &cu->editnurb->nurbs;
+ Nurb *nu1;
+ BezTriple *bezt1;
+ BPoint *bp1;
+ int a;
+
+ *r_nu = NULL;
+ *r_bezt = NULL;
+ *r_bp = NULL;
+
+ for (nu1 = editnurb->first; nu1; nu1 = nu1->next) {
+ if (nu1->type == CU_BEZIER) {
+ bezt1 = nu1->bezt;
+ a = nu1->pntsu;
+ while (a--) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1)) {
+ if (*r_nu != NULL && *r_nu != nu1) {
+ *r_nu = NULL;
+ *r_bp = NULL;
+ *r_bezt = NULL;
+ return;
+ }
+ else if (*r_bezt || *r_bp) {
+ *r_bp = NULL;
+ *r_bezt = NULL;
+ }
+ else {
+ *r_bezt = bezt1;
+ *r_nu = nu1;
+ }
+ }
+ bezt1++;
+ }
+ }
+ else {
+ bp1 = nu1->bp;
+ a = nu1->pntsu * nu1->pntsv;
+ while (a--) {
+ if (bp1->f1 & SELECT) {
+ if (*r_nu != NULL && *r_nu != nu1) {
+ *r_bp = NULL;
+ *r_bezt = NULL;
+ *r_nu = NULL;
+ return;
+ }
+ else if (*r_bezt || *r_bp) {
+ *r_bp = NULL;
+ *r_bezt = NULL;
+ }
+ else {
+ *r_bp = bp1;
+ *r_nu = nu1;
+ }
+ }
+ bp1++;
+ }
+ }
+ }
+}
+
+bool ED_curve_active_center(Curve *cu, float center[3])
+{
+ Nurb *nu = NULL;
+ void *vert = NULL;
+
+ if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
+ return false;
+ }
+
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt = (BezTriple *)vert;
+ copy_v3_v3(center, bezt->vec[1]);
+ }
+ else {
+ BPoint *bp = (BPoint *)vert;
+ copy_v3_v3(center, bp->vec);
+ }
+
+ return true;
+}
+
+/** \} */
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index 9df79a082e1..9cf61d02677 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -27,10 +27,11 @@
#include "MEM_guardedalloc.h"
#include "BLI_bitmap.h"
-#include "BLI_math.h"
-#include "BLI_rand.h"
#include "BLI_heap_simple.h"
#include "BLI_kdtree.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_rand.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -41,12 +42,12 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_curve.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_types.h"
#include "ED_view3d.h"
-#include "ED_curve.h"
#include "curve_intern.h"
@@ -198,7 +199,7 @@ bool ED_curve_nurb_select_all(const Nurb *nu)
bool ED_curve_select_all(EditNurb *editnurb)
{
bool changed = false;
- for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
changed |= ED_curve_nurb_select_all(nu);
}
return changed;
@@ -257,7 +258,7 @@ bool ED_curve_select_check(View3D *v3d, struct EditNurb *editnurb)
bool ED_curve_deselect_all(EditNurb *editnurb)
{
bool changed = false;
- for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
changed |= ED_curve_nurb_deselect_all(nu);
}
return changed;
@@ -1825,7 +1826,7 @@ static float curve_calc_dist_span(Nurb *nu, int vert_src, int vert_dst)
int i_prev, i;
float dist = 0.0f;
- BLI_assert(nu->pntsv == 1);
+ BLI_assert(nu->pntsv <= 1);
i_prev = vert_src;
i = (i_prev + 1) % u;
diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c
index ff3a1386fd9..af492de638b 100644
--- a/source/blender/editors/curve/editcurve_undo.c
+++ b/source/blender/editors/curve/editcurve_undo.c
@@ -22,15 +22,15 @@
#include "CLG_log.h"
+#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_anim_types.h"
+#include "BLI_array_utils.h"
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
-#include "BLI_array_utils.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_fcurve.h"
@@ -40,11 +40,11 @@
#include "DEG_depsgraph.h"
-#include "ED_undo.h"
#include "ED_curve.h"
+#include "ED_undo.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "curve_intern.h"
@@ -216,8 +216,7 @@ static bool curve_undosys_step_encode(struct bContext *C, struct Main *bmain, Un
* outside of this list will be moved out of edit-mode when reading back undo steps. */
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, NULL, &objects_len);
+ Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
us->elems_len = objects_len;
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index c9206e8df4a..dc5dc71106f 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -21,11 +21,11 @@
* \ingroup edcurve
*/
+#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
-#include <fcntl.h>
#include <wchar.h>
-#include <errno.h>
#include "MEM_guardedalloc.h"
@@ -36,14 +36,14 @@
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
-#include "DNA_vfont_types.h"
#include "DNA_scene_types.h"
#include "DNA_text_types.h"
+#include "DNA_vfont_types.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_font.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -76,7 +76,7 @@ static int kill_selection(Object *obedit, int ins);
/** \name Internal Utilities
* \{ */
-static wchar_t findaccent(wchar_t char1, unsigned int code)
+static wchar_t findaccent(wchar_t char1, uint code)
{
wchar_t new = 0;
@@ -1684,7 +1684,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
/* tab should exit editmode, but we allow it to be typed using modifier keys */
- if (event_type == TABKEY) {
+ if (event_type == EVT_TABKEY) {
if ((alt || ctrl || shift) == 0) {
return OPERATOR_PASS_THROUGH;
}
@@ -1693,7 +1693,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
}
- if (event_type == BACKSPACEKEY) {
+ if (event_type == EVT_BACKSPACEKEY) {
if (alt && ef->len != 0 && ef->pos > 0) {
accentcode = 1;
}
@@ -2256,7 +2256,7 @@ bool ED_curve_editfont_select_pick(
for (j = 0; j < 4; j++) {
if (ED_view3d_project_float_object(
- vc.ar, obedit_co[j], screen_co[j], V3D_PROJ_TEST_CLIP_BB) == V3D_PROJ_RET_OK) {
+ vc.region, obedit_co[j], screen_co[j], V3D_PROJ_TEST_CLIP_BB) == V3D_PROJ_RET_OK) {
project_ok |= (1 << j);
}
}
@@ -2272,7 +2272,7 @@ bool ED_curve_editfont_select_pick(
}
}
- /* bias in pixels to cycle seletion */
+ /* Bias in pixels to cycle selection. */
if (i_iter == 0) {
dist_sq_min += active_bias_px;
}
diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c
index f00c4731b0f..af591e0c7c5 100644
--- a/source/blender/editors/curve/editfont_undo.c
+++ b/source/blender/editors/curve/editfont_undo.c
@@ -23,8 +23,8 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_array_utils.h"
+#include "BLI_utildefines.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
@@ -36,11 +36,11 @@
#include "DEG_depsgraph.h"
-#include "ED_object.h"
#include "ED_curve.h"
+#include "ED_object.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#define USE_ARRAY_STORE
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 62bac643347..1a5b3d6ac45 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -336,7 +336,7 @@ set(ICON_NAMES
force_boid
force_turbulence
force_drag
- force_smokeflow
+ force_fluidflow
image_plane
image_background
image_reference
@@ -609,6 +609,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.gpencil_draw.draw
brush.gpencil_draw.erase
brush.gpencil_draw.fill
+ brush.gpencil_draw.tint
brush.paint_texture.airbrush
brush.paint_texture.clone
brush.paint_texture.draw
@@ -622,6 +623,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.paint_vertex.average
brush.paint_vertex.blur
brush.paint_vertex.draw
+ brush.paint_vertex.replace
brush.paint_vertex.smear
brush.paint_weight.average
brush.paint_weight.blur
@@ -638,8 +640,11 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.sculpt.blob
brush.sculpt.clay
brush.sculpt.clay_strips
+ brush.sculpt.clay_thumb
+ brush.sculpt.cloth
brush.sculpt.crease
brush.sculpt.draw
+ brush.sculpt.draw_face_sets
brush.sculpt.draw_sharp
brush.sculpt.elastic_deform
brush.sculpt.fill
@@ -703,6 +708,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
ops.gpencil.sculpt_twist
ops.gpencil.sculpt_weight
ops.gpencil.stroke_cutter
+ ops.gpencil.transform_fill
ops.mesh.bevel
ops.mesh.bisect
ops.mesh.dupli_extrude_cursor
@@ -739,6 +745,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
ops.sculpt.border_mask
ops.sculpt.lasso_mask
ops.sculpt.mesh_filter
+ ops.sequencer.blade
ops.transform.bone_envelope
ops.transform.bone_size
ops.transform.edge_slide
@@ -759,8 +766,6 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
)
data_to_c_simple(../../../../release/datafiles/bfont.pfb SRC)
-data_to_c_simple(../../../../release/datafiles/bfont.ttf SRC)
-data_to_c_simple(../../../../release/datafiles/bmonofont.ttf SRC)
if(WITH_BLENDER)
# blender only (not player)
@@ -774,7 +779,7 @@ if(WITH_BLENDER)
# images
data_to_c_simple(../../../../release/datafiles/splash.png SRC)
- data_to_c_simple(../../../../release/datafiles/splash_2x.png SRC)
+ data_to_c_simple(../../../../release/datafiles/alert_icons.png SRC)
# XXX These are handy, but give nasty "false changes" in svn :/
# svg_to_png(../../../../release/datafiles/blender_icons.svg
# ../../../../release/datafiles/blender_icons16.png
diff --git a/source/blender/editors/gizmo_library/geometry/geom_arrow_gizmo.c b/source/blender/editors/gizmo_library/geometry/geom_arrow_gizmo.c
index 90196988d94..668b59ac191 100644
--- a/source/blender/editors/gizmo_library/geometry/geom_arrow_gizmo.c
+++ b/source/blender/editors/gizmo_library/geometry/geom_arrow_gizmo.c
@@ -55,7 +55,7 @@ static float normals[][3] = {
{0.000000, 0.000000, 1.000000},
};
-static unsigned short indices[] = {
+static ushort indices[] = {
1, 3, 2, 3, 5, 4, 5, 7, 6, 7, 9, 8, 9, 11, 10, 11, 13, 12, 5, 18, 19, 15, 1,
0, 13, 15, 14, 6, 10, 14, 11, 21, 22, 7, 19, 20, 13, 22, 23, 3, 17, 18, 9, 20, 21, 15,
23, 16, 1, 16, 17, 23, 22, 24, 21, 20, 24, 19, 18, 24, 17, 16, 24, 16, 23, 24, 22, 21, 24,
diff --git a/source/blender/editors/gizmo_library/geometry/geom_cube_gizmo.c b/source/blender/editors/gizmo_library/geometry/geom_cube_gizmo.c
index ea1a3147148..51618e353f4 100644
--- a/source/blender/editors/gizmo_library/geometry/geom_cube_gizmo.c
+++ b/source/blender/editors/gizmo_library/geometry/geom_cube_gizmo.c
@@ -45,7 +45,7 @@ static const float normals[][3] = {
{-0.577349, 0.577349, 0.577349},
};
-static const unsigned short indices[] = {
+static const ushort indices[] = {
1, 2, 3, 7, 6, 5, 4, 5, 1, 5, 6, 2, 2, 6, 7, 0, 3, 7,
0, 1, 3, 4, 7, 5, 0, 4, 1, 1, 5, 2, 3, 2, 7, 4, 0, 7,
};
diff --git a/source/blender/editors/gizmo_library/geometry/geom_dial_gizmo.c b/source/blender/editors/gizmo_library/geometry/geom_dial_gizmo.c
index 273f957e9b6..7e37c233c2a 100644
--- a/source/blender/editors/gizmo_library/geometry/geom_dial_gizmo.c
+++ b/source/blender/editors/gizmo_library/geometry/geom_dial_gizmo.c
@@ -221,7 +221,7 @@ static const float normals[][3] = {
{-0.466689, 0.092807, -0.879513}, {0.512650, -0.101962, -0.852504},
};
-static const unsigned short indices[] = {
+static const ushort indices[] = {
6, 7, 1, 7, 8, 2, 8, 9, 3, 9, 10, 4, 10, 11, 5, 5, 11, 6, 12,
13, 7, 13, 14, 8, 14, 15, 9, 15, 16, 10, 16, 17, 11, 11, 17, 12, 18, 19,
13, 13, 19, 20, 20, 21, 15, 15, 21, 22, 22, 23, 17, 17, 23, 18, 24, 25, 19,
diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
index cffafc56693..01e5a7eacfd 100644
--- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
@@ -66,7 +66,7 @@ void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info,
/* Elements */
GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, info->ntris, info->nverts);
for (int i = 0; i < info->ntris; i++) {
- const unsigned short *idx = &info->indices[i * 3];
+ const ushort *idx = &info->indices[i * 3];
GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
}
el = GPU_indexbuf_build(&elb);
diff --git a/source/blender/editors/gizmo_library/gizmo_geometry.h b/source/blender/editors/gizmo_library/gizmo_geometry.h
index ae8ba3c411b..a5f61158f66 100644
--- a/source/blender/editors/gizmo_library/gizmo_geometry.h
+++ b/source/blender/editors/gizmo_library/gizmo_geometry.h
@@ -30,12 +30,14 @@
#ifndef __GIZMO_GEOMETRY_H__
#define __GIZMO_GEOMETRY_H__
+#include "BLI_sys_types.h"
+
typedef struct GizmoGeomInfo {
int nverts;
int ntris;
const float (*verts)[3];
const float (*normals)[3];
- const unsigned short *indices;
+ const ushort *indices;
} GizmoGeomInfo;
/* arrow gizmo */
diff --git a/source/blender/editors/gizmo_library/gizmo_library_intern.h b/source/blender/editors/gizmo_library/gizmo_library_intern.h
index 35782ea8b95..31decb71c77 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_intern.h
+++ b/source/blender/editors/gizmo_library/gizmo_library_intern.h
@@ -24,9 +24,6 @@
#ifndef __GIZMO_LIBRARY_INTERN_H__
#define __GIZMO_LIBRARY_INTERN_H__
-/* distance around which gizmos respond to input (and get highlighted) */
-#define GIZMO_HOTSPOT 14.0f
-
/**
* Data for common interactions. Used in gizmo_library_utils.c functions.
*/
diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c
index fe0893ae3ff..9039851da01 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_presets.c
+++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c
@@ -26,8 +26,8 @@
#include "BLI_math.h"
-#include "DNA_view3d_types.h"
#include "DNA_object_types.h"
+#include "DNA_view3d_types.h"
#include "BKE_context.h"
@@ -38,11 +38,11 @@
#include "RNA_access.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
-#include "ED_view3d.h"
#include "ED_screen.h"
+#include "ED_view3d.h"
/* own includes */
#include "ED_gizmo_library.h" /* own include */
diff --git a/source/blender/editors/gizmo_library/gizmo_library_utils.c b/source/blender/editors/gizmo_library/gizmo_library_utils.c
index 1f61c45eb80..3902c112796 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_library_utils.c
@@ -27,8 +27,8 @@
#include "BLI_math.h"
-#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
#include "BKE_context.h"
@@ -196,12 +196,12 @@ bool gizmo_window_project_2d(bContext *C,
/* rotate mouse in relation to the center and relocate it */
if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
/* For 3d views, transform 2D mouse pos onto plane. */
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float plane[4], co[3];
plane_from_point_normal_v3(plane, mat[3], mat[2]);
- bool clip_ray = ((RegionView3D *)ar->regiondata)->is_persp;
- if (ED_view3d_win_to_3d_on_plane(ar, plane, mval, clip_ray, co)) {
+ bool clip_ray = ((RegionView3D *)region->regiondata)->is_persp;
+ if (ED_view3d_win_to_3d_on_plane(region, plane, mval, clip_ray, co)) {
float imat[4][4];
invert_m4_m4(imat, mat);
mul_m4_v3(imat, co);
@@ -237,10 +237,10 @@ bool gizmo_window_project_3d(
if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* Note: we might want a custom reference point passed in,
* instead of the gizmo center. */
- ED_view3d_win_to_3d(v3d, ar, mat[3], mval, r_co);
+ ED_view3d_win_to_3d(v3d, region, mat[3], mval, r_co);
invert_m4(mat);
mul_m4_v3(mat, r_co);
return true;
diff --git a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
index f1a8bc62cd3..e6333d7d3e0 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
@@ -50,12 +50,12 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
-#include "ED_view3d.h"
-#include "ED_screen.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
#include "UI_interface.h"
@@ -88,9 +88,14 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
const int draw_style = RNA_enum_get(arrow->gizmo.ptr, "draw_style");
const int draw_options = RNA_enum_get(arrow->gizmo.ptr, "draw_options");
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
if (draw_style == ED_GIZMO_ARROW_STYLE_CROSS) {
+ immUniform1f("lineWidth", U.pixelsize);
immUniformColor4fv(color);
immBegin(GPU_PRIM_LINES, 4);
@@ -112,7 +117,7 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
{-unitx, unity, 0},
};
- GPU_line_width(arrow->gizmo.line_width);
+ immUniform1f("lineWidth", arrow->gizmo.line_width * U.pixelsize);
wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_LOOP);
}
else {
@@ -127,7 +132,7 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
};
if (draw_options & ED_GIZMO_ARROW_DRAW_FLAG_STEM) {
- GPU_line_width(arrow->gizmo.line_width);
+ immUniform1f("lineWidth", arrow->gizmo.line_width * U.pixelsize);
wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_STRIP);
}
else {
@@ -160,6 +165,10 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
/* translate to line end */
GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length);
+ immUnbindProgram();
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+
imm_draw_circle_fill_3d(pos, 0.0, 0.0, width, 8);
imm_draw_cylinder_fill_3d(pos, width, 0.0, len, 8, 1);
}
@@ -242,7 +251,7 @@ static int gizmo_arrow_test_select(bContext *UNUSED(C), wmGizmo *gz, const int m
const float arrow_head_threshold_px = 12 * UI_DPI_FAC;
/* Distance to arrow head. */
- if (len_squared_v2v2(mval_fl, arrow_end) < SQUARE(arrow_head_threshold_px)) {
+ if (len_squared_v2v2(mval_fl, arrow_end) < square_f(arrow_head_threshold_px)) {
return 0;
}
@@ -252,7 +261,7 @@ static int gizmo_arrow_test_select(bContext *UNUSED(C), wmGizmo *gz, const int m
/* Clamp inside the line, to avoid overlapping with other gizmos,
* especially around the start of the arrow. */
if (lambda >= 0.0 && lambda <= 1.0) {
- if (len_squared_v2v2(mval_fl, co_isect) < SQUARE(arrow_stem_threshold_px)) {
+ if (len_squared_v2v2(mval_fl, co_isect) < square_f(arrow_stem_threshold_px)) {
return 0;
}
}
@@ -274,8 +283,8 @@ static int gizmo_arrow_modal(bContext *C,
}
ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
GizmoInteraction *inter = gz->interaction_data;
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
float offset[3];
float facdir = 1.0f;
@@ -298,7 +307,7 @@ static int gizmo_arrow_modal(bContext *C,
int ok = 0;
for (int j = 0; j < 2; j++) {
- ED_view3d_win_to_ray(ar, proj[j].mval, proj[j].ray_origin, proj[j].ray_direction);
+ ED_view3d_win_to_ray(region, proj[j].mval, proj[j].ray_origin, proj[j].ray_direction);
/* Force Y axis if we're view aligned */
if (j == 0) {
if (RAD2DEGF(acosf(dot_v3v3(proj[j].ray_direction, arrow->gizmo.matrix_basis[2]))) < 5.0f) {
@@ -353,8 +362,8 @@ static int gizmo_arrow_modal(bContext *C,
}
/* tag the region for redraw */
- ED_region_tag_redraw(ar);
- WM_event_add_mousemove(C);
+ ED_region_tag_redraw_editor_overlays(region);
+ WM_event_add_mousemove(CTX_wm_window(C));
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c
index e36ab0a0610..5617b6e125e 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c
@@ -27,11 +27,11 @@
#include "BKE_context.h"
-#include "ED_view3d.h"
#include "ED_gizmo_library.h"
+#include "ED_view3d.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
/* own includes */
#include "../gizmo_geometry.h"
diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
index ef3014eabc2..04b93f35681 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
@@ -32,12 +32,12 @@
#include "BKE_context.h"
+#include "GPU_batch.h"
+#include "GPU_batch_utils.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_select.h"
-#include "GPU_batch.h"
-#include "GPU_batch_utils.h"
#include "GPU_state.h"
#include "RNA_access.h"
@@ -47,9 +47,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_gizmo_library.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_gizmo_library.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -76,7 +76,8 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz,
const float fill_alpha,
const bool select)
{
- GPU_line_width(gz->line_width);
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -85,10 +86,14 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz,
if (color[3] == 1.0 && fill_alpha == 1.0 && select == false) {
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4fv(color);
- GPU_polygon_smooth(0);
imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION);
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", gz->line_width * U.pixelsize);
+ immUniformColor4fv(color);
imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION);
- GPU_polygon_smooth(1);
immUnbindProgram();
}
else {
@@ -103,9 +108,10 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz,
/* Draw outline. */
if ((fill_alpha != 1.0f) && (select == false)) {
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", gz->line_width * U.pixelsize);
immUniformColor4fv(color);
- GPU_line_width(gz->line_width);
imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION);
immUnbindProgram();
}
@@ -120,6 +126,8 @@ static void button2d_draw_intern(const bContext *C,
const bool highlight)
{
ButtonGizmo2D *button = (ButtonGizmo2D *)gz;
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
if (button->is_init == false) {
@@ -155,9 +163,9 @@ static void button2d_draw_intern(const bContext *C,
float matrix_final_no_offset[4][4];
WM_gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor4fv(color);
- GPU_line_width(gz->line_width);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", gz->line_width * U.pixelsize);
immUniformColor4fv(color);
immBegin(GPU_PRIM_LINE_STRIP, 2);
immVertex3fv(pos, matrix_final[3]);
@@ -197,11 +205,19 @@ static void button2d_draw_intern(const bContext *C,
if (button->shape_batch[0] != NULL) {
GPU_line_smooth(true);
GPU_polygon_smooth(false);
- GPU_line_width(1.0f);
for (uint i = 0; i < ARRAY_SIZE(button->shape_batch) && button->shape_batch[i]; i++) {
- /* Invert line color for wire. */
- GPU_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_2D_UNIFORM_COLOR);
+ const bool do_wires = (i == 1);
+ if (do_wires) {
+ GPU_batch_program_set_builtin(button->shape_batch[i],
+ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+ GPU_batch_uniform_2fv(button->shape_batch[i], "viewportSize", &viewport[2]);
+ GPU_batch_uniform_1f(button->shape_batch[i], "lineWidth", gz->line_width * U.pixelsize);
+ }
+ else {
+ GPU_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_2D_UNIFORM_COLOR);
+ }
+ /* Invert line color for wire. */
if (draw_options & ED_GIZMO_BUTTON_SHOW_BACKDROP) {
/* If we have a backdrop already,
* draw a contrasting shape over it instead of drawing it the same color.
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 2e4284d357a..fd24149e9ea 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
@@ -30,17 +30,17 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_dial_2d.h"
+#include "BLI_math.h"
#include "BLI_rect.h"
#include "BKE_context.h"
-#include "GPU_matrix.h"
-#include "GPU_shader.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "GPU_select.h"
+#include "GPU_shader.h"
#include "GPU_state.h"
#include "RNA_access.h"
@@ -49,9 +49,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_gizmo_library.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_gizmo_library.h"
/* own includes */
#include "../gizmo_library_intern.h"
@@ -162,13 +162,22 @@ static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[2], bool r_con
* Useful for 3D views, see: #ED_GIZMO_CAGE2D_STYLE_BOX
* \{ */
-static void cage2d_draw_box_corners(const rctf *r, const float margin[2], const float color[3])
+static void cage2d_draw_box_corners(const rctf *r,
+ const float margin[2],
+ const float color[3],
+ const float line_width)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
immUniformColor3fv(color);
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
+
+ immUniform1f("lineWidth", line_width * U.pixelsize);
+
immBegin(GPU_PRIM_LINES, 16);
immVertex2f(pos, r->xmin, r->ymin + margin[1]);
@@ -445,7 +454,7 @@ static void cage2d_draw_box_interaction(const float color[4],
.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT),
.col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT),
};
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBindBuiltinProgram(is_solid ? GPU_SHADER_2D_FLAT_COLOR : GPU_SHADER_3D_POLYLINE_FLAT_COLOR);
{
if (is_solid) {
@@ -459,7 +468,12 @@ static void cage2d_draw_box_interaction(const float color[4],
}
else {
BLI_assert(ELEM(prim_type, GPU_PRIM_LINE_STRIP, GPU_PRIM_LINES));
- GPU_line_width(line_width + 3.0f);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
+
+ immUniform1f("lineWidth", (line_width * 3.0f) * U.pixelsize);
immBegin(prim_type, verts_len);
immAttr3f(attr_id.col, 0.0f, 0.0f, 0.0f);
@@ -468,7 +482,7 @@ static void cage2d_draw_box_interaction(const float color[4],
}
immEnd();
- GPU_line_width(line_width);
+ immUniform1f("lineWidth", line_width * U.pixelsize);
immBegin(prim_type, verts_len);
immAttr3fv(attr_id.col, color);
@@ -505,13 +519,19 @@ static void cage2d_draw_circle_wire(const rctf *r,
const float margin[2],
const float color[3],
const int transform_flag,
- const int draw_options)
+ const int draw_options,
+ const float line_width)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
immUniformColor3fv(color);
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", line_width * U.pixelsize);
+
immBegin(GPU_PRIM_LINE_LOOP, 4);
immVertex2f(pos, r->xmin, r->ymin);
immVertex2f(pos, r->xmax, r->ymin);
@@ -662,15 +682,14 @@ static void gizmo_cage2d_draw_intern(wmGizmo *gz,
.ymax = size_real[1],
};
if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
+ float color[4], black[3] = {0, 0, 0};
+ gizmo_color_get(gz, highlight, color);
+
/* corner gizmos */
- GPU_line_width(gz->line_width + 3.0f);
- cage2d_draw_box_corners(&r, margin, (const float[3]){0, 0, 0});
+ cage2d_draw_box_corners(&r, margin, black, gz->line_width + 3.0f);
/* corner gizmos */
- float color[4];
- gizmo_color_get(gz, highlight, color);
- GPU_line_width(gz->line_width);
- cage2d_draw_box_corners(&r, margin, color);
+ cage2d_draw_box_corners(&r, margin, color, gz->line_width);
bool show = false;
if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
@@ -700,30 +719,26 @@ static void gizmo_cage2d_draw_intern(wmGizmo *gz,
}
}
else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
- float color[4];
+ float color[4], black[3] = {0, 0, 0};
gizmo_color_get(gz, highlight, color);
- GPU_line_smooth(true);
GPU_blend(true);
- GPU_line_width(gz->line_width + 3.0f);
- cage2d_draw_circle_wire(&r, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options);
- GPU_line_width(gz->line_width);
- cage2d_draw_circle_wire(&r, margin, color, transform_flag, draw_options);
+ float outline_line_width = gz->line_width + 3.0f;
+ cage2d_draw_circle_wire(&r, margin, black, transform_flag, draw_options, outline_line_width);
+ cage2d_draw_circle_wire(&r, margin, color, transform_flag, draw_options, gz->line_width);
/* corner gizmos */
cage2d_draw_circle_handles(&r, margin, color, transform_flag, true);
cage2d_draw_circle_handles(&r, margin, (const float[3]){0, 0, 0}, transform_flag, false);
GPU_blend(false);
- GPU_line_smooth(false);
}
else {
BLI_assert(0);
}
}
- GPU_line_width(1.0);
GPU_matrix_pop();
}
@@ -1086,8 +1101,8 @@ static int gizmo_cage2d_modal(bContext *C,
}
/* tag the region for redraw */
- ED_region_tag_redraw(CTX_wm_region(C));
- WM_event_add_mousemove(C);
+ ED_region_tag_redraw_editor_overlays(CTX_wm_region(C));
+ WM_event_add_mousemove(CTX_wm_window(C));
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
index 05b58903e04..b0af8641767 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
@@ -34,11 +34,11 @@
#include "BKE_context.h"
-#include "GPU_matrix.h"
-#include "GPU_shader.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "GPU_select.h"
+#include "GPU_shader.h"
#include "GPU_state.h"
#include "RNA_access.h"
@@ -47,9 +47,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_gizmo_library.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_gizmo_library.h"
/* own includes */
#include "../gizmo_library_intern.h"
@@ -130,14 +130,22 @@ static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[3], bool r_con
* Useful for 3D views, see: #ED_GIZMO_CAGE2D_STYLE_BOX
* \{ */
-static void cage3d_draw_box_corners(const float r[3], const float margin[3], const float color[3])
+static void cage3d_draw_box_corners(const float r[3],
+ const float margin[3],
+ const float color[3],
+ const float line_width)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
UNUSED_VARS(margin);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
immUniformColor3fv(color);
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", line_width * U.pixelsize);
+
imm_draw_cube_wire_3d(pos, (float[3]){0}, r);
immUnbindProgram();
@@ -199,13 +207,19 @@ static void cage3d_draw_circle_wire(const float r[3],
const float margin[3],
const float color[3],
const int transform_flag,
- const int draw_options)
+ const int draw_options,
+ const float line_width)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
immUniformColor3fv(color);
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", line_width * U.pixelsize);
+
imm_draw_cube_wire_3d(pos, (float[3]){0}, r);
#if 0
@@ -339,15 +353,14 @@ static void gizmo_cage3d_draw_intern(
};
#endif
if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
+ float color[4], black[3] = {0, 0, 0};
+ gizmo_color_get(gz, highlight, color);
+
/* corner gizmos */
- GPU_line_width(gz->line_width + 3.0f);
- cage3d_draw_box_corners(size_real, margin, (const float[3]){0, 0, 0});
+ cage3d_draw_box_corners(size_real, margin, black, gz->line_width + 3.0f);
/* corner gizmos */
- float color[4];
- gizmo_color_get(gz, highlight, color);
- GPU_line_width(gz->line_width);
- cage3d_draw_box_corners(size_real, margin, color);
+ cage3d_draw_box_corners(size_real, margin, color, gz->line_width);
bool show = false;
if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
@@ -366,34 +379,29 @@ static void gizmo_cage3d_draw_intern(
}
}
else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
- float color[4];
+ float color[4], black[3] = {0, 0, 0};
gizmo_color_get(gz, highlight, color);
- GPU_line_smooth(true);
- GPU_polygon_smooth(true);
GPU_blend(true);
- GPU_line_width(gz->line_width + 3.0f);
cage3d_draw_circle_wire(
- size_real, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options);
- GPU_line_width(gz->line_width);
- cage3d_draw_circle_wire(size_real, margin, color, transform_flag, draw_options);
+ size_real, margin, black, transform_flag, draw_options, gz->line_width + 3.0f);
+ cage3d_draw_circle_wire(
+ size_real, margin, color, transform_flag, draw_options, gz->line_width);
/* corner gizmos */
- cage3d_draw_circle_handles(
- rv3d, matrix_final, size_real, margin, (const float[3]){0, 0, 0}, true, 60);
+ GPU_polygon_smooth(true);
+ cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, black, true, 60);
cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, color, true, 40);
+ GPU_polygon_smooth(false);
GPU_blend(false);
- GPU_polygon_smooth(false);
- GPU_line_smooth(false);
}
else {
BLI_assert(0);
}
}
- GPU_line_width(1.0);
GPU_matrix_pop();
}
@@ -402,15 +410,15 @@ static void gizmo_cage3d_draw_intern(
*/
static void gizmo_cage3d_draw_select(const bContext *C, wmGizmo *gz, int select_id)
{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
gizmo_cage3d_draw_intern(rv3d, gz, true, false, select_id);
}
static void gizmo_cage3d_draw(const bContext *C, wmGizmo *gz)
{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
gizmo_cage3d_draw_intern(rv3d, gz, false, is_highlight, -1);
}
@@ -585,8 +593,8 @@ static int gizmo_cage3d_modal(bContext *C,
}
/* tag the region for redraw */
- ED_region_tag_redraw(CTX_wm_region(C));
- WM_event_add_mousemove(C);
+ ED_region_tag_redraw_editor_overlays(CTX_wm_region(C));
+ WM_event_add_mousemove(CTX_wm_window(C));
return OPERATOR_RUNNING_MODAL;
}
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 6dc81e26bf1..262f4b78b95 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
@@ -50,10 +50,10 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_gizmo_library.h"
#include "ED_screen.h"
-#include "ED_view3d.h"
#include "ED_transform.h"
-#include "ED_gizmo_library.h"
+#include "ED_view3d.h"
/* own includes */
#include "../gizmo_geometry.h"
@@ -111,19 +111,18 @@ static void dial_geom_draw(const float color[4],
ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT) :
ED_GIZMO_DIAL_DRAW_FLAG_FILL)));
- GPU_line_width(line_width);
-
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (clip_plane) {
- immBindBuiltinProgram(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR);
+ immBindBuiltinProgram(filled ? GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR :
+ GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR);
immUniform4fv("ClipPlane", clip_plane);
immUniformMatrix4fv("ModelMatrix", axis_modal_mat);
- glEnable(GL_CLIP_DISTANCE0);
}
else {
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(filled ? GPU_SHADER_3D_UNIFORM_COLOR :
+ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
}
immUniformColor4fv(color);
@@ -151,6 +150,11 @@ static void dial_geom_draw(const float color[4],
}
}
else {
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", line_width * U.pixelsize);
+
if (arc_partial_angle == 0.0f) {
imm_draw_circle_wire_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
if (arc_inner_factor != 0.0f) {
@@ -171,10 +175,6 @@ static void dial_geom_draw(const float color[4],
immUnbindProgram();
- if (clip_plane) {
- glDisable(GL_CLIP_DISTANCE0);
- }
-
UNUSED_VARS(select);
#endif
}
@@ -184,14 +184,20 @@ static void dial_geom_draw(const float color[4],
*/
static void dial_ghostarc_draw_helpline(const float angle,
const float co_outer[3],
- const float color[4])
+ const float color[4],
+ const float line_width)
{
GPU_matrix_push();
GPU_matrix_rotate_3f(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", line_width * U.pixelsize);
immUniformColor4fv(color);
@@ -211,11 +217,17 @@ static void dial_ghostarc_draw_helpline(const float angle,
static void dial_ghostarc_draw_incremental_angle(const float incremental_angle, const float offset)
{
const int tot_incr = (2 * M_PI) / incremental_angle;
- GPU_line_width(1.0f);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
immUniformColor3f(1.0f, 1.0f, 1.0f);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", U.pixelsize);
+
immBegin(GPU_PRIM_LINES, tot_incr * 2);
float v[3] = {0};
@@ -287,15 +299,15 @@ static void dial_ghostarc_draw(const float angle_ofs,
static void dial_ghostarc_get_angles(const wmGizmo *gz,
const wmEvent *event,
- const ARegion *ar,
+ const ARegion *region,
const float mat[4][4],
const float co_outer[3],
float *r_start,
float *r_delta)
{
DialInteraction *inter = gz->interaction_data;
- const RegionView3D *rv3d = ar->regiondata;
- const float mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+ const RegionView3D *rv3d = region->regiondata;
+ const float mval[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin};
/* We might need to invert the direction of the angles. */
float view_vec[3], axis_vec[3];
@@ -312,12 +324,13 @@ static void dial_ghostarc_get_angles(const wmGizmo *gz,
plane_from_point_normal_v3(dial_plane, gz->matrix_basis[3], axis_vec);
- if (!ED_view3d_win_to_3d_on_plane(ar, dial_plane, inter->init.mval, false, proj_mval_init_rel)) {
+ if (!ED_view3d_win_to_3d_on_plane(
+ region, dial_plane, inter->init.mval, false, proj_mval_init_rel)) {
goto fail;
}
sub_v3_v3(proj_mval_init_rel, gz->matrix_basis[3]);
- if (!ED_view3d_win_to_3d_on_plane(ar, dial_plane, mval, false, proj_mval_new_rel)) {
+ if (!ED_view3d_win_to_3d_on_plane(region, dial_plane, mval, false, proj_mval_new_rel)) {
goto fail;
}
sub_v3_v3(proj_mval_new_rel, gz->matrix_basis[3]);
@@ -368,14 +381,12 @@ static void dial_ghostarc_draw_with_helplines(const float angle_ofs,
{
/* Coordinate at which the arc drawing will be started. */
const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f};
- dial_ghostarc_draw(
- angle_ofs, angle_delta, arc_inner_factor, (const float[4]){0.8f, 0.8f, 0.8f, 0.4f});
- GPU_line_width(1.0f);
- dial_ghostarc_draw_helpline(angle_ofs, co_outer, color_helpline);
- if (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE) {
- GPU_line_width(3.0f);
- }
- dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer, color_helpline);
+ const float color_arc_inner[4] = {0.8f, 0.8f, 0.8f, 0.2f};
+ dial_ghostarc_draw(angle_ofs, angle_delta, arc_inner_factor, color_arc_inner);
+
+ float line_width = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE) ? 3.0f : 1.0f;
+ dial_ghostarc_draw_helpline(angle_ofs, co_outer, color_helpline, 1.0f);
+ dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer, color_helpline, line_width);
}
static void dial_draw_intern(
@@ -440,8 +451,8 @@ static void gizmo_dial_draw_select(const bContext *C, wmGizmo *gz, int select_id
float *clip_plane = (draw_options & ED_GIZMO_DIAL_DRAW_FLAG_CLIP) ? clip_plane_buf : NULL;
if (clip_plane) {
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
copy_v3_v3(clip_plane, rv3d->viewinv[2]);
clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]);
@@ -467,8 +478,8 @@ static void gizmo_dial_draw(const bContext *C, wmGizmo *gz)
NULL;
if (clip_plane) {
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
copy_v3_v3(clip_plane, rv3d->viewinv[2]);
clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], gz->matrix_basis[3]);
diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
index f040e67ae44..374b7b1f6a2 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
@@ -46,10 +46,10 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_screen.h"
-#include "ED_view3d.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
#include "ED_transform_snap_object_context.h"
+#include "ED_view3d.h"
/* own includes */
#include "../gizmo_geometry.h"
@@ -106,34 +106,43 @@ static void move_geom_draw(const wmGizmo *gz,
wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_move3d, select);
#else
const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
- const bool filled = ((draw_options & (select ? (ED_GIZMO_MOVE_DRAW_FLAG_FILL |
+ const bool filled = (draw_style != ED_GIZMO_MOVE_STYLE_CROSS_2D) &&
+ ((draw_options & (select ? (ED_GIZMO_MOVE_DRAW_FLAG_FILL |
ED_GIZMO_MOVE_DRAW_FLAG_FILL_SELECT) :
ED_GIZMO_MOVE_DRAW_FLAG_FILL)));
- GPU_line_width(gz->line_width);
-
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(filled ? GPU_SHADER_3D_UNIFORM_COLOR :
+ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", gz->line_width * U.pixelsize);
immUniformColor4fv(color);
+ /* Use the final scale as a radius if it's not already applied to the final matrix. */
+ const float radius = (gz->flag & WM_GIZMO_DRAW_NO_SCALE) ? gz->scale_final : 1.0f;
+
if (draw_style == ED_GIZMO_MOVE_STYLE_RING_2D) {
if (filled) {
- imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION);
+ imm_draw_circle_fill_2d(pos, 0, 0, radius, DIAL_RESOLUTION);
}
else {
- imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION);
+ imm_draw_circle_wire_2d(pos, 0, 0, radius, DIAL_RESOLUTION);
}
}
else if (draw_style == ED_GIZMO_MOVE_STYLE_CROSS_2D) {
+ const float radius_diag = M_SQRT1_2 * radius;
immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, 1.0f, 1.0f);
- immVertex2f(pos, -1.0f, -1.0f);
+ immVertex2f(pos, radius_diag, radius_diag);
+ immVertex2f(pos, -radius_diag, -radius_diag);
- immVertex2f(pos, -1.0f, 1.0f);
- immVertex2f(pos, 1.0f, -1.0f);
+ immVertex2f(pos, -radius_diag, radius_diag);
+ immVertex2f(pos, radius_diag, -radius_diag);
immEnd();
}
else {
@@ -148,7 +157,7 @@ static void move_geom_draw(const wmGizmo *gz,
static void move3d_get_translate(const wmGizmo *gz,
const wmEvent *event,
- const ARegion *ar,
+ const ARegion *region,
float co_delta[3])
{
MoveInteraction *inter = gz->interaction_data;
@@ -157,12 +166,12 @@ static void move3d_get_translate(const wmGizmo *gz,
event->mval[1] - inter->init.mval[1],
};
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
float co_ref[3];
mul_v3_mat3_m4v3(co_ref, gz->matrix_space, inter->init.prop_co);
const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
- ED_view3d_win_to_delta(ar, mval_delta, co_delta, zfac);
+ ED_view3d_win_to_delta(region, mval_delta, co_delta, zfac);
float matrix_space_inv[3][3];
copy_m3_m4(matrix_space_inv, gz->matrix_space);
@@ -246,11 +255,11 @@ static int gizmo_move_modal(bContext *C,
return OPERATOR_RUNNING_MODAL;
}
MoveGizmo3D *move = (MoveGizmo3D *)gz;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float prop_delta[3];
if (CTX_wm_area(C)->spacetype == SPACE_VIEW3D) {
- move3d_get_translate(gz, event, ar, prop_delta);
+ move3d_get_translate(gz, event, region, prop_delta);
}
else {
float mval_proj_init[2], mval_proj_curr[2];
@@ -260,6 +269,9 @@ static int gizmo_move_modal(bContext *C,
return OPERATOR_RUNNING_MODAL;
}
sub_v2_v2v2(prop_delta, mval_proj_curr, mval_proj_init);
+ if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
+ mul_v2_fl(prop_delta, gz->scale_final);
+ }
prop_delta[2] = 0.0f;
}
@@ -276,6 +288,7 @@ static int gizmo_move_modal(bContext *C,
float co[3];
if (ED_transform_snap_object_project_view3d(
inter->snap_context_v3d,
+ CTX_data_ensure_evaluated_depsgraph(C),
(SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
@@ -303,7 +316,7 @@ static int gizmo_move_modal(bContext *C,
zero_v3(move->prop_co);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_editor_overlays(region);
inter->prev.tweak_flag = tweak_flag;
@@ -364,17 +377,12 @@ static int gizmo_move_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
WM_gizmo_calc_matrix_final(gz, inter->init.matrix_final);
if (use_snap) {
- ScrArea *sa = CTX_wm_area(C);
- if (sa) {
- switch (sa->spacetype) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area) {
+ switch (area->spacetype) {
case SPACE_VIEW3D: {
inter->snap_context_v3d = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C),
- CTX_data_scene(C),
- CTX_data_ensure_evaluated_depsgraph(C),
- 0,
- CTX_wm_region(C),
- CTX_wm_view3d(C));
+ CTX_data_main(C), CTX_data_scene(C), 0, CTX_wm_region(C), CTX_wm_view3d(C));
break;
}
default:
@@ -398,8 +406,10 @@ static int gizmo_move_test_select(bContext *C, wmGizmo *gz, const int mval[2])
return -1;
}
- /* The 'gz->scale_final' is already applied when projecting. */
- if (len_squared_v2(point_local) < 1.0f) {
+ /* The 'gz->scale_final' is already applied to the projection
+ * when #WM_GIZMO_DRAW_NO_SCALE isn't set. */
+ const float radius = (gz->flag & WM_GIZMO_DRAW_NO_SCALE) ? gz->scale_final : 1.0f;
+ if (len_squared_v2(point_local) < radius) {
return 0;
}
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 21f1801f7eb..4083169d65c 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -43,7 +43,6 @@ set(SRC
gpencil_add_monkey.c
gpencil_add_stroke.c
gpencil_armature.c
- gpencil_brush.c
gpencil_convert.c
gpencil_data.c
gpencil_edit.c
@@ -54,9 +53,14 @@ set(SRC
gpencil_ops_versioning.c
gpencil_paint.c
gpencil_primitive.c
+ gpencil_sculpt_paint.c
gpencil_select.c
gpencil_undo.c
gpencil_utils.c
+ gpencil_uv.c
+ gpencil_vertex_ops.c
+ gpencil_vertex_paint.c
+ gpencil_weight_paint.c
gpencil_intern.h
)
diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c
index 6e91be862a9..22df7bbbf31 100644
--- a/source/blender/editors/gpencil/annotate_draw.c
+++ b/source/blender/editors/gpencil/annotate_draw.c
@@ -21,17 +21,18 @@
* \ingroup edgpencil
*/
+#include <float.h>
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
-#include <float.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_sys_types.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -39,12 +40,12 @@
#include "BLT_translation.h"
#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "DNA_view3d_types.h"
#include "DNA_userdef_types.h"
-#include "DNA_object_types.h"
+#include "DNA_view3d_types.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -59,8 +60,8 @@
#include "ED_gpencil.h"
#include "ED_screen.h"
-#include "ED_view3d.h"
#include "ED_space_api.h"
+#include "ED_view3d.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
@@ -89,14 +90,54 @@ typedef enum eDrawStrokeFlags {
/* ----- Tool Buffer Drawing ------ */
+static void annotation_draw_stroke_arrow_buffer(uint pos,
+ const float *corner_point,
+ const float *arrow_coords,
+ const int arrow_style)
+{
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, arrow_style);
+
+ switch (arrow_style) {
+ case GP_STROKE_ARROWSTYLE_SEGMENT:
+ immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
+ immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
+ break;
+ case GP_STROKE_ARROWSTYLE_CLOSED:
+ immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
+ immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
+ immVertex2f(pos, arrow_coords[4], arrow_coords[5]);
+ immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
+ break;
+ case GP_STROKE_ARROWSTYLE_OPEN:
+ immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
+ immVertex2f(pos, corner_point[0], corner_point[1]);
+ immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
+ break;
+ case GP_STROKE_ARROWSTYLE_SQUARE:
+ immVertex2f(pos, corner_point[0], corner_point[1]);
+ immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
+ immVertex2f(pos, arrow_coords[4], arrow_coords[5]);
+ immVertex2f(pos, arrow_coords[6], arrow_coords[7]);
+ immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
+ immVertex2f(pos, corner_point[0], corner_point[1]);
+ break;
+ default:
+ break;
+ }
+ immEnd();
+}
+
/* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
-static void annotation_draw_stroke_buffer(const tGPspoint *points,
- int totpoints,
+static void annotation_draw_stroke_buffer(bGPdata *gps,
short thickness,
short dflag,
- short sflag,
const float ink[4])
{
+ bGPdata_Runtime runtime = gps->runtime;
+ const tGPspoint *points = runtime.sbuffer;
+ int totpoints = runtime.sbuffer_used;
+ short sflag = runtime.sbuffer_sflag;
+
int draw_points = 0;
/* error checking */
@@ -175,6 +216,26 @@ static void annotation_draw_stroke_buffer(const tGPspoint *points,
}
immEnd();
+
+ /* Draw arrow stroke. */
+ if (totpoints > 1) {
+ /* Draw ending arrow stroke. */
+ if ((sflag & GP_STROKE_USE_ARROW_END) &&
+ (runtime.arrow_end_style != GP_STROKE_ARROWSTYLE_NONE)) {
+ float end[2];
+ copy_v2_fl2(end, points[1].x, points[1].y);
+ annotation_draw_stroke_arrow_buffer(pos, end, runtime.arrow_end, runtime.arrow_end_style);
+ }
+ /* Draw starting arrow stroke. */
+ if ((sflag & GP_STROKE_USE_ARROW_START) &&
+ (runtime.arrow_start_style != GP_STROKE_ARROWSTYLE_NONE)) {
+ float start[2];
+ copy_v2_fl2(start, points[0].x, points[0].y);
+ annotation_draw_stroke_arrow_buffer(
+ pos, start, runtime.arrow_start, runtime.arrow_start_style);
+ }
+ }
+
immUnbindProgram();
}
@@ -208,7 +269,6 @@ static void annotation_calc_2d_stroke_fxy(
/* draw a given stroke - just a single dot (only one point) */
static void annotation_draw_stroke_point(const bGPDspoint *points,
short thickness,
- short UNUSED(dflag),
short sflag,
int offsx,
int offsy,
@@ -251,12 +311,8 @@ static void annotation_draw_stroke_point(const bGPDspoint *points,
}
/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
-static void annotation_draw_stroke_3d(const bGPDspoint *points,
- int totpoints,
- short thickness,
- short UNUSED(sflag),
- const float ink[4],
- bool cyclic)
+static void annotation_draw_stroke_3d(
+ const bGPDspoint *points, int totpoints, short thickness, const float ink[4], bool cyclic)
{
float curpressure = points[0].pressure;
float cyclic_fpt[3];
@@ -332,13 +388,10 @@ static void annotation_draw_stroke_3d(const bGPDspoint *points,
immUnbindProgram();
}
-/* ----- Fancy 2D-Stroke Drawing ------ */
-
-/* draw a given stroke in 2d */
+/* Draw a given stroke in 2d. */
static void annotation_draw_stroke_2d(const bGPDspoint *points,
int totpoints,
short thickness_s,
- short dflag,
short sflag,
int offsx,
int offsy,
@@ -346,167 +399,84 @@ static void annotation_draw_stroke_2d(const bGPDspoint *points,
int winy,
const float ink[4])
{
- /* otherwise thickness is twice that of the 3D view */
- float thickness = (float)thickness_s * 0.5f;
-
- /* strokes in Image Editor need a scale factor, since units there are not pixels! */
- float scalefac = 1.0f;
- if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
- scalefac = 0.001f;
+ if (totpoints == 0) {
+ return;
}
+ float thickness = (float)thickness_s;
- /* Tessellation code - draw stroke as series of connected quads
- * (triangle strips in fact) with connection edges rotated to minimize shrinking artifacts,
- * and rounded endcaps.
- */
- {
- const bGPDspoint *pt1, *pt2;
- float s0[2], s1[2]; /* segment 'center' points */
- float pm[2]; /* normal from previous segment. */
- int i;
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ const bGPDspoint *pt;
+ const bGPDspoint *pt_prev;
+ int draw_points = 0;
+ float co[2];
+ float oldpressure = points[0].pressure;
+ if (totpoints == 1) {
+ /* if drawing a single point, draw it larger */
+ GPU_point_size((float)(thickness + 2) * points->pressure);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+ immUniformColor3fvAlpha(ink, ink[3]);
+ immBegin(GPU_PRIM_POINTS, 1);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ annotation_calc_2d_stroke_fxy(&points->x, sflag, offsx, offsy, winx, winy, co);
+ immVertex2fv(pos, co);
+ }
+ else {
+ /* draw stroke curve */
+ GPU_line_width(max_ff(oldpressure * thickness, 1.0));
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3fvAlpha(ink, ink[3]);
- immBegin(GPU_PRIM_TRI_STRIP, totpoints * 2 + 4);
-
- /* get x and y coordinates from first point */
- annotation_calc_2d_stroke_fxy(&points->x, sflag, offsx, offsy, winx, winy, s0);
-
- for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) {
- float t0[2], t1[2]; /* tessellated coordinates */
- float m1[2], m2[2]; /* gradient and normal */
- float mt[2], sc[2]; /* gradient for thickness, point for end-cap */
- float pthick; /* thickness at segment point */
-
- /* Get x and y coordinates from point2
- * (point1 has already been computed in previous iteration). */
- annotation_calc_2d_stroke_fxy(&pt2->x, sflag, offsx, offsy, winx, winy, s1);
-
- /* calculate gradient and normal - 'angle'=(ny/nx) */
- m1[1] = s1[1] - s0[1];
- m1[0] = s1[0] - s0[0];
- normalize_v2(m1);
- m2[1] = -m1[0];
- m2[0] = m1[1];
-
- /* always use pressure from first point here */
- pthick = (pt1->pressure * thickness * scalefac);
-
- /* if the first segment, start of segment is segment's normal */
- if (i == 0) {
- /* draw start cap first
- * - make points slightly closer to center (about halfway across)
- */
- mt[0] = m2[0] * pthick * 0.5f;
- mt[1] = m2[1] * pthick * 0.5f;
- sc[0] = s0[0] - (m1[0] * pthick * 0.75f);
- sc[1] = s0[1] - (m1[1] * pthick * 0.75f);
-
- t0[0] = sc[0] - mt[0];
- t0[1] = sc[1] - mt[1];
- t1[0] = sc[0] + mt[0];
- t1[1] = sc[1] + mt[1];
-
- /* First two points of cap. */
- immVertex2fv(pos, t0);
- immVertex2fv(pos, t1);
-
- /* calculate points for start of segment */
- mt[0] = m2[0] * pthick;
- mt[1] = m2[1] * pthick;
-
- t0[0] = s0[0] - mt[0];
- t0[1] = s0[1] - mt[1];
- t1[0] = s0[0] + mt[0];
- t1[1] = s0[1] + mt[1];
-
- /* Last two points of start cap (and first two points of first segment). */
- immVertex2fv(pos, t0);
- immVertex2fv(pos, t1);
- }
- /* if not the first segment, use bisector of angle between segments */
- else {
- float mb[2]; /* bisector normal */
- float athick, dfac; /* actual thickness, difference between thicknesses */
-
- /* calculate gradient of bisector (as average of normals) */
- mb[0] = (pm[0] + m2[0]) / 2;
- mb[1] = (pm[1] + m2[1]) / 2;
- normalize_v2(mb);
-
- /* calculate gradient to apply
- * - as basis, use just pthick * bisector gradient
- * - if cross-section not as thick as it should be, add extra padding to fix it
- */
- mt[0] = mb[0] * pthick;
- mt[1] = mb[1] * pthick;
- athick = len_v2(mt);
- dfac = pthick - (athick * 2);
-
- if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) {
- mt[0] += (mb[0] * dfac);
- mt[1] += (mb[1] * dfac);
+
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints);
+
+ for (int i = 0; i < totpoints; i++) {
+ pt = &points[i];
+ /* If there was a significant pressure change,
+ * stop the curve, change the thickness of the stroke,
+ * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP).
+ */
+ if (fabsf(pt->pressure - oldpressure) > 0.2f) {
+ /* need to have 2 points to avoid immEnd assert error */
+ if (draw_points < 2) {
+ pt_prev = &points[i - 1];
+ annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
+ immVertex2fv(pos, co);
}
- /* calculate points for start of segment */
- t0[0] = s0[0] - mt[0];
- t0[1] = s0[1] - mt[1];
- t1[0] = s0[0] + mt[0];
- t1[1] = s0[1] + mt[1];
+ immEnd();
+ draw_points = 0;
- /* Last two points of previous segment, and first two points of current segment. */
- immVertex2fv(pos, t0);
- immVertex2fv(pos, t1);
- }
+ GPU_line_width(max_ff(pt->pressure * thickness, 1.0f));
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1);
+
+ /* need to roll-back one point to ensure that there are no gaps in the stroke */
+ if (i != 0) {
+ pt_prev = &points[i - 1];
+ annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
+ immVertex2fv(pos, co);
+ draw_points++;
+ }
- /* if last segment, also draw end of segment (defined as segment's normal) */
- if (i == totpoints - 2) {
- /* for once, we use second point's pressure (otherwise it won't be drawn) */
- pthick = (pt2->pressure * thickness * scalefac);
-
- /* calculate points for end of segment */
- mt[0] = m2[0] * pthick;
- mt[1] = m2[1] * pthick;
-
- t0[0] = s1[0] - mt[0];
- t0[1] = s1[1] - mt[1];
- t1[0] = s1[0] + mt[0];
- t1[1] = s1[1] + mt[1];
-
- /* Last two points of last segment (and first two points of end cap). */
- immVertex2fv(pos, t0);
- immVertex2fv(pos, t1);
-
- /* draw end cap as last step
- * - make points slightly closer to center (about halfway across)
- */
- mt[0] = m2[0] * pthick * 0.5f;
- mt[1] = m2[1] * pthick * 0.5f;
- sc[0] = s1[0] + (m1[0] * pthick * 0.75f);
- sc[1] = s1[1] + (m1[1] * pthick * 0.75f);
-
- t0[0] = sc[0] - mt[0];
- t0[1] = sc[1] - mt[1];
- t1[0] = sc[0] + mt[0];
- t1[1] = sc[1] + mt[1];
-
- /* Last two points of end cap. */
- immVertex2fv(pos, t0);
- immVertex2fv(pos, t1);
+ oldpressure = pt->pressure; /* reset our threshold */
}
- /* store computed point2 coordinates as point1 ones of next segment. */
- copy_v2_v2(s0, s1);
- /* store stroke's 'natural' normal for next stroke to use */
- copy_v2_v2(pm, m2);
+ /* now the point we want */
+ annotation_calc_2d_stroke_fxy(&pt->x, sflag, offsx, offsy, winx, winy, co);
+ immVertex2fv(pos, co);
+ draw_points++;
+ }
+ /* need to have 2 points to avoid immEnd assert error */
+ if (draw_points < 2) {
+ pt_prev = &points[0];
+ annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
+ immVertex2fv(pos, co);
}
-
- immEnd();
- immUnbindProgram();
}
+
+ immEnd();
+ immUnbindProgram();
}
/* ----- Strokes Drawing ------ */
@@ -549,9 +519,7 @@ static bool annotation_can_draw_stroke(const bGPDstroke *gps, const int dflag)
}
/* draw a set of strokes */
-static void annotation_draw_strokes(bGPdata *UNUSED(gpd),
- bGPDlayer *UNUSED(gpl),
- const bGPDframe *gpf,
+static void annotation_draw_strokes(const bGPDframe *gpf,
int offsx,
int offsy,
int winx,
@@ -562,7 +530,7 @@ static void annotation_draw_strokes(bGPdata *UNUSED(gpd),
{
GPU_program_point_size(true);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* check if stroke can be drawn */
if (annotation_can_draw_stroke(gps, dflag) == false) {
continue;
@@ -586,11 +554,11 @@ static void annotation_draw_strokes(bGPdata *UNUSED(gpd),
/* 3D Lines - OpenGL primitives-based */
if (gps->totpoints == 1) {
annotation_draw_stroke_point(
- gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color);
+ gps->points, lthick, gps->flag, offsx, offsy, winx, winy, color);
}
else {
annotation_draw_stroke_3d(
- gps->points, gps->totpoints, lthick, gps->flag, color, gps->flag & GP_STROKE_CYCLIC);
+ gps->points, gps->totpoints, lthick, color, gps->flag & GP_STROKE_CYCLIC);
}
if (no_xray) {
@@ -604,180 +572,22 @@ static void annotation_draw_strokes(bGPdata *UNUSED(gpd),
/* 2D Strokes... */
if (gps->totpoints == 1) {
annotation_draw_stroke_point(
- gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color);
- }
- else {
- annotation_draw_stroke_2d(gps->points,
- gps->totpoints,
- lthick,
- dflag,
- gps->flag,
- offsx,
- offsy,
- winx,
- winy,
- color);
- }
- }
- }
-
- GPU_program_point_size(false);
-}
-
-/* Draw selected verts for strokes being edited */
-static void annotation_draw_strokes_edit(bGPdata *gpd,
- bGPDlayer *gpl,
- const bGPDframe *gpf,
- int offsx,
- int offsy,
- int winx,
- int winy,
- short dflag,
- short UNUSED(lflag),
- float alpha)
-{
- /* if alpha 0 do not draw */
- if (alpha == 0.0f) {
- return;
- }
-
- const bool no_xray = (dflag & GP_DRAWDATA_NO_XRAY) != 0;
- int mask_orig = 0;
-
- /* set up depth masks... */
- if (dflag & GP_DRAWDATA_ONLY3D) {
- if (no_xray) {
- glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
- glDepthMask(0);
- GPU_depth_test(true);
-
- /* first arg is normally rv3d->dist, but this isn't
- * available here and seems to work quite well without */
- bglPolygonOffset(1.0f, 1.0f);
- }
- }
-
- GPU_program_point_size(true);
-
- /* draw stroke verts */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- /* check if stroke can be drawn */
- if (annotation_can_draw_stroke(gps, dflag) == false) {
- continue;
- }
-
- /* Optimization: only draw points for selected strokes
- * We assume that selected points can only occur in
- * strokes that are selected too.
- */
- if ((gps->flag & GP_STROKE_SELECT) == 0) {
- continue;
- }
-
- /* Get size of verts:
- * - The selected state needs to be larger than the unselected state so that
- * they stand out more.
- * - We use the theme setting for size of the unselected verts
- */
- float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
- float vsize;
- if ((int)bsize > 8) {
- vsize = 10.0f;
- bsize = 8.0f;
- }
- else {
- vsize = bsize + 2;
- }
-
- float selectColor[4];
- UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
- selectColor[3] = alpha;
-
- GPUVertFormat *format = immVertexFormat();
- uint pos; /* specified later */
- uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- if (gps->flag & GP_STROKE_3DSPACE) {
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
- }
- else {
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR);
- }
-
- immBegin(GPU_PRIM_POINTS, gps->totpoints);
-
- /* Draw start and end point differently if enabled stroke direction hint */
- bool show_direction_hint = (gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
-
- /* Draw all the stroke points (selected or not) */
- bGPDspoint *pt = gps->points;
- for (int i = 0; i < gps->totpoints; i++, pt++) {
- /* size and color first */
- if (show_direction_hint && i == 0) {
- /* start point in green bigger */
- immAttr3f(color, 0.0f, 1.0f, 0.0f);
- immAttr1f(size, vsize + 4);
- }
- else if (show_direction_hint && (i == gps->totpoints - 1)) {
- /* end point in red smaller */
- immAttr3f(color, 1.0f, 0.0f, 0.0f);
- immAttr1f(size, vsize + 1);
- }
- else if (pt->flag & GP_SPOINT_SELECT) {
- immAttr3fv(color, selectColor);
- immAttr1f(size, vsize);
+ gps->points, lthick, gps->flag, offsx, offsy, winx, winy, color);
}
else {
- immAttr3fv(color, gpl->color);
- immAttr1f(size, bsize);
- }
-
- /* then position */
- if (gps->flag & GP_STROKE_3DSPACE) {
- immVertex3fv(pos, &pt->x);
- }
- else {
- float co[2];
- annotation_calc_2d_stroke_fxy(&pt->x, gps->flag, offsx, offsy, winx, winy, co);
- immVertex2fv(pos, co);
+ annotation_draw_stroke_2d(
+ gps->points, gps->totpoints, lthick, gps->flag, offsx, offsy, winx, winy, color);
}
}
-
- immEnd();
- immUnbindProgram();
}
GPU_program_point_size(false);
-
- /* clear depth mask */
- if (dflag & GP_DRAWDATA_ONLY3D) {
- if (no_xray) {
- glDepthMask(mask_orig);
- GPU_depth_test(false);
-
- bglPolygonOffset(0.0, 0.0);
-#if 0
- glDisable(GL_POLYGON_OFFSET_LINE);
- glPolygonOffset(0, 0);
-#endif
- }
- }
}
/* ----- General Drawing ------ */
/* draw onion-skinning for a layer */
-static void annotation_draw_onionskins(bGPdata *gpd,
- bGPDlayer *gpl,
- bGPDframe *gpf,
- int offsx,
- int offsy,
- int winx,
- int winy,
- int UNUSED(cfra),
- int dflag)
+static void annotation_draw_onionskins(
+ bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag)
{
const float alpha = 1.0f;
float color[4];
@@ -796,8 +606,7 @@ static void annotation_draw_onionskins(bGPdata *gpd,
/* alpha decreases with distance from curframe index */
fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
color[3] = alpha * fac * 0.66f;
- annotation_draw_strokes(
- gpd, gpl, gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
+ annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
}
else {
break;
@@ -808,8 +617,7 @@ static void annotation_draw_onionskins(bGPdata *gpd,
/* draw the strokes for the ghost frames (at half of the alpha set by user) */
if (gpf->prev) {
color[3] = (alpha / 7);
- annotation_draw_strokes(
- gpd, gpl, gpf->prev, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
+ annotation_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
}
}
else {
@@ -830,8 +638,7 @@ static void annotation_draw_onionskins(bGPdata *gpd,
/* alpha decreases with distance from curframe index */
fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
color[3] = alpha * fac * 0.66f;
- annotation_draw_strokes(
- gpd, gpl, gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
+ annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
}
else {
break;
@@ -842,8 +649,7 @@ static void annotation_draw_onionskins(bGPdata *gpd,
/* draw the strokes for the ghost frames (at half of the alpha set by user) */
if (gpf->next) {
color[3] = (alpha / 4);
- annotation_draw_strokes(
- gpd, gpl, gpf->next, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
+ annotation_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
}
}
else {
@@ -853,11 +659,11 @@ static void annotation_draw_onionskins(bGPdata *gpd,
/* loop over gpencil data layers, drawing them */
static void annotation_draw_data_layers(
- bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag, float alpha)
+ bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
float ink[4];
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* verify never thickness is less than 1 */
CLAMP_MIN(gpl->thickness, 1.0f);
short lthick = gpl->thickness;
@@ -872,7 +678,7 @@ static void annotation_draw_data_layers(
}
/* get frame to draw */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_USE_PREV);
if (gpf == NULL) {
continue;
}
@@ -890,26 +696,11 @@ static void annotation_draw_data_layers(
/* Draw 'onionskins' (frame left + right) */
if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
- annotation_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag);
+ annotation_draw_onionskins(gpl, gpf, offsx, offsy, winx, winy, dflag);
}
/* draw the strokes already in active frame */
- annotation_draw_strokes(gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, lthick, ink);
-
- /* Draw verts of selected strokes:
- * - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
- * - locked layers can't be edited, so there's no point showing these verts
- * as they will have no bearings on what gets edited
- * - only show when in editmode, since operators shouldn't work otherwise
- * (NOTE: doing it this way means that the toggling editmode
- * shows visible change immediately).
- */
- /* XXX: perhaps we don't want to show these when users are drawing... */
- if ((G.f & G_FLAG_RENDER_VIEWPORT) == 0 && (gpl->flag & GP_LAYER_LOCKED) == 0 &&
- (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
- annotation_draw_strokes_edit(
- gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, alpha);
- }
+ annotation_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, lthick, ink);
/* Check if may need to draw the active stroke cache, only if this layer is the active layer
* that is being edited. (Stroke buffer is currently stored in gp-data)
@@ -922,67 +713,14 @@ static void annotation_draw_data_layers(
* It should also be noted that sbuffer contains temporary point types
* i.e. tGPspoints NOT bGPDspoints
*/
- annotation_draw_stroke_buffer(gpd->runtime.sbuffer,
- gpd->runtime.sbuffer_used,
- lthick,
- dflag,
- gpd->runtime.sbuffer_sflag,
- ink);
+ annotation_draw_stroke_buffer(gpd, lthick, dflag, ink);
}
}
}
-/* draw a short status message in the top-right corner */
-static void annotation_draw_status_text(const bGPdata *gpd, ARegion *ar)
-{
-
- /* Cannot draw any status text when drawing OpenGL Renders */
- if (G.f & G_FLAG_RENDER_VIEWPORT) {
- return;
- }
-
- /* Get bounds of region - Necessary to avoid problems with region overlap */
- const rcti *rect = ED_region_visible_rect(ar);
-
- /* for now, this should only be used to indicate when we are in stroke editmode */
- if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
- const char *printable = IFACE_("GPencil Stroke Editing");
- float printable_size[2];
-
- int font_id = BLF_default();
-
- BLF_width_and_height(
- font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
-
- int xco = (rect->xmax - U.widget_unit) - (int)printable_size[0];
- int yco = (rect->ymax - U.widget_unit);
-
- /* text label */
- UI_FontThemeColor(font_id, TH_TEXT_HI);
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
-#else
- BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
-#endif
-
- /* grease pencil icon... */
- // XXX: is this too intrusive?
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- xco -= U.widget_unit;
- yco -= (int)printable_size[1] / 2;
-
- UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
-
- GPU_blend(false);
- }
-}
-
/* draw grease-pencil datablock */
static void annotation_draw_data(
- bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag, float alpha)
+ bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
/* turn on smooth lines (i.e. anti-aliasing) */
GPU_line_smooth(true);
@@ -993,7 +731,7 @@ static void annotation_draw_data(
GPU_blend(true);
/* draw! */
- annotation_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha);
+ annotation_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag);
/* turn off alpha blending, then smooth lines */
GPU_blend(false); // alpha blending
@@ -1013,7 +751,6 @@ static void annotation_draw_data_all(Scene *scene,
const char spacetype)
{
bGPdata *gpd_source = NULL;
- float alpha = 1.0f;
if (scene) {
if (spacetype == SPACE_VIEW3D) {
@@ -1026,14 +763,14 @@ static void annotation_draw_data_all(Scene *scene,
}
if (gpd_source) {
- annotation_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag, alpha);
+ annotation_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag);
}
}
/* scene/clip data has already been drawn, only object/track data is drawn here
* if gpd_source == gpd, we don't have any object/track data and we can skip */
if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
- annotation_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha);
+ annotation_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag);
}
}
@@ -1049,8 +786,8 @@ static void annotation_draw_data_all(Scene *scene,
void ED_annotation_draw_2dimage(const bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
int offsx, offsy, sizex, sizey;
@@ -1062,7 +799,7 @@ void ED_annotation_draw_2dimage(const bContext *C)
}
/* calculate rect */
- switch (sa->spacetype) {
+ switch (area->spacetype) {
case SPACE_IMAGE: /* image */
case SPACE_CLIP: /* clip */
{
@@ -1071,10 +808,11 @@ void ED_annotation_draw_2dimage(const bContext *C)
* so disabled. */
offsx = 0;
offsy = 0;
- sizex = ar->winx;
- sizey = ar->winy;
+ sizex = region->winx;
+ sizey = region->winy;
- wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
+ wmOrtho2(
+ region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, region->v2d.cur.ymax);
dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK;
break;
@@ -1084,8 +822,8 @@ void ED_annotation_draw_2dimage(const bContext *C)
/* just draw using standard scaling (settings here are currently ignored anyways) */
offsx = 0;
offsy = 0;
- sizex = ar->winx;
- sizey = ar->winy;
+ sizex = region->winx;
+ sizey = region->winy;
/* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
* and everything moved to standard View2d
@@ -1096,8 +834,8 @@ void ED_annotation_draw_2dimage(const bContext *C)
default: /* for spacetype not yet handled */
offsx = 0;
offsy = 0;
- sizex = ar->winx;
- sizey = ar->winy;
+ sizex = region->winx;
+ sizey = region->winy;
dflag |= GP_DRAWDATA_ONLYI2D;
break;
@@ -1110,7 +848,7 @@ void ED_annotation_draw_2dimage(const bContext *C)
}
/* draw it! */
- annotation_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype);
+ annotation_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, area->spacetype);
}
/**
@@ -1123,13 +861,13 @@ void ED_annotation_draw_2dimage(const bContext *C)
void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
{
wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
int dflag = 0;
/* check that we have grease-pencil stuff to draw */
- if (sa == NULL) {
+ if (area == NULL) {
return;
}
bGPdata *gpd = ED_annotation_data_get_active(C);
@@ -1140,7 +878,7 @@ void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
/* special hack for Image Editor */
/* FIXME: the opengl poly-strokes don't draw at right thickness when done this way,
* so disabled. */
- if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
+ if (ELEM(area->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
dflag |= GP_DRAWDATA_IEDITHACK;
}
@@ -1152,26 +890,23 @@ void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
dflag |= GP_DRAWDATA_NO_ONIONS;
}
- annotation_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype);
-
- /* draw status text (if in screen/pixel-space) */
- if (!onlyv2d) {
- annotation_draw_status_text(gpd, ar);
- }
+ annotation_draw_data_all(
+ scene, gpd, 0, 0, region->winx, region->winy, CFRA, dflag, area->spacetype);
}
-/* draw annotations sketches to specified 3d-view assuming that matrices are already set correctly
- * Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
+/* draw annotations sketches to specified 3d-view assuming that matrices are already set
+ * correctly Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
* second time with only3d=false for screen-aligned strokes */
void ED_annotation_draw_view3d(
- Scene *scene, struct Depsgraph *depsgraph, View3D *v3d, ARegion *ar, bool only3d)
+ Scene *scene, struct Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d)
{
int dflag = 0;
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
int offsx, offsy, winx, winy;
/* check that we have grease-pencil stuff to draw */
- /* XXX: Hardcoded reference here may get out of sync if we change how we fetch annotation data */
+ /* XXX: Hardcoded reference here may get out of sync if we change how we fetch annotation data
+ */
bGPdata *gpd = scene->gpd;
if (gpd == NULL) {
return;
@@ -1181,7 +916,7 @@ void ED_annotation_draw_view3d(
* deal with the camera border, otherwise map the coords to the camera border. */
if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_FLAG_RENDER_VIEWPORT)) {
rctf rectf;
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &rectf, true); /* no shift */
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &rectf, true); /* no shift */
offsx = round_fl_to_int(rectf.xmin);
offsy = round_fl_to_int(rectf.ymin);
@@ -1191,8 +926,8 @@ void ED_annotation_draw_view3d(
else {
offsx = 0;
offsy = 0;
- winx = ar->winx;
- winy = ar->winy;
+ winx = region->winx;
+ winy = region->winy;
}
/* set flags */
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 5eaf14e361b..c53b90fbfee 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -21,18 +21,18 @@
* \ingroup edgpencil
*/
-#include <stdio.h>
+#include <math.h>
#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_math_geom.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -48,17 +48,17 @@
#include "BKE_screen.h"
#include "BKE_tracking.h"
+#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_gpencil_types.h"
#include "DNA_windowmanager_types.h"
#include "UI_view2d.h"
+#include "ED_clip.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_clip.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
@@ -100,6 +100,9 @@ typedef enum eGPencil_PaintFlags {
GP_PAINTFLAG_STROKEADDED = (1 << 1),
GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2),
GP_PAINTFLAG_SELECTMASK = (1 << 3),
+ /* Flags used to indicate if stabilization is being used. */
+ GP_PAINTFLAG_USE_STABILIZER = (1 << 7),
+ GP_PAINTFLAG_USE_STABILIZER_TEMP = (1 << 8),
} eGPencil_PaintFlags;
/* Temporary 'Stroke' Operation data
@@ -114,9 +117,9 @@ typedef struct tGPsdata {
/** window where painting originated. */
wmWindow *win;
/** area where painting originated. */
- ScrArea *sa;
+ ScrArea *area;
/** region where painting originated. */
- ARegion *ar;
+ ARegion *region;
/** needed for GP_STROKE_2DSPACE. */
View2D *v2d;
/** for using the camera rect within the 3d view. */
@@ -148,6 +151,11 @@ typedef struct tGPsdata {
/** radius of influence for eraser. */
short radius;
+ /* Stabilizer. */
+ float stabilizer_factor;
+ char stabilizer_radius;
+ void *stabilizer_cursor;
+
/** current mouse-position. */
float mval[2];
/** previous recorded mouse-position. */
@@ -278,6 +286,18 @@ static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2
* - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
*/
}
+ /* If lazy mouse, check minimum distance. */
+ else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
+ if ((dx * dx + dy * dy) > (p->stabilizer_radius * p->stabilizer_radius)) {
+ return true;
+ }
+ else {
+ /* If the mouse is moving within the radius of the last move,
+ * don't update the mouse position. This allows sharp turns. */
+ copy_v2_v2(p->mval, p->mvalo);
+ return false;
+ }
+ }
else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) {
return true;
@@ -306,7 +326,8 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
if (gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) {
int mval_i[2];
round_v2i_v2fl(mval_i, mval);
- if (gpencil_project_check(p) && (ED_view3d_autodist_simple(p->ar, mval_i, out, 0, depth))) {
+ if (gpencil_project_check(p) &&
+ (ED_view3d_autodist_simple(p->region, mval_i, out, 0, depth))) {
/* projecting onto 3D-Geometry
* - nothing more needs to be done here, since view_autodist_simple() has already done it
*/
@@ -326,13 +347,13 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
*/
gp_get_3d_reference(p, rvec);
- zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL);
+ zfac = ED_view3d_calc_zfac(p->region->regiondata, rvec, NULL);
- if (ED_view3d_project_float_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
+ if (ED_view3d_project_float_global(p->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK) {
float mval_f[2];
sub_v2_v2v2(mval_f, mval_prj, mval);
- ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac);
+ ED_view3d_win_to_delta(p->region, mval_f, dvec, zfac);
sub_v3_v3v3(out, rvec, dvec);
}
else {
@@ -350,8 +371,8 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
/* 2d - relative to screen (viewport area) */
else {
if (p->subrect == NULL) { /* normal 3D view */
- out[0] = (float)(mval[0]) / (float)(p->ar->winx) * 100;
- out[1] = (float)(mval[1]) / (float)(p->ar->winy) * 100;
+ out[0] = (float)(mval[0]) / (float)(p->region->winx) * 100;
+ out[1] = (float)(mval[1]) / (float)(p->region->winy) * 100;
}
else { /* camera view, use subrect */
out[0] = ((mval[0] - p->subrect->xmin) / BLI_rctf_size_x(p->subrect)) * 100;
@@ -417,6 +438,85 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
copy_v2_v2(&ptc->x, c);
}
+static void gp_stroke_arrow_calc_points_segment(float stroke_points[8],
+ const float ref_point[2],
+ const float dir_cw[2],
+ const float dir_ccw[2],
+ const float lenght,
+ const float sign)
+{
+ stroke_points[0] = ref_point[0] + dir_cw[0] * lenght * sign;
+ stroke_points[1] = ref_point[1] + dir_cw[1] * lenght * sign;
+ stroke_points[2] = ref_point[0] + dir_ccw[0] * lenght * sign;
+ stroke_points[3] = ref_point[1] + dir_ccw[1] * lenght * sign;
+}
+
+static void gp_stroke_arrow_calc_points(tGPspoint *point,
+ const float stroke_dir[2],
+ float corner[2],
+ float stroke_points[8],
+ const int arrow_style)
+{
+ const int arrow_lenght = 8;
+ float norm_dir[2];
+ copy_v2_v2(norm_dir, stroke_dir);
+ normalize_v2(norm_dir);
+ const float inv_norm_dir_clockwise[2] = {norm_dir[1], -norm_dir[0]};
+ const float inv_norm_dir_counterclockwise[2] = {-norm_dir[1], norm_dir[0]};
+
+ switch (arrow_style) {
+ case GP_STROKE_ARROWSTYLE_OPEN:
+ mul_v2_fl(norm_dir, arrow_lenght);
+ stroke_points[0] = corner[0] + inv_norm_dir_clockwise[0] * arrow_lenght + norm_dir[0];
+ stroke_points[1] = corner[1] + inv_norm_dir_clockwise[1] * arrow_lenght + norm_dir[1];
+ stroke_points[2] = corner[0] + inv_norm_dir_counterclockwise[0] * arrow_lenght + norm_dir[0];
+ stroke_points[3] = corner[1] + inv_norm_dir_counterclockwise[1] * arrow_lenght + norm_dir[1];
+ break;
+ case GP_STROKE_ARROWSTYLE_SEGMENT:
+ gp_stroke_arrow_calc_points_segment(stroke_points,
+ corner,
+ inv_norm_dir_clockwise,
+ inv_norm_dir_counterclockwise,
+ arrow_lenght,
+ 1.0f);
+ break;
+ case GP_STROKE_ARROWSTYLE_CLOSED:
+ mul_v2_fl(norm_dir, arrow_lenght);
+ if (point != NULL) {
+ add_v2_v2(&point->x, norm_dir);
+ copy_v2_v2(corner, &point->x);
+ }
+ gp_stroke_arrow_calc_points_segment(stroke_points,
+ corner,
+ inv_norm_dir_clockwise,
+ inv_norm_dir_counterclockwise,
+ arrow_lenght,
+ -1.0f);
+ stroke_points[4] = corner[0] - norm_dir[0];
+ stroke_points[5] = corner[1] - norm_dir[1];
+ break;
+ case GP_STROKE_ARROWSTYLE_SQUARE:
+ mul_v2_fl(norm_dir, arrow_lenght * 1.5f);
+ if (point != NULL) {
+ add_v2_v2(&point->x, norm_dir);
+ copy_v2_v2(corner, &point->x);
+ }
+ gp_stroke_arrow_calc_points_segment(stroke_points,
+ corner,
+ inv_norm_dir_clockwise,
+ inv_norm_dir_counterclockwise,
+ arrow_lenght * 0.75f,
+ -1.0f);
+ stroke_points[4] = stroke_points[0] - norm_dir[0];
+ stroke_points[5] = stroke_points[1] - norm_dir[1];
+ stroke_points[6] = stroke_points[2] - norm_dir[0];
+ stroke_points[7] = stroke_points[3] - norm_dir[1];
+ break;
+ default:
+ break;
+ }
+}
+
/* add current stroke-point to buffer (returns whether point was successfully added) */
static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime)
{
@@ -456,6 +556,32 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
/* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
gpd->runtime.sbuffer_used = 2;
+
+ /* Arrows. */
+ if (gpd->runtime.sbuffer_sflag & (GP_STROKE_USE_ARROW_START | GP_STROKE_USE_ARROW_END)) {
+ /* Store start and end point coords for arrows. */
+ float end[2];
+ copy_v2_v2(end, &pt->x);
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer));
+ float start[2];
+ copy_v2_v2(start, &pt->x);
+
+ /* Arrow end corner. */
+ if (gpd->runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_END) {
+ pt++;
+ float e_heading[2] = {start[0] - end[0], start[1] - end[1]};
+ /* Calculate points for ending arrow. */
+ gp_stroke_arrow_calc_points(
+ pt, e_heading, end, gpd->runtime.arrow_end, gpd->runtime.arrow_end_style);
+ }
+ /* Arrow start corner. */
+ if (gpd->runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_START) {
+ float s_heading[2] = {end[0] - start[0], end[1] - start[1]};
+ /* Calculate points for starting arrow. */
+ gp_stroke_arrow_calc_points(
+ NULL, s_heading, start, gpd->runtime.arrow_start, gpd->runtime.arrow_start_style);
+ }
+ }
}
/* can keep carrying on this way :) */
@@ -480,16 +606,20 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
/* increment counters */
gpd->runtime.sbuffer_used++;
- /* smooth while drawing previous points with a reduction factor for previous */
- for (int s = 0; s < 3; s++) {
- gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s);
+
+ /* Don't smooth if stabilizer is on. */
+ if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) {
+ /* smooth while drawing previous points with a reduction factor for previous */
+ for (int s = 0; s < 3; s++) {
+ gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s);
+ }
}
return GP_STROKEADD_NORMAL;
}
else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
/* get pointer to destination point */
- pt = (tGPspoint *)(gpd->runtime.sbuffer);
+ pt = (tGPspoint *)gpd->runtime.sbuffer;
/* store settings */
copy_v2_v2(&pt->x, mval);
@@ -520,11 +650,13 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
* so initialize depth buffer before converting coordinates
*/
if (gpencil_project_check(p)) {
- View3D *v3d = p->sa->spacedata.first;
+ View3D *v3d = p->area->spacedata.first;
- view3d_region_operator_needs_opengl(p->win, p->ar);
- ED_view3d_autodist_init(
- p->depsgraph, p->ar, v3d, (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ view3d_region_operator_needs_opengl(p->win, p->region);
+ ED_view3d_autodist_init(p->depsgraph,
+ p->region,
+ v3d,
+ (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
}
/* convert screen-coordinates to appropriate coordinates (and store them) */
@@ -534,9 +666,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
pts->pressure = pt->pressure;
pts->strength = pt->strength;
pts->time = pt->time;
-
- /* force fill recalc */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->tot_triangles = 0;
}
/* increment counters */
@@ -551,6 +681,123 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
return GP_STROKEADD_INVALID;
}
+static void gp_stroke_arrow_init_point_default(bGPDspoint *pt)
+{
+ pt->pressure = 1.0f;
+ pt->strength = 1.0f;
+ pt->time = 1.0f;
+}
+
+static void gp_stroke_arrow_init_conv_point(bGPDspoint *pt, const float point[3])
+{
+ copy_v3_v3(&pt->x, point);
+ gp_stroke_arrow_init_point_default(pt);
+}
+
+static void gp_stroke_arrow_init_point(
+ tGPsdata *p, tGPspoint *ptc, bGPDspoint *pt, const float co[8], const int co_idx)
+{
+ /* Note: provided co_idx should be always pair number as it's [x1, y1, x2, y2, x3, y3]. */
+ float real_co[2] = {co[co_idx], co[co_idx + 1]};
+ copy_v2_v2(&ptc->x, real_co);
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+ gp_stroke_arrow_init_point_default(pt);
+}
+
+static void gp_stroke_arrow_allocate(bGPDstroke *gps, const int totpoints)
+{
+ /* Copy appropriate settings for stroke. */
+ gps->totpoints = totpoints;
+ /* Allocate enough memory for a continuous array for storage points. */
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+}
+
+static void gp_arrow_create_open(tGPsdata *p,
+ tGPspoint *ptc,
+ bGPDspoint *pt,
+ const float corner_point[3],
+ const float arrow_points[8])
+{
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0);
+ pt++;
+ gp_stroke_arrow_init_conv_point(pt, corner_point);
+ pt++;
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2);
+}
+
+static void gp_arrow_create_segm(tGPsdata *p,
+ tGPspoint *ptc,
+ bGPDspoint *pt,
+ const float arrow_points[8])
+{
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0);
+ pt++;
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2);
+}
+
+static void gp_arrow_create_closed(tGPsdata *p,
+ tGPspoint *ptc,
+ bGPDspoint *pt,
+ const float arrow_points[8])
+{
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0);
+ pt++;
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2);
+ pt++;
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4);
+ pt++;
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0);
+}
+
+static void gp_arrow_create_square(tGPsdata *p,
+ tGPspoint *ptc,
+ bGPDspoint *pt,
+ const float corner_point[3],
+ const float arrow_points[8])
+{
+ gp_stroke_arrow_init_conv_point(pt, corner_point);
+ pt++;
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0);
+ pt++;
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4);
+ pt++;
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 6);
+ pt++;
+ gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2);
+ pt++;
+ gp_stroke_arrow_init_conv_point(pt, corner_point);
+}
+
+static void gp_arrow_create(tGPsdata *p,
+ tGPspoint *ptc,
+ bGPDspoint *pt,
+ bGPDstroke *arrow_stroke,
+ const float arrow_points[8],
+ const int style)
+{
+ float corner_conv[3];
+ copy_v3_v3(corner_conv, &pt->x);
+
+ switch (style) {
+ case GP_STROKE_ARROWSTYLE_SEGMENT:
+ gp_arrow_create_segm(p, ptc, pt, arrow_points);
+ break;
+ case GP_STROKE_ARROWSTYLE_CLOSED:
+ gp_arrow_create_closed(p, ptc, pt, arrow_points);
+ break;
+ case GP_STROKE_ARROWSTYLE_OPEN:
+ gp_arrow_create_open(p, ptc, pt, corner_conv, arrow_points);
+ break;
+ case GP_STROKE_ARROWSTYLE_SQUARE:
+ gp_arrow_create_square(p, ptc, pt, corner_conv, arrow_points);
+ break;
+ default:
+ break;
+ }
+ /* Link stroke to frame. */
+ BLI_addtail(&p->gpf->strokes, arrow_stroke);
+}
+
/* make a new stroke from the buffer data */
static void gp_stroke_newfrombuffer(tGPsdata *p)
{
@@ -601,14 +848,13 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* copy appropriate settings for stroke */
gps->totpoints = totelem;
gps->thickness = gpl->thickness;
- gps->gradient_f = 1.0f;
- gps->gradient_s[0] = 1.0f;
- gps->gradient_s[1] = 1.0f;
+ gps->fill_opacity_fac = 1.0f;
+ gps->hardeness = 1.0f;
+ copy_v2_fl(gps->aspect_ratio, 1.0f);
+ gps->uv_scale = 1.0f;
gps->flag = gpd->runtime.sbuffer_sflag;
gps->inittime = p->inittime;
-
- /* enable recalculation flag by default (only used if hq fill) */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->tot_triangles = 0;
/* allocate enough memory for a continuous array for storage points */
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
@@ -637,17 +883,61 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
if (totelem == 2) {
- /* last point if applicable */
- ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_used - 1);
+ bGPdata_Runtime runtime = gpd->runtime;
- /* convert screen-coordinates to appropriate coordinates (and store them) */
+ /* Last point if applicable. */
+ ptc = ((tGPspoint *)runtime.sbuffer) + (runtime.sbuffer_used - 1);
+
+ /* Convert screen-coordinates to appropriate coordinates (and store them). */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* copy pressure and time */
+ /* Copy pressure and time. */
pt->pressure = ptc->pressure;
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt->time = ptc->time;
+
+ /** Create arrow strokes. **/
+ /* End arrow stroke. */
+ if ((runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_END) &&
+ (runtime.arrow_end_style != GP_STROKE_ARROWSTYLE_NONE)) {
+ int totarrowpoints = runtime.arrow_end_style;
+
+ /* Setting up arrow stroke. */
+ bGPDstroke *e_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false);
+ gp_stroke_arrow_allocate(e_arrow_gps, totarrowpoints);
+
+ /* Set pointer to first non-initialized point. */
+ pt = e_arrow_gps->points + (e_arrow_gps->totpoints - totarrowpoints);
+
+ /* End point. */
+ ptc = ((tGPspoint *)runtime.sbuffer) + (runtime.sbuffer_used - 1);
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+ gp_stroke_arrow_init_point_default(pt);
+
+ /* Fill and convert arrow points to create arrow shape. */
+ gp_arrow_create(p, ptc, pt, e_arrow_gps, runtime.arrow_end, runtime.arrow_end_style);
+ }
+ /* Start arrow stroke. */
+ if ((runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_START) &&
+ (runtime.arrow_start_style != GP_STROKE_ARROWSTYLE_NONE)) {
+ int totarrowpoints = runtime.arrow_start_style;
+
+ /* Setting up arrow stroke. */
+ bGPDstroke *s_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false);
+ gp_stroke_arrow_allocate(s_arrow_gps, totarrowpoints);
+
+ /* Set pointer to first non-initialized point. */
+ pt = s_arrow_gps->points + (s_arrow_gps->totpoints - totarrowpoints);
+
+ /* Start point. */
+ ptc = runtime.sbuffer;
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
+ gp_stroke_arrow_init_point_default(pt);
+
+ /* Fill and convert arrow points to create arrow shape. */
+ gp_arrow_create(p, ptc, pt, s_arrow_gps, runtime.arrow_start, runtime.arrow_start_style);
+ }
}
}
else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
@@ -676,9 +966,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used; i++, ptc++, pt++) {
round_v2i_v2fl(mval_i, &ptc->x);
- if ((ED_view3d_autodist_depth(p->ar, mval_i, depth_margin, depth_arr + i) == 0) &&
+ if ((ED_view3d_autodist_depth(p->region, mval_i, depth_margin, depth_arr + i) == 0) &&
(i && (ED_view3d_autodist_depth_seg(
- p->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
+ p->region, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
interp_depth = true;
}
else {
@@ -793,12 +1083,12 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
const int x,
const int y)
{
- if ((p->sa->spacetype == SPACE_VIEW3D) && (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH)) {
- RegionView3D *rv3d = p->ar->regiondata;
+ if ((p->area->spacetype == SPACE_VIEW3D) && (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH)) {
+ RegionView3D *rv3d = p->region->regiondata;
const int mval_i[2] = {x, y};
float mval_3d[3];
- if (ED_view3d_autodist_simple(p->ar, mval_i, mval_3d, 0, NULL)) {
+ if (ED_view3d_autodist_simple(p->region, mval_i, mval_3d, 0, NULL)) {
const float depth_mval = view3d_point_depth(rv3d, mval_3d);
const float depth_pt = view3d_point_depth(rv3d, &pt->x);
@@ -816,7 +1106,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
bGPDframe *gpf,
bGPDstroke *gps,
const float mval[2],
- const float mvalo[2],
const int radius,
const rcti *rect)
{
@@ -885,7 +1174,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
* eraser region (either within stroke painted, or on its lines)
* - this assumes that linewidth is irrelevant
*/
- if (gp_stroke_inside_circle(mval, mvalo, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
+ if (gp_stroke_inside_circle(mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
if ((gp_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) ||
(gp_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) {
/* Edge is affected - Check individual points now */
@@ -921,11 +1210,11 @@ static void gp_stroke_doeraser(tGPsdata *p)
rect.xmax = p->mval[0] + p->radius;
rect.ymax = p->mval[1] + p->radius;
- if (p->sa->spacetype == SPACE_VIEW3D) {
+ if (p->area->spacetype == SPACE_VIEW3D) {
if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
- View3D *v3d = p->sa->spacedata.first;
- view3d_region_operator_needs_opengl(p->win, p->ar);
- ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, 0);
+ View3D *v3d = p->area->spacedata.first;
+ view3d_region_operator_needs_opengl(p->win, p->region);
+ ED_view3d_autodist_init(p->depsgraph, p->region, v3d, 0);
}
}
@@ -937,8 +1226,8 @@ static void gp_stroke_doeraser(tGPsdata *p)
/* Not all strokes in the datablock may be valid in the current editor/context
* (e.g. 2D space strokes in the 3D view, if the same datablock is shared)
*/
- if (ED_gpencil_stroke_can_use_direct(p->sa, gps)) {
- gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, p->mvalo, p->radius, &rect);
+ if (ED_gpencil_stroke_can_use_direct(p->area, gps)) {
+ gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, p->radius, &rect);
}
}
}
@@ -967,7 +1256,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = NULL;
ScrArea *curarea = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ToolSettings *ts = CTX_data_tool_settings(C);
/* make sure the active view (at the starting time) is a 3d-view */
@@ -992,17 +1281,17 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
/* supported views first */
case SPACE_VIEW3D: {
/* View3D *v3d = curarea->spacedata.first; */
- /* RegionView3D *rv3d = ar->regiondata; */
+ /* RegionView3D *rv3d = region->regiondata; */
/* set current area
* - must verify that region data is 3D-view (and not something else)
*/
/* CAUTION: If this is the "toolbar", then this will change on the first stroke */
- p->sa = curarea;
- p->ar = ar;
+ p->area = curarea;
+ p->region = region;
p->align_flag = &ts->annotate_v3d_align;
- if (ar->regiondata == NULL) {
+ if (region->regiondata == NULL) {
p->status = GP_STATUS_ERROR;
if (G.debug & G_DEBUG) {
printf(
@@ -1017,9 +1306,9 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
/* SpaceNode *snode = curarea->spacedata.first; */
/* set current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
+ p->area = curarea;
+ p->region = region;
+ p->v2d = &region->v2d;
p->align_flag = &ts->gpencil_v2d_align;
break;
}
@@ -1027,9 +1316,9 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
SpaceSeq *sseq = curarea->spacedata.first;
/* set current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
+ p->area = curarea;
+ p->region = region;
+ p->v2d = &region->v2d;
p->align_flag = &ts->gpencil_seq_align;
/* check that gpencil data is allowed to be drawn */
@@ -1046,9 +1335,9 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
/* SpaceImage *sima = curarea->spacedata.first; */
/* set the current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
+ p->area = curarea;
+ p->region = region;
+ p->v2d = &region->v2d;
p->align_flag = &ts->gpencil_ima_align;
break;
}
@@ -1062,9 +1351,9 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
}
/* set the current area */
- p->sa = curarea;
- p->ar = ar;
- p->v2d = &ar->v2d;
+ p->area = curarea;
+ p->region = region;
+ p->v2d = &region->v2d;
p->align_flag = &ts->gpencil_v2d_align;
invert_m4_m4(p->imat, sc->unistabmat);
@@ -1204,7 +1493,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
ToolSettings *ts = scene->toolsettings;
/* get active layer (or add a new one if non-existent) */
- p->gpl = BKE_gpencil_layer_getactive(p->gpd);
+ p->gpl = BKE_gpencil_layer_active_get(p->gpd);
if (p->gpl == NULL) {
/* tag for annotations */
p->gpd->flag |= GP_DATA_ANNOTATIONS;
@@ -1232,7 +1521,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
*/
bool has_layer_to_erase = false;
- if (gpencil_layer_is_editable(p->gpl)) {
+ if (BKE_gpencil_layer_is_editable(p->gpl)) {
/* Ensure that there's stuff to erase here (not including selection mask below)... */
if (p->gpl->actframe && p->gpl->actframe->strokes.first) {
has_layer_to_erase = true;
@@ -1260,7 +1549,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode);
+ p->gpf = BKE_gpencil_layer_frame_get(p->gpl, CFRA, add_frame_mode);
if (p->gpf == NULL) {
p->status = GP_STATUS_ERROR;
@@ -1280,7 +1569,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
p->gpd->runtime.sbuffer_sflag |= GP_STROKE_ERASER;
/* check if we should respect depth while erasing */
- if (p->sa->spacetype == SPACE_VIEW3D) {
+ if (p->area->spacetype == SPACE_VIEW3D) {
if (p->gpl->flag & GP_LAYER_NO_XRAY) {
p->flags |= GP_PAINTFLAG_V3D_ERASER_DEPTH;
}
@@ -1290,7 +1579,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* disable eraser flags - so that we can switch modes during a session */
p->gpd->runtime.sbuffer_sflag &= ~GP_STROKE_ERASER;
- if (p->sa->spacetype == SPACE_VIEW3D) {
+ if (p->area->spacetype == SPACE_VIEW3D) {
if (p->gpl->flag & GP_LAYER_NO_XRAY) {
p->flags &= ~GP_PAINTFLAG_V3D_ERASER_DEPTH;
}
@@ -1303,15 +1592,15 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* when drawing in the camera view, in 2D space, set the subrect */
p->subrect = NULL;
if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) {
- if (p->sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = p->sa->spacedata.first;
- RegionView3D *rv3d = p->ar->regiondata;
+ if (p->area->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = p->area->spacedata.first;
+ RegionView3D *rv3d = p->region->regiondata;
/* for camera view set the subrect */
if (rv3d->persp == RV3D_CAMOB) {
/* no shift */
ED_view3d_calc_camera_border(
- p->scene, depsgraph, p->ar, v3d, rv3d, &p->subrect_data, true);
+ p->scene, depsgraph, p->region, v3d, rv3d, &p->subrect_data, true);
p->subrect = &p->subrect_data;
}
}
@@ -1321,8 +1610,8 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
p->gsc.gpd = p->gpd;
p->gsc.gpl = p->gpl;
- p->gsc.sa = p->sa;
- p->gsc.ar = p->ar;
+ p->gsc.area = p->area;
+ p->gsc.region = p->region;
p->gsc.v2d = p->v2d;
p->gsc.subrect_data = p->subrect_data;
@@ -1332,7 +1621,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* check if points will need to be made in view-aligned space */
if (*p->align_flag & GP_PROJECT_VIEWSPACE) {
- switch (p->sa->spacetype) {
+ switch (p->area->spacetype) {
case SPACE_VIEW3D: {
p->gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
break;
@@ -1356,12 +1645,12 @@ static void gp_paint_strokeend(tGPsdata *p)
* the conversions will project the values correctly...
*/
if (gpencil_project_check(p)) {
- View3D *v3d = p->sa->spacedata.first;
+ View3D *v3d = p->area->spacedata.first;
/* need to restore the original projection settings before packing up */
- view3d_region_operator_needs_opengl(p->win, p->ar);
+ view3d_region_operator_needs_opengl(p->win, p->region);
ED_view3d_autodist_init(
- p->depsgraph, p->ar, v3d, (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ p->depsgraph, p->region, v3d, (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
}
/* check if doing eraser or not */
@@ -1457,6 +1746,67 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en
p);
}
}
+static void gpencil_draw_stabilizer(bContext *C, int x, int y, void *p_ptr)
+{
+ ARegion *region = CTX_wm_region(C);
+ tGPsdata *p = (tGPsdata *)p_ptr;
+ bGPdata_Runtime runtime = p->gpd->runtime;
+ const tGPspoint *points = runtime.sbuffer;
+ int totpoints = runtime.sbuffer_used;
+ if (totpoints < 2) {
+ return;
+ }
+ const tGPspoint *pt = &points[totpoints - 1];
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ GPU_line_width(1.25f);
+ const float color[3] = {1.0f, 0.39f, 0.39f};
+
+ /* default radius and color */
+ float darkcolor[3];
+ const float radius = 4.0f;
+
+ /* Inner Ring: Color from UI panel */
+ immUniformColor4f(color[0], color[1], color[2], 0.8f);
+ imm_draw_circle_wire_2d(pos, x, y, radius, 40);
+
+ /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
+ mul_v3_v3fl(darkcolor, color, 0.40f);
+ immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f);
+ imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40);
+
+ /* Rope Simple. */
+ immUniformColor4f(color[0], color[1], color[2], 0.8f);
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, pt->x + region->winrct.xmin, pt->y + region->winrct.ymin);
+ immVertex2f(pos, x, y);
+ immEnd();
+
+ /* Returns back all GPU settings */
+ GPU_blend(false);
+ GPU_line_smooth(false);
+
+ immUnbindProgram();
+}
+
+/* Turn *stabilizer* brush cursor in 3D view on/off */
+static void gpencil_draw_toggle_stabilizer_cursor(bContext *C, tGPsdata *p, short enable)
+{
+ if (p->stabilizer_cursor && !enable) {
+ /* clear cursor */
+ WM_paint_cursor_end(CTX_wm_manager(C), p->stabilizer_cursor);
+ p->stabilizer_cursor = NULL;
+ }
+ else if (enable && !p->stabilizer_cursor) {
+ /* enable cursor */
+ p->stabilizer_cursor = WM_paint_cursor_activate(
+ CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p);
+ }
+}
/* Check if tablet eraser is being used (when processing events) */
static bool gpencil_is_tablet_eraser_active(const wmEvent *event)
@@ -1480,6 +1830,9 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
/* turn off radial brush cursor */
gpencil_draw_toggle_eraser_cursor(C, p, false);
}
+ else if (p->paintmode == GP_PAINTMODE_DRAW) {
+ gpencil_draw_toggle_stabilizer_cursor(C, p, false);
+ }
/* always store the new eraser size to be used again next time
* NOTE: Do this even when not in eraser mode, as eraser may
@@ -1567,8 +1920,8 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
"ESC/Enter to end (or click outside this area)"));
break;
default:
- /* Do nothing - the others are self explanatory, exit quickly once the mouse is released
- * Showing any text would just be annoying as it would flicker.
+ /* Do nothing - the others are self explanatory, exit quickly once the mouse is
+ * released Showing any text would just be annoying as it would flicker.
*/
break;
}
@@ -1633,6 +1986,16 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph
/* Only add current point to buffer if mouse moved
* (even though we got an event, it might be just noise). */
else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) {
+ /* If lazy mouse, interpolate the last and current mouse positions. */
+ if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
+ float now_mouse[2];
+ float last_mouse[2];
+ copy_v2_v2(now_mouse, p->mval);
+ copy_v2_v2(last_mouse, p->mvalo);
+ interp_v2_v2v2(now_mouse, now_mouse, last_mouse, min_ff(p->stabilizer_factor, .995f));
+ copy_v2_v2(p->mval, now_mouse);
+ }
+
/* try to add point */
short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
@@ -1676,7 +2039,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph
/* handle draw event */
static void annotation_draw_apply_event(
- wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
+ bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
{
tGPsdata *p = op->customdata;
PointerRNA itemptr;
@@ -1688,8 +2051,23 @@ static void annotation_draw_apply_event(
p->mval[0] = (float)event->mval[0] - x;
p->mval[1] = (float)event->mval[1] - y;
+ /* Key to toggle stabilization. */
+ if (event->shift > 0 && p->paintmode == GP_PAINTMODE_DRAW) {
+ /* Using permanent stabilization, shift will deactivate the flag. */
+ if (p->flags & (GP_PAINTFLAG_USE_STABILIZER)) {
+ if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
+ gpencil_draw_toggle_stabilizer_cursor(C, p, false);
+ p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP;
+ }
+ }
+ /* Not using any stabilization flag. Activate temporal one. */
+ else if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) {
+ p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
+ gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ }
+ }
/* verify key status for straight lines */
- if ((event->ctrl > 0) || (event->alt > 0)) {
+ else if ((event->ctrl > 0) || (event->alt > 0)) {
if (p->straight[0] == 0) {
int dx = abs((int)(p->mval[0] - p->mvalo[0]));
int dy = abs((int)(p->mval[1] - p->mvalo[1]));
@@ -1710,6 +2088,22 @@ static void annotation_draw_apply_event(
}
else {
p->straight[0] = 0;
+ /* We were using shift while having permanent stabilization actived,
+ so activate the temp flag back again. */
+ if (p->flags & GP_PAINTFLAG_USE_STABILIZER) {
+ if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) {
+ gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
+ }
+ }
+ /* We are using the temporal stabilizer flag atm,
+ but shift is not pressed as well as the permanent flag is not used,
+ so we don't need the cursor anymore. */
+ else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
+ /* Reset temporal stabilizer flag and remove cursor. */
+ p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP;
+ gpencil_draw_toggle_stabilizer_cursor(C, p, false);
+ }
}
p->curtime = PIL_check_seconds_timer();
@@ -1776,7 +2170,7 @@ static void annotation_draw_apply_event(
/* force refresh */
/* just active area for now, since doing whole screen is too slow */
- ED_region_tag_redraw(p->ar);
+ ED_region_tag_redraw(p->region);
}
/* ------------------------------- */
@@ -1897,12 +2291,35 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* TODO: set any additional settings that we can take from the events?
* TODO? if tablet is erasing, force eraser to be on? */
- /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... */
+ /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway...
+ */
/* if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
gpencil_draw_toggle_eraser_cursor(C, p, true);
}
+ else if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
+ if (RNA_enum_get(op->ptr, "arrowstyle_start") != GP_STROKE_ARROWSTYLE_NONE) {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_USE_ARROW_START;
+ p->gpd->runtime.arrow_start_style = RNA_enum_get(op->ptr, "arrowstyle_start");
+ }
+ if (RNA_enum_get(op->ptr, "arrowstyle_end") != GP_STROKE_ARROWSTYLE_NONE) {
+ p->gpd->runtime.sbuffer_sflag |= GP_STROKE_USE_ARROW_END;
+ p->gpd->runtime.arrow_end_style = RNA_enum_get(op->ptr, "arrowstyle_end");
+ }
+ }
+ else if (p->paintmode == GP_PAINTMODE_DRAW) {
+ p->stabilizer_factor = RNA_float_get(op->ptr, "stabilizer_factor");
+ p->stabilizer_radius = RNA_int_get(op->ptr, "stabilizer_radius");
+ if (RNA_boolean_get(op->ptr, "use_stabilizer")) {
+ p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP;
+ gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ }
+ else if (event->shift > 0) {
+ p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
+ gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ }
+ }
/* set cursor
* NOTE: This may change later (i.e. intentionally via brush toggle,
* or unintentionally if the user scrolls outside the area)...
@@ -1916,7 +2333,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
p->status = GP_STATUS_PAINTING;
/* handle the initial drawing - i.e. for just doing a simple dot */
- annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
+ annotation_draw_apply_event(C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
else {
@@ -1932,10 +2349,10 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
}
/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
-static bool gpencil_area_exists(bContext *C, ScrArea *sa_test)
+static bool gpencil_area_exists(bContext *C, ScrArea *area_test)
{
- bScreen *sc = CTX_wm_screen(C);
- return (BLI_findindex(&sc->areabase, sa_test) != -1);
+ bScreen *screen = CTX_wm_screen(C);
+ return (BLI_findindex(&screen->areabase, area_test) != -1);
}
static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
@@ -1945,7 +2362,7 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
/* we must check that we're still within the area that we're set up to work from
* otherwise we could crash (see bug #20586)
*/
- if (CTX_wm_area(C) != p->sa) {
+ if (CTX_wm_area(C) != p->area) {
printf("\t\t\tGP - wrong area execution abort!\n");
p->status = GP_STATUS_ERROR;
}
@@ -2008,7 +2425,7 @@ static void annotation_add_missing_events(bContext *C,
interp_v2_v2v2(pt, a, b, 0.5f);
sub_v2_v2v2(pt, b, pt);
/* create fake event */
- annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]);
+ annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]);
}
else if (dist >= factor) {
int slices = 2 + (int)((dist - 1.0) / factor);
@@ -2017,7 +2434,7 @@ static void annotation_add_missing_events(bContext *C,
interp_v2_v2v2(pt, a, b, n * i);
sub_v2_v2v2(pt, b, pt);
/* create fake event */
- annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]);
+ annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]);
}
}
}
@@ -2043,27 +2460,42 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
*/
if (p->status == GP_STATUS_IDLING) {
- ARegion *ar = CTX_wm_region(C);
- p->ar = ar;
+ ARegion *region = CTX_wm_region(C);
+ p->region = region;
}
/* We don't pass on key events, GP is used with key-modifiers -
* prevents Dkey to insert drivers. */
if (ISKEYBOARD(event->type)) {
- if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY, ZKEY)) {
+ if (ELEM(event->type,
+ EVT_LEFTARROWKEY,
+ EVT_DOWNARROWKEY,
+ EVT_RIGHTARROWKEY,
+ EVT_UPARROWKEY,
+ EVT_ZKEY)) {
/* allow some keys:
* - for frame changing [#33412]
* - for undo (during sketching sessions)
*/
}
- else if (ELEM(event->type, PAD0, PAD1, PAD2, PAD3, PAD4, PAD5, PAD6, PAD7, PAD8, PAD9)) {
+ else if (ELEM(event->type,
+ EVT_PAD0,
+ EVT_PAD1,
+ EVT_PAD2,
+ EVT_PAD3,
+ EVT_PAD4,
+ EVT_PAD5,
+ EVT_PAD6,
+ EVT_PAD7,
+ EVT_PAD8,
+ EVT_PAD9)) {
/* allow numpad keys so that camera/view manipulations can still take place
* - PAD0 in particular is really important for Grease Pencil drawing,
* as animators may be working "to camera", so having this working
* is essential for ensuring that they can quickly return to that view
*/
}
- else if ((event->type == BKEY) && (event->val == KM_RELEASE)) {
+ else if ((event->type == EVT_BKEY) && (event->val == KM_RELEASE)) {
/* Add Blank Frame
* - Since this operator is non-modal, we can just call it here, and keep going...
* - This operator is especially useful when animating
@@ -2083,7 +2515,8 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* NOTE: cannot do RIGHTMOUSE (as is standard for canceling)
* as that would break polyline T32647.
*/
- if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, EKEY)) {
+ if (event->val == KM_PRESS &&
+ ELEM(event->type, EVT_RETKEY, EVT_PADENTER, EVT_ESCKEY, EVT_SPACEKEY, EVT_EKEY)) {
/* exit() ends the current stroke before cleaning up */
/* printf("\t\tGP - end of paint op + end of stroke\n"); */
p->status = GP_STATUS_DONE;
@@ -2091,7 +2524,8 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* toggle painting mode upon mouse-button movement
- * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox only)
+ * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox
+ * only)
* - RIGHTMOUSE = polyline (hotkey) / eraser (all)
* (Disabling RIGHTMOUSE case here results in bugs like [#32647])
* also making sure we have a valid event value, to not exit too early
@@ -2151,27 +2585,28 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* NOTE: An exception here is that if launched from the toolbar,
* whatever region we're now in should become the new region
*/
- if ((p->ar) && (p->ar->regiontype == RGN_TYPE_TOOLS)) {
+ if ((p->region) && (p->region->regiontype == RGN_TYPE_TOOLS)) {
/* Change to whatever region is now under the mouse */
- ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y);
+ ARegion *current_region = BKE_area_find_region_xy(
+ p->area, RGN_TYPE_ANY, event->x, event->y);
if (G.debug & G_DEBUG) {
- printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
+ printf("found alternative region %p (old was %p) - at %d %d (area: %d %d -> %d %d)\n",
current_region,
- p->ar,
+ p->region,
event->x,
event->y,
- p->sa->totrct.xmin,
- p->sa->totrct.ymin,
- p->sa->totrct.xmax,
- p->sa->totrct.ymax);
+ p->area->totrct.xmin,
+ p->area->totrct.ymin,
+ p->area->totrct.xmax,
+ p->area->totrct.ymax);
}
if (current_region) {
/* Assume that since we found the cursor in here, it is in bounds
* and that this should be the region that we begin drawing in
*/
- p->ar = current_region;
+ p->region = current_region;
in_bounds = true;
}
else {
@@ -2184,9 +2619,9 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
}
- else if (p->ar) {
+ else if (p->region) {
/* Perform bounds check. */
- const rcti *region_rect = ED_region_visible_rect(p->ar);
+ const rcti *region_rect = ED_region_visible_rect(p->region);
in_bounds = BLI_rcti_isect_pt_v(region_rect, event->mval);
}
else {
@@ -2246,7 +2681,8 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* TODO(sergey): Possibly evaluating dependency graph from modal operator? */
- annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
+ annotation_draw_apply_event(
+ C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
/* finish painting operation if anything went wrong just now */
if (p->status == GP_STATUS_ERROR) {
@@ -2261,19 +2697,19 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* eraser size */
else if ((p->paintmode == GP_PAINTMODE_ERASER) &&
- ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, PADPLUSKEY, PADMINUS)) {
+ ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, EVT_PADPLUSKEY, EVT_PADMINUS)) {
/* just resize the brush (local version)
* TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys
*/
/* printf("\t\tGP - resize eraser\n"); */
switch (event->type) {
case WHEELDOWNMOUSE: /* larger */
- case PADPLUSKEY:
+ case EVT_PADPLUSKEY:
p->radius += 5;
break;
case WHEELUPMOUSE: /* smaller */
- case PADMINUS:
+ case EVT_PADMINUS:
p->radius -= 5;
if (p->radius <= 0) {
@@ -2284,7 +2720,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* force refresh */
/* just active area for now, since doing whole screen is too slow */
- ED_region_tag_redraw(p->ar);
+ ED_region_tag_redraw(p->region);
/* event handled, so just tag as running modal */
estate = OPERATOR_RUNNING_MODAL;
@@ -2299,7 +2735,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
- if (0 == gpencil_area_exists(C, p->sa)) {
+ if (0 == gpencil_area_exists(C, p->area)) {
estate = OPERATOR_CANCELLED;
}
else {
@@ -2354,6 +2790,19 @@ static const EnumPropertyItem prop_gpencil_drawmodes[] = {
{0, NULL, 0, NULL, NULL},
};
+static const EnumPropertyItem arrow_types[] = {
+ {GP_STROKE_ARROWSTYLE_NONE, "NONE", 0, "None", "Don't use any arrow/style in corner"},
+ {GP_STROKE_ARROWSTYLE_CLOSED, "ARROW", 0, "Arrow", "Use closed arrow style"},
+ {GP_STROKE_ARROWSTYLE_OPEN, "ARROW_OPEN", 0, "Open Arrow", "Use open arrow style"},
+ {GP_STROKE_ARROWSTYLE_SEGMENT,
+ "ARROW_OPEN_INVERTED",
+ 0,
+ "Segment",
+ "Use perpendicular segment style"},
+ {GP_STROKE_ARROWSTYLE_SQUARE, "DIAMOND", 0, "Square", "Use square style"},
+ {0, NULL, 0, NULL, NULL},
+};
+
void GPENCIL_OT_annotate(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -2377,6 +2826,37 @@ void GPENCIL_OT_annotate(wmOperatorType *ot)
ot->prop = RNA_def_enum(
ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "arrowstyle_start", arrow_types, 0, "Start Arrow Style", "Stroke start style");
+ prop = RNA_def_enum(
+ ot->srna, "arrowstyle_end", arrow_types, 0, "End Arrow Style", "Stroke end style");
+ prop = RNA_def_boolean(ot->srna,
+ "use_stabilizer",
+ false,
+ "Stabilize Stroke",
+ "Helper to draw smooth and clean lines. Press Shift for an invert effect "
+ "(even if this option is not active)");
+ prop = RNA_def_float(ot->srna,
+ "stabilizer_factor",
+ 0.75f,
+ 0.0f,
+ 1.0f,
+ "Stabilizer Stroke Factor",
+ "Higher values gives a smoother stroke",
+ 0.0f,
+ 1.0f);
+ prop = RNA_def_int(ot->srna,
+ "stabilizer_radius",
+ 35,
+ 0,
+ 200,
+ "Stabilizer Stroke Radius",
+ "Minimun distance from last point before stroke continues",
+ 1,
+ 100);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+
prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 06e5f36637b..6d41e9bddbe 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -21,40 +21,40 @@
* \ingroup edgpencil
*/
+#include <float.h>
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
-#include <float.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_sys_types.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_polyfill_2d.h"
+#include "BLI_utildefines.h"
#include "BLF_api.h"
#include "BLT_translation.h"
#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "DNA_view3d_types.h"
#include "DNA_userdef_types.h"
-#include "DNA_object_types.h"
+#include "DNA_view3d_types.h"
-#include "BKE_context.h"
#include "BKE_brush.h"
+#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_material.h"
-#include "BKE_paint.h"
#include "BKE_gpencil.h"
#include "BKE_image.h"
+#include "BKE_material.h"
+#include "BKE_paint.h"
#include "DEG_depsgraph.h"
@@ -67,8 +67,8 @@
#include "ED_gpencil.h"
#include "ED_screen.h"
-#include "ED_view3d.h"
#include "ED_space_api.h"
+#include "ED_view3d.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
@@ -114,13 +114,6 @@ typedef enum eDrawStrokeFlags {
/* ----- Tool Buffer Drawing ------ */
/* helper functions to set color of buffer point */
-static void gp_set_point_uniform_color(const bGPDspoint *pt, const float ink[4])
-{
- float alpha = ink[3] * pt->strength;
- CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
- immUniformColor3fvAlpha(ink, alpha);
-}
-
static void gp_set_point_varying_color(const bGPDspoint *pt,
const float ink[4],
uint attr_id,
@@ -134,74 +127,8 @@ static void gp_set_point_varying_color(const bGPDspoint *pt,
immAttr4ub(attr_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha));
}
-/* --------- 2D Stroke Drawing Helpers --------- */
-/* change in parameter list */
-static void gp_calc_2d_stroke_fxy(
- const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
-{
- if (sflag & GP_STROKE_2DSPACE) {
- r_co[0] = pt[0];
- r_co[1] = pt[1];
- }
- else if (sflag & GP_STROKE_2DIMAGE) {
- const float x = (float)((pt[0] * winx) + offsx);
- const float y = (float)((pt[1] * winy) + offsy);
-
- r_co[0] = x;
- r_co[1] = y;
- }
- else {
- const float x = (float)(pt[0] / 100 * winx) + offsx;
- const float y = (float)(pt[1] / 100 * winy) + offsy;
-
- r_co[0] = x;
- r_co[1] = y;
- }
-}
/* ----------- Volumetric Strokes --------------- */
-/* draw a 2D strokes in "volumetric" style */
-static void gp_draw_stroke_volumetric_2d(const bGPDspoint *points,
- int totpoints,
- short thickness,
- short UNUSED(dflag),
- short sflag,
- int offsx,
- int offsy,
- int winx,
- int winy,
- const float diff_mat[4][4],
- const float ink[4])
-{
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint color = GPU_vertformat_attr_add(
- format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
- GPU_program_point_size(true);
- immBegin(GPU_PRIM_POINTS, totpoints);
-
- const bGPDspoint *pt = points;
- for (int i = 0; i < totpoints; i++, pt++) {
- /* transform position to 2D */
- float co[2];
- float fpt[3];
-
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
-
- gp_set_point_varying_color(pt, ink, color, false);
- immAttr1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
- immVertex2f(pos, co[0], co[1]);
- }
-
- immEnd();
- immUnbindProgram();
- GPU_program_point_size(false);
-}
-
/* draw a 3D stroke in "volumetric" style */
static void gp_draw_stroke_volumetric_3d(const bGPDspoint *points,
int totpoints,
@@ -232,313 +159,8 @@ static void gp_draw_stroke_volumetric_3d(const bGPDspoint *points,
GPU_program_point_size(false);
}
-/* --------------- Stroke Fills ----------------- */
-/* calc bounding box in 2d using flat projection data */
-static void gp_calc_2d_bounding_box(
- const float (*points2d)[2], int totpoints, float minv[2], float maxv[2], bool expand)
-{
- copy_v2_v2(minv, points2d[0]);
- copy_v2_v2(maxv, points2d[0]);
-
- for (int i = 1; i < totpoints; i++) {
- /* min */
- if (points2d[i][0] < minv[0]) {
- minv[0] = points2d[i][0];
- }
- if (points2d[i][1] < minv[1]) {
- minv[1] = points2d[i][1];
- }
- /* max */
- if (points2d[i][0] > maxv[0]) {
- maxv[0] = points2d[i][0];
- }
- if (points2d[i][1] > maxv[1]) {
- maxv[1] = points2d[i][1];
- }
- }
- /* If not expanded, use a perfect square */
- if (expand == false) {
- if (maxv[0] > maxv[1]) {
- maxv[1] = maxv[0];
- }
- else {
- maxv[0] = maxv[1];
- }
- }
-}
-
-/* calc texture coordinates using flat projected points */
-static void gp_calc_stroke_text_coordinates(const float (*points2d)[2],
- int totpoints,
- const float minv[2],
- float maxv[2],
- float (*r_uv)[2])
-{
- float d[2];
- d[0] = maxv[0] - minv[0];
- d[1] = maxv[1] - minv[1];
- for (int i = 0; i < totpoints; i++) {
- r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0];
- r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1];
- }
-}
-
-/* Triangulate stroke for high quality fill
- * (this is done only if cache is null or stroke was modified). */
-static void gp_triangulate_stroke_fill(bGPDstroke *gps)
-{
- BLI_assert(gps->totpoints >= 3);
-
- /* allocate memory for temporary areas */
- gps->tot_triangles = gps->totpoints - 2;
- uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles,
- "GP Stroke temp triangulation");
- float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints,
- "GP Stroke temp 2d points");
- float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
-
- int direction = 0;
-
- /* convert to 2d and triangulate */
- BKE_gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
- BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles);
-
- /* calc texture coordinates automatically */
- float minv[2];
- float maxv[2];
- /* first needs bounding box data */
- gp_calc_2d_bounding_box((const float(*)[2])points2d, gps->totpoints, minv, maxv, false);
- /* calc uv data */
- gp_calc_stroke_text_coordinates((const float(*)[2])points2d, gps->totpoints, minv, maxv, uv);
-
- /* Number of triangles */
- gps->tot_triangles = gps->totpoints - 2;
- /* save triangulation data in stroke cache */
- if (gps->tot_triangles > 0) {
- if (gps->triangles == NULL) {
- gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles,
- "GP Stroke triangulation");
- }
- else {
- gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
- }
-
- for (int i = 0; i < gps->tot_triangles; i++) {
- bGPDtriangle *stroke_triangle = &gps->triangles[i];
- memcpy(stroke_triangle->verts, tmp_triangles[i], sizeof(uint[3]));
- /* copy texture coordinates */
- copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
- copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
- copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
- }
- }
- else {
- /* No triangles needed - Free anything allocated previously */
- if (gps->triangles) {
- MEM_freeN(gps->triangles);
- }
-
- gps->triangles = NULL;
- }
-
- /* disable recalculation flag */
- if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
- gps->flag &= ~GP_STROKE_RECALC_GEOMETRY;
- }
-
- /* clear memory */
- MEM_SAFE_FREE(tmp_triangles);
- MEM_SAFE_FREE(points2d);
- MEM_SAFE_FREE(uv);
-}
-
-/* add a new fill point and texture coordinates to vertex buffer */
-static void gp_add_filldata_tobuffer(const bGPDspoint *pt,
- const float uv[2],
- uint pos,
- uint texcoord,
- short flag,
- int offsx,
- int offsy,
- int winx,
- int winy,
- const float diff_mat[4][4])
-{
- float fpt[3];
- float co[2];
-
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- /* if 2d, need conversion */
- if (!(flag & GP_STROKE_3DSPACE)) {
- gp_calc_2d_stroke_fxy(fpt, flag, offsx, offsy, winx, winy, co);
- copy_v2_v2(fpt, co);
- fpt[2] = 0.0f; /* 2d always is z=0.0f */
- }
-
- immAttr2f(texcoord, uv[0], uv[1]); /* texture coordinates */
- immVertex3fv(pos, fpt); /* position */
-}
-
-#if 0 /* GPXX disabled, not used in annotations */
-/* assign image texture for filling stroke */
-static int gp_set_filling_texture(Image *image, short flag)
-{
- ImBuf *ibuf;
- uint *bind = &image->bindcode[TEXTARGET_TEXTURE_2D];
- int error = GL_NO_ERROR;
- ImageUser iuser = {NULL};
- void *lock;
-
- iuser.ok = true;
-
- ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
-
- if (ibuf == NULL || ibuf->rect == NULL) {
- BKE_image_release_ibuf(image, ibuf, NULL);
- return (int)GL_INVALID_OPERATION;
- }
-
- GPU_create_gl_tex(
- bind, ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, GL_TEXTURE_2D, false, false, image);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- if (flag & GP_STYLE_COLOR_TEX_CLAMP) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- }
- else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- BKE_image_release_ibuf(image, ibuf, NULL);
-
- return error;
-}
-#endif
-
-/* draw fills for shapes */
-static void gp_draw_stroke_fill(bGPdata *gpd,
- bGPDstroke *gps,
- int offsx,
- int offsy,
- int winx,
- int winy,
- const float diff_mat[4][4],
- const float color[4])
-{
- BLI_assert(gps->totpoints >= 3);
- const bool use_mat = (gpd->mat != NULL);
-
- Material *ma = (use_mat) ? gpd->mat[gps->mat_nr] : BKE_material_gpencil_default_get();
- MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL;
-
- /* Calculate triangles cache for filling area (must be done only after changes) */
- if ((gps->flag & GP_STROKE_RECALC_GEOMETRY) || (gps->tot_triangles == 0) ||
- (gps->triangles == NULL)) {
- gp_triangulate_stroke_fill(gps);
- }
- BLI_assert(gps->tot_triangles >= 1);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_GPENCIL_FILL);
-
- immUniformColor4fv(color);
- immUniform4fv("color2", gp_style->mix_rgba);
- immUniform1i("fill_type", gp_style->fill_style);
- immUniform1f("mix_factor", gp_style->mix_factor);
-
- immUniform1f("gradient_angle", gp_style->gradient_angle);
- immUniform1f("gradient_radius", gp_style->gradient_radius);
- immUniform1f("pattern_gridsize", gp_style->pattern_gridsize);
- immUniform2fv("gradient_scale", gp_style->gradient_scale);
- immUniform2fv("gradient_shift", gp_style->gradient_shift);
-
- immUniform1f("texture_angle", gp_style->texture_angle);
- immUniform2fv("texture_scale", gp_style->texture_scale);
- immUniform2fv("texture_offset", gp_style->texture_offset);
- immUniform1f("texture_opacity", gp_style->texture_opacity);
- immUniform1i("t_mix", (gp_style->flag & GP_STYLE_FILL_TEX_MIX) != 0);
- immUniform1i("t_flip", (gp_style->flag & GP_STYLE_COLOR_FLIP_FILL) != 0);
-#if 0 /* GPXX disabled, not used in annotations */
- /* image texture */
- if ((gp_style->fill_style == GP_STYLE_FILL_STYLE_TEXTURE) ||
- (gp_style->flag & GP_STYLE_COLOR_TEX_MIX)) {
- gp_set_filling_texture(gp_style->ima, gp_style->flag);
- }
-#endif
- /* Draw all triangles for filling the polygon (cache must be calculated before) */
- immBegin(GPU_PRIM_TRIS, gps->tot_triangles * 3);
- /* TODO: use batch instead of immediate mode, to share vertices */
-
- const bGPDtriangle *stroke_triangle = gps->triangles;
- for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
- for (int j = 0; j < 3; j++) {
- gp_add_filldata_tobuffer(&gps->points[stroke_triangle->verts[j]],
- stroke_triangle->uv[j],
- pos,
- texcoord,
- gps->flag,
- offsx,
- offsy,
- winx,
- winy,
- diff_mat);
- }
- }
-
- immEnd();
- immUnbindProgram();
-}
-
/* ----- Existing Strokes Drawing (3D and Point) ------ */
-/* draw a given stroke - just a single dot (only one point) */
-static void gp_draw_stroke_point(const bGPDspoint *points,
- short thickness,
- short UNUSED(dflag),
- short sflag,
- int offsx,
- int offsy,
- int winx,
- int winy,
- const float diff_mat[4][4],
- const float ink[4])
-{
- const bGPDspoint *pt = points;
-
- /* get final position using parent matrix */
- float fpt[3];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- if (sflag & GP_STROKE_3DSPACE) {
- immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
- }
- else {
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
-
- /* get 2D coordinates of point */
- float co[3] = {0.0f};
- gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
- copy_v3_v3(fpt, co);
- }
-
- gp_set_point_uniform_color(pt, ink);
- /* set point thickness (since there's only one of these) */
- immUniform1f("size", (float)(thickness + 2) * pt->pressure);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, fpt);
- immEnd();
-
- immUnbindProgram();
-}
-
/* draw a given stroke in 3d (i.e. in 3d-space) */
static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4], bool cyclic)
{
@@ -631,200 +253,6 @@ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4
immUnbindProgram();
}
-/* ----- Fancy 2D-Stroke Drawing ------ */
-
-/* draw a given stroke in 2d */
-static void gp_draw_stroke_2d(const bGPDspoint *points,
- int totpoints,
- short thickness_s,
- short dflag,
- short sflag,
- bool UNUSED(debug),
- int offsx,
- int offsy,
- int winx,
- int winy,
- const float diff_mat[4][4],
- const float ink[4])
-{
- /* otherwise thickness is twice that of the 3D view */
- float thickness = (float)thickness_s * 0.5f;
-
- /* strokes in Image Editor need a scale factor, since units there are not pixels! */
- float scalefac = 1.0f;
- if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
- scalefac = 0.001f;
- }
-
- /* TODO: fancy++ with the magic of shaders */
-
- /* tessellation code - draw stroke as series of connected quads (triangle strips in fact)
- * with connection edges rotated to minimize shrinking artifacts, and rounded endcaps.
- */
- {
- const bGPDspoint *pt1, *pt2;
- float s0[2], s1[2]; /* segment 'center' points */
- float pm[2]; /* normal from previous segment. */
- int i;
- float fpt[3];
-
- GPUVertFormat *format = immVertexFormat();
- const struct {
- uint pos, color;
- } attr_id = {
- .pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT),
- .color = GPU_vertformat_attr_add(
- format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT),
- };
-
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GPU_PRIM_TRI_STRIP, totpoints * 2 + 4);
-
- /* get x and y coordinates from first point */
- mul_v3_m4v3(fpt, diff_mat, &points->x);
- gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s0);
-
- for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) {
- float t0[2], t1[2]; /* tessellated coordinates */
- float m1[2], m2[2]; /* gradient and normal */
- float mt[2], sc[2]; /* gradient for thickness, point for end-cap */
- float pthick; /* thickness at segment point */
-
- /* Get x and y coordinates from point2
- * (point1 has already been computed in previous iteration). */
- mul_v3_m4v3(fpt, diff_mat, &pt2->x);
- gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s1);
-
- /* calculate gradient and normal - 'angle'=(ny/nx) */
- m1[1] = s1[1] - s0[1];
- m1[0] = s1[0] - s0[0];
- normalize_v2(m1);
- m2[1] = -m1[0];
- m2[0] = m1[1];
-
- /* always use pressure from first point here */
- pthick = (pt1->pressure * thickness * scalefac);
-
- /* color of point */
- gp_set_point_varying_color(pt1, ink, attr_id.color, false);
-
- /* if the first segment, start of segment is segment's normal */
- if (i == 0) {
- /* draw start cap first
- * - make points slightly closer to center (about halfway across)
- */
- mt[0] = m2[0] * pthick * 0.5f;
- mt[1] = m2[1] * pthick * 0.5f;
- sc[0] = s0[0] - (m1[0] * pthick * 0.75f);
- sc[1] = s0[1] - (m1[1] * pthick * 0.75f);
-
- t0[0] = sc[0] - mt[0];
- t0[1] = sc[1] - mt[1];
- t1[0] = sc[0] + mt[0];
- t1[1] = sc[1] + mt[1];
-
- /* First two points of cap. */
- immVertex2fv(attr_id.pos, t0);
- immVertex2fv(attr_id.pos, t1);
-
- /* calculate points for start of segment */
- mt[0] = m2[0] * pthick;
- mt[1] = m2[1] * pthick;
-
- t0[0] = s0[0] - mt[0];
- t0[1] = s0[1] - mt[1];
- t1[0] = s0[0] + mt[0];
- t1[1] = s0[1] + mt[1];
-
- /* Last two points of start cap (and first two points of first segment). */
- immVertex2fv(attr_id.pos, t0);
- immVertex2fv(attr_id.pos, t1);
- }
- /* if not the first segment, use bisector of angle between segments */
- else {
- float mb[2]; /* bisector normal */
- float athick, dfac; /* actual thickness, difference between thicknesses */
-
- /* calculate gradient of bisector (as average of normals) */
- mb[0] = (pm[0] + m2[0]) / 2;
- mb[1] = (pm[1] + m2[1]) / 2;
- normalize_v2(mb);
-
- /* calculate gradient to apply
- * - as basis, use just pthick * bisector gradient
- * - if cross-section not as thick as it should be, add extra padding to fix it
- */
- mt[0] = mb[0] * pthick;
- mt[1] = mb[1] * pthick;
- athick = len_v2(mt);
- dfac = pthick - (athick * 2);
-
- if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) {
- mt[0] += (mb[0] * dfac);
- mt[1] += (mb[1] * dfac);
- }
-
- /* calculate points for start of segment */
- t0[0] = s0[0] - mt[0];
- t0[1] = s0[1] - mt[1];
- t1[0] = s0[0] + mt[0];
- t1[1] = s0[1] + mt[1];
-
- /* Last two points of previous segment, and first two points of current segment. */
- immVertex2fv(attr_id.pos, t0);
- immVertex2fv(attr_id.pos, t1);
- }
-
- /* if last segment, also draw end of segment (defined as segment's normal) */
- if (i == totpoints - 2) {
- /* for once, we use second point's pressure (otherwise it won't be drawn) */
- pthick = (pt2->pressure * thickness * scalefac);
-
- /* color of point */
- gp_set_point_varying_color(pt2, ink, attr_id.color, false);
-
- /* calculate points for end of segment */
- mt[0] = m2[0] * pthick;
- mt[1] = m2[1] * pthick;
-
- t0[0] = s1[0] - mt[0];
- t0[1] = s1[1] - mt[1];
- t1[0] = s1[0] + mt[0];
- t1[1] = s1[1] + mt[1];
-
- /* Last two points of last segment (and first two points of end cap). */
- immVertex2fv(attr_id.pos, t0);
- immVertex2fv(attr_id.pos, t1);
-
- /* draw end cap as last step
- * - make points slightly closer to center (about halfway across)
- */
- mt[0] = m2[0] * pthick * 0.5f;
- mt[1] = m2[1] * pthick * 0.5f;
- sc[0] = s1[0] + (m1[0] * pthick * 0.75f);
- sc[1] = s1[1] + (m1[1] * pthick * 0.75f);
-
- t0[0] = sc[0] - mt[0];
- t0[1] = sc[1] - mt[1];
- t1[0] = sc[0] + mt[0];
- t1[1] = sc[1] + mt[1];
-
- /* Last two points of end cap. */
- immVertex2fv(attr_id.pos, t0);
- immVertex2fv(attr_id.pos, t1);
- }
-
- /* store computed point2 coordinates as point1 ones of next segment. */
- copy_v2_v2(s0, s1);
- /* store stroke's 'natural' normal for next stroke to use */
- copy_v2_v2(pm, m2);
- }
-
- immEnd();
- immUnbindProgram();
- }
-}
-
/* ----- Strokes Drawing ------ */
/* Helper for doing all the checks on whether a stroke can be drawn */
@@ -868,7 +296,6 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
static void gp_draw_strokes(tGPDdraw *tgpw)
{
float tcolor[4];
- float tfill[4];
short sthickness;
float ink[4];
const bool is_unique = (tgpw->gps != NULL);
@@ -884,18 +311,18 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
continue;
}
/* check if the color is visible */
- Material *ma = (use_mat) ? tgpw->gpd->mat[gps->mat_nr] : BKE_material_gpencil_default_get();
+ Material *ma = (use_mat) ? tgpw->gpd->mat[gps->mat_nr] : BKE_material_default_gpencil();
MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL;
- if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
+ if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE) ||
/* if onion and ghost flag do not draw*/
- (tgpw->onion && (gp_style->flag & GP_STYLE_COLOR_ONIONSKIN))) {
+ (tgpw->onion && (gp_style->flag & GP_MATERIAL_ONIONSKIN))) {
continue;
}
/* 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) && (gp_style->flag & GP_STYLE_FILL_SHOW)) {
+ ((gps->flag & GP_STROKE_NOFILL) == 0) && (gp_style->flag & GP_MATERIAL_FILL_SHOW)) {
continue;
}
@@ -925,37 +352,6 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
bglPolygonOffset(1.0f, 1.0f);
}
- /* 3D Fill */
- // if ((dflag & GP_DRAWDATA_FILL) && (gps->totpoints >= 3)) {
- if ((gps->totpoints >= 3) && (tgpw->disable_fill != 1)) {
- /* set color using material, tint color and opacity */
- interp_v3_v3v3(tfill, gp_style->fill_rgba, tgpw->tintcolor, tgpw->tintcolor[3]);
- tfill[3] = gp_style->fill_rgba[3] * tgpw->opacity;
- if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) {
- const float *color;
- if (!tgpw->onion) {
- color = tfill;
- }
- else {
- if (tgpw->custonion) {
- color = tgpw->tintcolor;
- }
- else {
- ARRAY_SET_ITEMS(tfill, UNPACK3(gp_style->fill_rgba), tgpw->tintcolor[3]);
- color = tfill;
- }
- }
- gp_draw_stroke_fill(tgpw->gpd,
- gps,
- tgpw->offsx,
- tgpw->offsy,
- tgpw->winx,
- tgpw->winy,
- tgpw->diff_mat,
- color);
- }
- }
-
/* 3D Stroke */
/* set color using material tint color and opacity */
if (!tgpw->onion) {
@@ -980,7 +376,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
}
}
- if (gp_style->mode == GP_STYLE_MODE_DOTS) {
+ if (gp_style->mode == GP_MATERIAL_MODE_DOT) {
/* volumetric stroke drawing */
if (tgpw->disable_fill != 1) {
gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
@@ -988,21 +384,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
}
else {
/* 3D Lines - OpenGL primitives-based */
- if (gps->totpoints == 1) {
- if (tgpw->disable_fill != 1) {
- gp_draw_stroke_point(gps->points,
- sthickness,
- tgpw->dflag,
- gps->flag,
- tgpw->offsx,
- tgpw->offsy,
- tgpw->winx,
- tgpw->winy,
- tgpw->diff_mat,
- ink);
- }
- }
- else {
+ if (gps->totpoints > 1) {
tgpw->gps = gps;
gp_draw_stroke_3d(tgpw, sthickness, ink, gps->flag & GP_STROKE_CYCLIC);
}
@@ -1014,97 +396,6 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
bglPolygonOffset(0.0, 0.0);
}
}
- else {
- /* 2D - Fill */
- if (gps->totpoints >= 3) {
- /* set color using material, tint color and opacity */
- interp_v3_v3v3(tfill, gp_style->fill_rgba, tgpw->tintcolor, tgpw->tintcolor[3]);
- tfill[3] = gp_style->fill_rgba[3] * tgpw->opacity;
- if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) {
- const float *color;
- if (!tgpw->onion) {
- color = tfill;
- }
- else {
- if (tgpw->custonion) {
- color = tgpw->tintcolor;
- }
- else {
- ARRAY_SET_ITEMS(tfill, UNPACK3(gp_style->fill_rgba), tgpw->tintcolor[3]);
- color = tfill;
- }
- }
- gp_draw_stroke_fill(tgpw->gpd,
- gps,
- tgpw->offsx,
- tgpw->offsy,
- tgpw->winx,
- tgpw->winy,
- tgpw->diff_mat,
- color);
- }
- }
-
- /* 2D Strokes... */
- /* set color using material, tint color and opacity */
- if (!tgpw->onion) {
- interp_v3_v3v3(tcolor, gp_style->stroke_rgba, tgpw->tintcolor, tgpw->tintcolor[3]);
- tcolor[3] = gp_style->stroke_rgba[3] * tgpw->opacity;
- copy_v4_v4(ink, tcolor);
- }
- else {
- if (tgpw->custonion) {
- copy_v4_v4(ink, tgpw->tintcolor);
- }
- else {
- ARRAY_SET_ITEMS(tcolor, UNPACK3(gp_style->stroke_rgba), tgpw->opacity);
- copy_v4_v4(ink, tcolor);
- }
- }
- if (gp_style->mode == GP_STYLE_MODE_DOTS) {
- /* blob/disk-based "volumetric" drawing */
- gp_draw_stroke_volumetric_2d(gps->points,
- gps->totpoints,
- sthickness,
- tgpw->dflag,
- gps->flag,
- tgpw->offsx,
- tgpw->offsy,
- tgpw->winx,
- tgpw->winy,
- tgpw->diff_mat,
- ink);
- }
- else {
- /* normal 2D strokes */
- if (gps->totpoints == 1) {
- gp_draw_stroke_point(gps->points,
- sthickness,
- tgpw->dflag,
- gps->flag,
- tgpw->offsx,
- tgpw->offsy,
- tgpw->winx,
- tgpw->winy,
- tgpw->diff_mat,
- ink);
- }
- else {
- gp_draw_stroke_2d(gps->points,
- gps->totpoints,
- sthickness,
- tgpw->dflag,
- gps->flag,
- false,
- tgpw->offsx,
- tgpw->offsy,
- tgpw->winx,
- tgpw->winy,
- tgpw->diff_mat,
- ink);
- }
- }
- }
/* if only one stroke, exit from loop */
if (is_unique) {
break;
@@ -1116,113 +407,8 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
/* ----- General Drawing ------ */
-/* draw interpolate strokes (used only while operator is running) */
-void ED_gp_draw_interpolation(const bContext *C, tGPDinterpolate *tgpi, const int type)
-{
- tGPDdraw tgpw;
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
- tGPDinterpolate_layer *tgpil;
- Object *obact = CTX_data_active_object(C);
- /* Drawing code is expected to run with fully evaluated depsgraph. */
- Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
-
- float color[4];
-
- UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, color);
- color[3] = 0.6f;
- int dflag = 0;
- /* if 3d stuff, enable flags */
- if (type == REGION_DRAW_POST_VIEW) {
- dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
- }
-
- tgpw.rv3d = rv3d;
- tgpw.depsgraph = depsgraph;
- tgpw.ob = obact;
- tgpw.gpd = tgpi->gpd;
- tgpw.offsx = 0;
- tgpw.offsy = 0;
- tgpw.winx = tgpi->ar->winx;
- tgpw.winy = tgpi->ar->winy;
- tgpw.dflag = dflag;
-
- /* turn on alpha-blending */
- GPU_blend(true);
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- /* calculate parent position */
- ED_gpencil_parent_location(depsgraph, obact, tgpi->gpd, tgpil->gpl, tgpw.diff_mat);
- if (tgpil->interFrame) {
- tgpw.gpl = tgpil->gpl;
- tgpw.gpf = tgpil->interFrame;
- tgpw.t_gpf = tgpil->interFrame;
- tgpw.gps = NULL;
-
- tgpw.lthick = tgpil->gpl->line_change;
- tgpw.opacity = 1.0;
- copy_v4_v4(tgpw.tintcolor, color);
- tgpw.onion = true;
- tgpw.custonion = true;
- if (obact->totcol == 0) {
- tgpw.gpd->mat = NULL;
- }
-
- gp_draw_strokes(&tgpw);
- }
- }
- GPU_blend(false);
-}
-
/* wrapper to draw strokes for filling operator */
void ED_gp_draw_fill(tGPDdraw *tgpw)
{
gp_draw_strokes(tgpw);
}
-
-/* draw a short status message in the top-right corner */
-static void UNUSED_FUNCTION(gp_draw_status_text)(const bGPdata *gpd, ARegion *ar)
-{
-
- /* Cannot draw any status text when drawing OpenGL Renders */
- if (G.f & G_FLAG_RENDER_VIEWPORT) {
- return;
- }
-
- /* Get bounds of region - Necessary to avoid problems with region overlap. */
- const rcti *rect = ED_region_visible_rect(ar);
-
- /* for now, this should only be used to indicate when we are in stroke editmode */
- if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
- const char *printable = IFACE_("GPencil Stroke Editing");
- float printable_size[2];
-
- int font_id = BLF_default();
-
- BLF_width_and_height(
- font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
-
- int xco = (rect->xmax - U.widget_unit) - (int)printable_size[0];
- int yco = (rect->ymax - U.widget_unit);
-
- /* text label */
- UI_FontThemeColor(font_id, TH_TEXT_HI);
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
-#else
- BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
-#endif
-
- /* grease pencil icon... */
- // XXX: is this too intrusive?
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- xco -= U.widget_unit;
- yco -= (int)printable_size[1] / 2;
-
- UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
-
- GPU_blend(false);
- }
-}
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index f4636e81966..d2b1eba7d86 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -21,11 +21,11 @@
* \ingroup edgpencil
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -58,15 +58,13 @@
/* Loops over the gp-frames for a gp-layer, and applies the given callback */
bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *))
{
- bGPDframe *gpf;
-
/* error checker */
if (gpl == NULL) {
return false;
}
/* do loop */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* execute callback */
if (gpf_cb(gpf, scene)) {
return true;
@@ -83,7 +81,6 @@ bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPD
/* make a listing all the gp-frames in a layer as cfraelems */
void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel)
{
- bGPDframe *gpf;
CfraElem *ce;
/* error checking */
@@ -92,7 +89,7 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel)
}
/* loop through gp-frames, adding */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) {
ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
@@ -110,15 +107,13 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel)
/* check if one of the frames in this layer is selected */
bool ED_gplayer_frame_select_check(bGPDlayer *gpl)
{
- bGPDframe *gpf;
-
/* error checking */
if (gpl == NULL) {
return false;
}
/* stop at the first one found */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->flag & GP_FRAME_SELECT) {
return true;
}
@@ -151,15 +146,13 @@ static void gpframe_select(bGPDframe *gpf, short select_mode)
/* set all/none/invert select (like above, but with SELECT_* modes) */
void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
{
- bGPDframe *gpf;
-
/* error checking */
if (gpl == NULL) {
return;
}
/* handle according to mode */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
gpframe_select(gpf, select_mode);
}
}
@@ -185,7 +178,7 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
return;
}
- gpf = BKE_gpencil_layer_find_frame(gpl, selx);
+ gpf = BKE_gpencil_layer_frame_find(gpl, selx);
if (gpf) {
gpframe_select(gpf, select_mode);
@@ -195,14 +188,12 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
/* select the frames in this layer that occur within the bounds specified */
void ED_gplayer_frames_select_box(bGPDlayer *gpl, float min, float max, short select_mode)
{
- bGPDframe *gpf;
-
if (gpl == NULL) {
return;
}
/* only select those frames which are in bounds */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (IN_RANGE(gpf->framenum, min, max)) {
gpframe_select(gpf, select_mode);
}
@@ -215,14 +206,12 @@ void ED_gplayer_frames_select_region(KeyframeEditData *ked,
short tool,
short select_mode)
{
- bGPDframe *gpf;
-
if (gpl == NULL) {
return;
}
/* only select frames which are within the region */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* construct a dummy point coordinate to do this testing with */
float pt[2] = {0};
@@ -251,7 +240,6 @@ void ED_gplayer_frames_select_region(KeyframeEditData *ked,
/* Delete selected frames */
bool ED_gplayer_frames_delete(bGPDlayer *gpl)
{
- bGPDframe *gpf, *gpfn;
bool changed = false;
/* error checking */
@@ -260,11 +248,9 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
}
/* check for frames to delete */
- for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
- gpfn = gpf->next;
-
+ LISTBASE_FOREACH_MUTABLE (bGPDframe *, gpf, &gpl->frames) {
if (gpf->flag & GP_FRAME_SELECT) {
- BKE_gpencil_layer_delframe(gpl, gpf);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
changed = true;
}
}
@@ -275,16 +261,13 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
/* Duplicate selected frames from given gp-layer */
void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
{
- bGPDframe *gpf, *gpfn;
-
/* error checking */
if (gpl == NULL) {
return;
}
/* duplicate selected frames */
- for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
- gpfn = gpf->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDframe *, gpf, &gpl->frames) {
/* duplicate this frame */
if (gpf->flag & GP_FRAME_SELECT) {
@@ -304,13 +287,11 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
*/
void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
{
- bGPDframe *gpf;
-
if (gpl == NULL) {
return;
}
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->flag & GP_FRAME_SELECT) {
gpf->key_type = type;
}
@@ -370,10 +351,9 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
for (ale = anim_data.first; ale; ale = ale->next) {
ListBase copied_frames = {NULL, NULL};
bGPDlayer *gpl = (bGPDlayer *)ale->data;
- bGPDframe *gpf;
/* loop over frames, and copy only selected frames */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* if frame is selected, make duplicate it and its strokes */
if (gpf->flag & GP_FRAME_SELECT) {
/* make a copy of this frame */
@@ -489,7 +469,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
gpfs->framenum += offset;
/* get frame to copy data into (if no frame returned, then just ignore) */
- gpf = BKE_gpencil_layer_getframe(gpld, gpfs->framenum, GP_GETFRAME_ADD_NEW);
+ gpf = BKE_gpencil_layer_frame_get(gpld, gpfs->framenum, GP_GETFRAME_ADD_NEW);
if (gpf) {
bGPDstroke *gps, *gpsn;
@@ -502,21 +482,15 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
*/
for (gps = gpfs->strokes.first; gps; gps = gps->next) {
/* make a copy of stroke, then of its points array */
- gpsn = MEM_dupallocN(gps);
- gpsn->points = MEM_dupallocN(gps->points);
- if (gps->dvert != NULL) {
- gpsn->dvert = MEM_dupallocN(gps->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps, gpsn);
- }
- /* duplicate triangle information */
- gpsn->triangles = MEM_dupallocN(gps->triangles);
+ gpsn = BKE_gpencil_stroke_duplicate(gps, true);
+
/* append stroke to frame */
BLI_addtail(&gpf->strokes, gpsn);
}
/* if no strokes (i.e. new frame) added, free gpf */
if (BLI_listbase_is_empty(&gpf->strokes)) {
- BKE_gpencil_layer_delframe(gpld, gpf);
+ BKE_gpencil_layer_frame_delete(gpld, gpf);
}
}
@@ -638,13 +612,13 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene)
/* In order for this mirror function to work without
* any extra arguments being added, we use the case
- * of bezt==NULL to denote that we should find the
+ * of gpf==NULL to denote that we should find the
* marker to mirror over. The static pointer is safe
* to use this way, as it will be set to null after
* each cycle in which this is called.
*/
- if (gpf) {
+ if (gpf != NULL) {
/* mirroring time */
if ((gpf->flag & GP_FRAME_SELECT) && (marker)) {
diff = (marker->frame - gpf->framenum);
@@ -685,9 +659,9 @@ void ED_gplayer_mirror_frames(bGPDlayer *gpl, Scene *scene, short mode)
ED_gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis);
break;
case MIRROR_KEYS_MARKER: /* mirror over marker */
- mirror_gpf_marker(NULL, NULL);
+ mirror_gpf_marker(NULL, scene);
ED_gplayer_frames_looper(gpl, scene, mirror_gpf_marker);
- mirror_gpf_marker(NULL, NULL);
+ mirror_gpf_marker(NULL, scene);
break;
default: /* just in case */
ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
index 139697ad0e3..23ca5241866 100644
--- a/source/blender/editors/gpencil/gpencil_add_monkey.c
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -31,7 +31,8 @@
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
-#include "BKE_library.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -51,10 +52,10 @@ typedef struct ColorTemplate {
static int gpencil_monkey_color(
Main *bmain, Object *ob, const ColorTemplate *pct, bool stroke, bool fill)
{
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
Material *ma = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
if (STREQ(ma->id.name, pct->name)) {
return i;
}
@@ -66,17 +67,20 @@ static int gpencil_monkey_color(
ma = BKE_gpencil_object_material_new(bmain, ob, pct->name, &idx);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
+ srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
+
copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
+ srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
if (!stroke) {
- ma->gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
+ ma->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
}
if (!fill) {
- ma->gp_style->flag &= ~GP_STYLE_FILL_SHOW;
+ ma->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
}
else {
- ma->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
return idx;
@@ -855,89 +859,117 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4])
bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, CFRA);
/* generate strokes */
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin, 270, 75);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin, 270, 75, false);
BKE_gpencil_stroke_add_points(gps, data0, 270, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data1, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 60, false);
BKE_gpencil_stroke_add_points(gps, data2, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 64, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
BKE_gpencil_stroke_add_points(gps, data3, 64, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data4, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 64, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
BKE_gpencil_stroke_add_points(gps, data5, 64, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data6, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data7, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Eyes, 49, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
BKE_gpencil_stroke_add_points(gps, data8, 49, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data9, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Eyes, 49, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
BKE_gpencil_stroke_add_points(gps, data10, 49, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data11, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data12, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data13, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data14, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 65, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 65, 60, false);
BKE_gpencil_stroke_add_points(gps, data15, 65, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 34, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 60, false);
BKE_gpencil_stroke_add_points(gps, data16, 34, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data17, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 40);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 40, false);
BKE_gpencil_stroke_add_points(gps, data18, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 34, 40);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 40, false);
BKE_gpencil_stroke_add_points(gps, data19, 34, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data20, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 64, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 64, 60, false);
BKE_gpencil_stroke_add_points(gps, data21, 64, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 26, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
BKE_gpencil_stroke_add_points(gps, data22, 26, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 26, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
BKE_gpencil_stroke_add_points(gps, data23, 26, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data24, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data25, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data26, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data27, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
index 74617599eaa..60a4404beaf 100644
--- a/source/blender/editors/gpencil/gpencil_add_stroke.c
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -31,7 +31,8 @@
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
-#include "BKE_library.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -50,10 +51,10 @@ typedef struct ColorTemplate {
/* Add color an ensure duplications (matched by name) */
static int gp_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct, const bool fill)
{
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
Material *ma = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
if (STREQ(ma->id.name, pct->name)) {
return i;
}
@@ -65,10 +66,13 @@ static int gp_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct,
ma = BKE_gpencil_object_material_new(bmain, ob, pct->name, &idx);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
+ srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
+
copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
+ srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
if (fill) {
- ma->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
return idx;
@@ -240,8 +244,9 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4])
UNUSED_VARS(frame_color);
/* generate stroke */
- gps = BKE_gpencil_add_stroke(frame_lines, color_black, 175, 75);
+ gps = BKE_gpencil_stroke_add(frame_lines, color_black, 175, 75, false);
BKE_gpencil_stroke_add_points(gps, data0, 175, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c
index 9e70be323eb..962a74d9e6f 100644
--- a/source/blender/editors/gpencil/gpencil_armature.c
+++ b/source/blender/editors/gpencil/gpencil_armature.c
@@ -23,17 +23,17 @@
* Operators for dealing with armatures and GP data-blocks.
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -42,13 +42,13 @@
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
-#include "BKE_main.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
+#include "BKE_main.h"
#include "BKE_object_deform.h"
#include "BKE_report.h"
@@ -60,8 +60,8 @@
#include "RNA_enum_types.h"
#include "ED_gpencil.h"
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -168,7 +168,7 @@ static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
* If such a vertex group already exist the routine exits.
*/
if (!(bone->flag & BONE_NO_DEFORM)) {
- if (!defgroup_find_name(ob, bone->name)) {
+ if (!BKE_object_defgroup_find_name(ob, bone->name)) {
BKE_object_defgroup_add_name(ob, bone->name);
return 1;
}
@@ -221,7 +221,7 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
}
if (arm->layer & bone->layer) {
- if (!(defgroup = defgroup_find_name(ob, bone->name))) {
+ if (!(defgroup = BKE_object_defgroup_find_name(ob, bone->name))) {
defgroup = BKE_object_defgroup_add_name(ob, bone->name);
}
else if (defgroup->flag & DG_LOCK_WEIGHT) {
@@ -357,7 +357,7 @@ static void gpencil_add_verts_to_dgroups(
}
/* loop all strokes */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
bGPDspoint *pt = NULL;
@@ -368,7 +368,7 @@ static void gpencil_add_verts_to_dgroups(
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -418,7 +418,7 @@ static void gpencil_add_verts_to_dgroups(
}
/* assign weight */
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr);
if (dw) {
dw->weight = weight;
}
@@ -481,8 +481,7 @@ static void gpencil_object_vgroup_calc_from_armature(const bContext *C,
DEG_relations_tag_update(CTX_data_main(C));
}
-bool ED_gpencil_add_armature_weights(
- const bContext *C, ReportList *reports, Object *ob, Object *ob_arm, int mode)
+bool ED_gpencil_add_armature(const bContext *C, ReportList *reports, Object *ob, Object *ob_arm)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -492,7 +491,7 @@ bool ED_gpencil_add_armature_weights(
}
/* if no armature modifier, add a new one */
- GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob, eGpencilModifierType_Armature);
+ GpencilModifierData *md = BKE_gpencil_modifiers_findby_type(ob, eGpencilModifierType_Armature);
if (md == NULL) {
md = ED_object_gpencil_modifier_add(
reports, bmain, scene, ob, "Armature", eGpencilModifierType_Armature);
@@ -516,11 +515,24 @@ bool ED_gpencil_add_armature_weights(
return false;
}
}
+ return true;
+}
+
+bool ED_gpencil_add_armature_weights(
+ const bContext *C, ReportList *reports, Object *ob, Object *ob_arm, int mode)
+{
+ if (ob == NULL) {
+ return false;
+ }
+
+ bool success = ED_gpencil_add_armature(C, reports, ob, ob_arm);
/* add weights */
- gpencil_object_vgroup_calc_from_armature(C, ob, ob_arm, mode, DEFAULT_RATIO, DEFAULT_DECAY);
+ if (success) {
+ gpencil_object_vgroup_calc_from_armature(C, ob, ob_arm, mode, DEFAULT_RATIO, DEFAULT_DECAY);
+ }
- return true;
+ return success;
}
/* ***************** Generate armature weights ************************** */
static bool gpencil_generate_weights_poll(bContext *C)
@@ -543,7 +555,7 @@ static bool gpencil_generate_weights_poll(bContext *C)
}
/* need some armature in the view layer */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->object->type == OB_ARMATURE) {
return true;
}
@@ -578,8 +590,8 @@ static int gpencil_generate_weights_exec(bContext *C, wmOperator *op)
}
else {
/* get armature from modifier */
- GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob_eval,
- eGpencilModifierType_Armature);
+ GpencilModifierData *md = BKE_gpencil_modifiers_findby_type(ob_eval,
+ eGpencilModifierType_Armature);
if (md == NULL) {
BKE_report(op->reports, RPT_ERROR, "The grease pencil object need an Armature modifier");
return OPERATOR_CANCELLED;
@@ -630,7 +642,7 @@ static const EnumPropertyItem *gpencil_armatures_enum_itemf(bContext *C,
RNA_enum_item_add(&item, &totitem, &item_tmp);
i++;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
if (ob->type == OB_ARMATURE) {
item_tmp.identifier = item_tmp.name = ob->id.name + 2;
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 1ce4ffbbd46..5441d4e24a6 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -22,16 +22,16 @@
* \ingroup edgpencil
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
@@ -40,13 +40,13 @@
#include "DNA_anim_types.h"
#include "DNA_collection_types.h"
#include "DNA_curve_types.h"
-#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_node_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_gpencil_types.h"
#include "BKE_collection.h"
#include "BKE_context.h"
@@ -75,11 +75,11 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "ED_gpencil.h"
-#include "ED_view3d.h"
#include "ED_clip.h"
+#include "ED_gpencil.h"
#include "ED_keyframing.h"
#include "ED_object.h"
+#include "ED_view3d.h"
#include "gpencil_intern.h"
@@ -152,7 +152,6 @@ static const EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C),
* - assumes that the active space is the 3D-View
*/
static void gp_strokepoint_convertcoords(bContext *C,
- bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
bGPDspoint *source_pt,
@@ -161,9 +160,9 @@ static void gp_strokepoint_convertcoords(bContext *C,
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* TODO(sergey): This function might be called from a loop, but no tagging is happening in it,
- * so it's not that expensive to ensure evaluated depsgraph here. However, ideally all the
+ * so it's not that expensive to ensure evaluated depsgraph here. However, ideally all the
* parameters are to wrapped into a context style struct and queried from Context once.*/
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *obact = CTX_data_active_object(C);
@@ -174,7 +173,7 @@ static void gp_strokepoint_convertcoords(bContext *C,
/* apply parent transform */
float fpt[3];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
mul_v3_m4v3(fpt, diff_mat, &source_pt->x);
copy_v3_v3(&pt->x, fpt);
@@ -188,7 +187,7 @@ static void gp_strokepoint_convertcoords(bContext *C,
/* get screen coordinate */
if (gps->flag & GP_STROKE_2DSPACE) {
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
UI_view2d_view_to_region_fl(v2d, pt->x, pt->y, &mvalf[0], &mvalf[1]);
}
else {
@@ -197,12 +196,12 @@ static void gp_strokepoint_convertcoords(bContext *C,
mvalf[1] = (((float)pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
}
else {
- mvalf[0] = (float)pt->x / 100.0f * ar->winx;
- mvalf[1] = (float)pt->y / 100.0f * ar->winy;
+ mvalf[0] = (float)pt->x / 100.0f * region->winx;
+ mvalf[1] = (float)pt->y / 100.0f * region->winy;
}
}
- ED_view3d_win_to_3d(v3d, ar, fp, mvalf, p3d);
+ ED_view3d_win_to_3d(v3d, region, fp, mvalf, p3d);
}
}
@@ -513,8 +512,8 @@ static void gp_stroke_path_animation(bContext *C,
prop = RNA_struct_find_property(&ptr, "eval_time");
/* Ensure we have an F-Curve to add keyframes to */
- act = verify_adt_action(bmain, (ID *)cu, true);
- fcu = verify_fcurve(bmain, act, NULL, &ptr, "eval_time", 0, true);
+ act = ED_id_action_ensure(bmain, (ID *)cu);
+ fcu = ED_action_fcurve_ensure(bmain, act, NULL, &ptr, "eval_time", 0);
if (G.debug & G_DEBUG) {
printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
@@ -633,7 +632,6 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd,
}
static void gp_stroke_to_path(bContext *C,
- bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
Curve *cu,
@@ -708,7 +706,7 @@ static void gp_stroke_to_path(bContext *C,
bp = &nu->bp[old_nbp - 1];
/* First point */
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect);
+ gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect);
if (prev_bp) {
interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC);
if (do_gtd) {
@@ -737,7 +735,7 @@ static void gp_stroke_to_path(bContext *C,
/* Second point */
/* Note dt2 is always negative, which marks the gap. */
if (gps->totpoints > 1) {
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points + 1, next_p, subrect);
+ gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect);
interp_v3_v3v3(p2, p, next_p, -GAP_DFAC);
if (do_gtd) {
dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
@@ -759,9 +757,9 @@ static void gp_stroke_to_path(bContext *C,
float p[3], next_p[3];
float dt = 0.0f;
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect);
+ gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect);
if (gps->totpoints > 1) {
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points + 1, next_p, subrect);
+ gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect);
interp_v3_v3v3(p, p, next_p, -GAP_DFAC);
if (do_gtd) {
dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC);
@@ -794,7 +792,7 @@ static void gp_stroke_to_path(bContext *C,
float width = pt->pressure * (gps->thickness + gpl->line_change) * WIDTH_CORR_FAC;
/* get coordinates to add at */
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt, p, subrect);
+ gp_strokepoint_convertcoords(C, gpl, gps, pt, p, subrect);
gp_stroke_to_path_add_point(gtd,
bp,
@@ -882,7 +880,6 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd,
}
static void gp_stroke_to_bezier(bContext *C,
- bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
Curve *cu,
@@ -934,13 +931,12 @@ static void gp_stroke_to_bezier(bContext *C,
/* get initial coordinates */
pt = gps->points;
if (tot) {
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect);
+ gp_strokepoint_convertcoords(C, gpl, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect);
if (tot > 1) {
- gp_strokepoint_convertcoords(
- C, gpd, gpl, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect);
+ gp_strokepoint_convertcoords(C, gpl, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect);
}
if (stitch && tot > 2) {
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect);
+ gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect);
}
}
@@ -1106,7 +1102,7 @@ static void gp_stroke_to_bezier(bContext *C,
copy_v3_v3(p3d_cur, p3d_next);
if (i + 2 < tot) {
- gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect);
+ gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect);
}
prev_bezt = bezt;
@@ -1236,16 +1232,16 @@ static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2
static int gp_camera_view_subrect(bContext *C, rctf *subrect)
{
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
if (v3d) {
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
/* for camera view set the subrect */
if (rv3d->persp == RV3D_CAMOB) {
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, subrect, true);
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, subrect, true);
return 1;
}
}
@@ -1270,7 +1266,7 @@ static void gp_layer_to_curve(bContext *C,
Collection *collection = CTX_data_collection(C);
Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
bGPDstroke *gps, *prev_gps = NULL;
Object *ob;
Curve *cu;
@@ -1334,7 +1330,6 @@ static void gp_layer_to_curve(bContext *C,
switch (mode) {
case GP_STROKECONVERT_PATH:
gp_stroke_to_path(C,
- gpd,
gpl,
gps,
cu,
@@ -1350,7 +1345,6 @@ static void gp_layer_to_curve(bContext *C,
case GP_STROKECONVERT_CURVE:
case GP_STROKECONVERT_POLY: /* convert after */
gp_stroke_to_bezier(C,
- gpd,
gpl,
gps,
cu,
@@ -1385,7 +1379,7 @@ static void gp_layer_to_curve(bContext *C,
if (mode == GP_STROKECONVERT_POLY) {
for (nu = cu->nurb.first; nu; nu = nu->next) {
- BKE_nurb_type_convert(nu, CU_POLY, false);
+ BKE_nurb_type_convert(nu, CU_POLY, false, NULL);
}
}
@@ -1410,7 +1404,7 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe
int i;
bool valid = true;
- if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV)) ||
+ if (!gpl || !(gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV)) ||
!(gps = gpf->strokes.first)) {
return false;
}
@@ -1471,13 +1465,13 @@ static bool gp_convert_poll(bContext *C)
bGPdata *gpd = (bGPdata *)ob->data;
bGPDlayer *gpl = NULL;
bGPDframe *gpf = NULL;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!),
* and if we are not in edit mode!
*/
- return ((sa && sa->spacetype == SPACE_VIEW3D) && (gpl = BKE_gpencil_layer_getactive(gpd)) &&
- (gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV)) &&
+ return ((area && area->spacetype == SPACE_VIEW3D) && (gpl = BKE_gpencil_layer_active_get(gpd)) &&
+ (gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV)) &&
(gpf->strokes.first) && (!GPENCIL_ANY_EDIT_MODE(gpd)));
}
@@ -1487,7 +1481,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
Scene *scene = CTX_data_scene(C);
const int mode = RNA_enum_get(op->ptr, "type");
const bool norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights");
@@ -1751,4 +1745,92 @@ void GPENCIL_OT_convert(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ************************************************ */
+/* Generate Grease Pencil from Image. */
+static bool image_to_gpencil_poll(bContext *C)
+{
+ SpaceLink *sl = CTX_wm_space_data(C);
+ if ((sl != NULL) && (sl->spacetype == SPACE_IMAGE)) {
+ return true;
+ }
+
+ return false;
+}
+
+static int image_to_gpencil_exec(bContext *C, wmOperator *op)
+{
+ const float size = RNA_float_get(op->ptr, "size");
+ const bool is_mask = RNA_boolean_get(op->ptr, "mask");
+
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ bool done = false;
+
+ if (sima->image == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Create Object. */
+ const float *cur = scene->cursor.location;
+ ushort local_view_bits = 0;
+ Object *ob = ED_gpencil_add_object(C, cur, local_view_bits);
+ DEG_relations_tag_update(bmain); /* added object */
+
+ /* Create material slot. */
+ Material *ma = BKE_gpencil_object_material_new(bmain, ob, "Image Material", NULL);
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ gp_style->mode = GP_MATERIAL_MODE_SQUARE;
+
+ /* Add layer and frame. */
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, "Image Layer", true);
+ bGPDframe *gpf = BKE_gpencil_frame_addnew(gpl, CFRA);
+ done = BKE_gpencil_from_image(sima, gpf, size, is_mask);
+
+ if (done) {
+ /* Delete any selected point. */
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
+ }
+
+ BKE_reportf(op->reports, RPT_INFO, "Object created");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_image_to_grease_pencil(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Generate Grease Pencil Object using image as source";
+ ot->idname = "GPENCIL_OT_image_to_grease_pencil";
+ ot->description = "Generate a Grease Pencil Object using Image as source";
+
+ /* api callbacks */
+ ot->exec = image_to_gpencil_exec;
+ ot->poll = image_to_gpencil_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_float(ot->srna,
+ "size",
+ 0.005f,
+ 0.0001f,
+ 10.0f,
+ "Point Size",
+ "Size used for grease pencil points",
+ 0.001f,
+ 1.0f);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna,
+ "mask",
+ false,
+ "Generate Mask",
+ "Create an inverted image for masking using alpha channel");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index fa23dd5e059..8c80334bf8a 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -23,19 +23,19 @@
* Operators for dealing with GP data-blocks and layers.
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_string_utils.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -50,14 +50,15 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
+#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_fcurve.h"
+#include "BKE_fcurve_driver.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
@@ -76,8 +77,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "ED_object.h"
#include "ED_gpencil.h"
+#include "ED_object.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -214,6 +215,7 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op)
PointerRNA gpd_owner = {NULL};
Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
bGPdata *gpd = NULL;
if (is_annotation) {
@@ -238,7 +240,11 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
if ((ob != NULL) && (ob->type == OB_GPENCIL)) {
gpd = (bGPdata *)ob->data;
- BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+ bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+ /* Add a new frame to make it visible in Dopesheet. */
+ if (gpl != NULL) {
+ gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ }
}
}
@@ -292,7 +298,7 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
/* sanity checks */
if (ELEM(NULL, gpd, gpl)) {
@@ -309,18 +315,22 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op)
* - if this is the only layer, this naturally becomes NULL
*/
if (gpl->prev) {
- BKE_gpencil_layer_setactive(gpd, gpl->prev);
+ BKE_gpencil_layer_active_set(gpd, gpl->prev);
}
else {
- BKE_gpencil_layer_setactive(gpd, gpl->next);
+ BKE_gpencil_layer_active_set(gpd, gpl->next);
}
/* delete the layer now... */
BKE_gpencil_layer_delete(gpd, gpl);
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort_all(gpd);
+
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -342,7 +352,7 @@ void GPENCIL_OT_layer_remove(wmOperatorType *ot)
static bool gp_active_layer_annotation_poll(bContext *C)
{
bGPdata *gpd = ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return (gpl != NULL);
}
@@ -373,7 +383,7 @@ static int gp_layer_move_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
const int direction = RNA_enum_get(op->ptr, "type") * -1;
@@ -384,6 +394,9 @@ static int gp_layer_move_exec(bContext *C, wmOperator *op)
BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) {
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort_all(gpd);
+
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
@@ -441,7 +454,7 @@ void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot)
static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
bGPDlayer *new_layer;
/* sanity checks */
@@ -460,11 +473,12 @@ static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
'.',
offsetof(bGPDlayer, info),
sizeof(new_layer->info));
- BKE_gpencil_layer_setactive(gpd, new_layer);
+ BKE_gpencil_layer_active_set(gpd, new_layer);
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -499,14 +513,14 @@ static bool gp_layer_duplicate_object_poll(bContext *C)
}
bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl == NULL) {
return false;
}
/* check there are more grease pencil objects */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if ((base->object != ob) && (base->object->type == OB_GPENCIL)) {
return true;
}
@@ -532,7 +546,7 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
Object *ob_src = CTX_data_active_object(C);
bGPdata *gpd_src = (bGPdata *)ob_src->data;
- bGPDlayer *gpl_src = BKE_gpencil_layer_getactive(gpd_src);
+ bGPDlayer *gpl_src = BKE_gpencil_layer_active_get(gpd_src);
/* Sanity checks. */
if (ELEM(NULL, gpd_src, gpl_src, ob_dst)) {
@@ -555,7 +569,7 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
gpl_dst->opacity = gpl_src->opacity;
/* Create all frames. */
- for (bGPDframe *gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
continue;
@@ -565,14 +579,14 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
bGPDframe *gpf_dst = BKE_gpencil_frame_addnew(gpl_dst, gpf_src->framenum);
/* Copy strokes. */
- for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
/* Make copy of source stroke. */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
/* Check if material is in destination object,
* otherwise add the slot with the material. */
- Material *ma_src = give_current_material(ob_src, gps_src->mat_nr + 1);
+ Material *ma_src = BKE_object_material_get(ob_src, gps_src->mat_nr + 1);
if (ma_src != NULL) {
int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
@@ -630,21 +644,21 @@ enum {
static int gp_frame_duplicate_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
Scene *scene = CTX_data_scene(C);
int mode = RNA_enum_get(op->ptr, "mode");
/* sanity checks */
- if (ELEM(NULL, gpd, gpl)) {
+ if (ELEM(NULL, gpd, gpl_active)) {
return OPERATOR_CANCELLED;
}
if (mode == 0) {
- BKE_gpencil_frame_addcopy(gpl, CFRA);
+ BKE_gpencil_frame_addcopy(gpl_active, CFRA);
}
else {
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
BKE_gpencil_frame_addcopy(gpl, CFRA);
}
@@ -700,16 +714,13 @@ static int gp_frame_clean_fill_exec(bContext *C, wmOperator *op)
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || (mode == GP_FRAME_CLEAN_FILL_ALL)) {
- bGPDstroke *gps, *gpsn;
if (gpf == NULL) {
continue;
}
/* simply delete strokes which are no fill */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -778,8 +789,6 @@ static int gp_frame_clean_loose_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
- bGPDstroke *gps = NULL;
- bGPDstroke *gpsn = NULL;
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
@@ -788,9 +797,7 @@ static int gp_frame_clean_loose_exec(bContext *C, wmOperator *op)
}
/* simply delete strokes which are no loose */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -861,7 +868,7 @@ void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot)
static int gp_hide_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *layer = BKE_gpencil_layer_active_get(gpd);
bool unselected = RNA_boolean_get(op->ptr, "unselected");
/* sanity checks */
@@ -870,10 +877,8 @@ static int gp_hide_exec(bContext *C, wmOperator *op)
}
if (unselected) {
- bGPDlayer *gpl;
-
/* hide unselected */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl != layer) {
gpl->flag |= GP_LAYER_HIDE;
}
@@ -946,7 +951,6 @@ static void gp_reveal_select_frame(bContext *C, bGPDframe *frame, bool select)
static int gp_reveal_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
const bool select = RNA_boolean_get(op->ptr, "select");
/* sanity checks */
@@ -954,8 +958,7 @@ static int gp_reveal_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
-
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->flag & GP_LAYER_HIDE) {
gpl->flag &= ~GP_LAYER_HIDE;
@@ -1008,7 +1011,6 @@ void GPENCIL_OT_reveal(wmOperatorType *ot)
static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
/* sanity checks */
if (gpd == NULL) {
@@ -1016,7 +1018,7 @@ static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* make all layers non-editable */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag |= GP_LAYER_LOCKED;
}
@@ -1048,7 +1050,6 @@ void GPENCIL_OT_lock_all(wmOperatorType *ot)
static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
/* sanity checks */
if (gpd == NULL) {
@@ -1056,7 +1057,7 @@ static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* make all layers editable again */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~GP_LAYER_LOCKED;
}
@@ -1087,8 +1088,7 @@ void GPENCIL_OT_unlock_all(wmOperatorType *ot)
static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
- bGPDlayer *gpl;
+ bGPDlayer *layer = BKE_gpencil_layer_active_get(gpd);
int flags = GP_LAYER_LOCKED;
bool isolate = false;
@@ -1102,7 +1102,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
}
/* Test whether to isolate or clear all flags */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Skip if this is the active layer */
if (gpl == layer) {
continue;
@@ -1121,7 +1121,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
/* TODO: Include onion-skinning on this list? */
if (isolate) {
/* Set flags on all "other" layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl == layer) {
continue;
}
@@ -1132,7 +1132,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
}
else {
/* Clear flags - Restore everything else */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~flags;
}
}
@@ -1172,7 +1172,7 @@ void GPENCIL_OT_layer_isolate(wmOperatorType *ot)
static int gp_merge_layer_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl_next = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl_next = BKE_gpencil_layer_active_get(gpd);
bGPDlayer *gpl_current = gpl_next->prev;
if (ELEM(NULL, gpd, gpl_current, gpl_next)) {
@@ -1182,16 +1182,16 @@ static int gp_merge_layer_exec(bContext *C, wmOperator *op)
/* Collect frames of gpl_current in hash table to avoid O(n^2) lookups */
GHash *gh_frames_cur = BLI_ghash_int_new_ex(__func__, 64);
- for (bGPDframe *gpf = gpl_current->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_current->frames) {
BLI_ghash_insert(gh_frames_cur, POINTER_FROM_INT(gpf->framenum), gpf);
}
/* read all frames from next layer and add any missing in current layer */
- for (bGPDframe *gpf = gpl_next->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_next->frames) {
/* try to find frame in current layer */
bGPDframe *frame = BLI_ghash_lookup(gh_frames_cur, POINTER_FROM_INT(gpf->framenum));
if (!frame) {
- bGPDframe *actframe = BKE_gpencil_layer_getframe(
+ bGPDframe *actframe = BKE_gpencil_layer_frame_get(
gpl_current, gpf->framenum, GP_GETFRAME_USE_PREV);
frame = BKE_gpencil_frame_addnew(gpl_current, gpf->framenum);
/* duplicate strokes of current active frame */
@@ -1203,13 +1203,33 @@ static int gp_merge_layer_exec(bContext *C, wmOperator *op)
BLI_movelisttolist(&frame->strokes, &gpf->strokes);
}
+ /* Add Masks to destination layer. */
+ LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl_next->mask_layers) {
+ /* Don't add merged layers or missing layer names. */
+ if (!BKE_gpencil_layer_named_get(gpd, mask->name) || STREQ(mask->name, gpl_next->info) ||
+ STREQ(mask->name, gpl_current->info)) {
+ continue;
+ }
+ if (!BKE_gpencil_layer_mask_named_get(gpl_current, mask->name)) {
+ bGPDlayer_Mask *mask_new = MEM_dupallocN(mask);
+ BLI_addtail(&gpl_current->mask_layers, mask_new);
+ gpl_current->act_mask++;
+ }
+ }
+ /* Set destination layer as active. */
+ BKE_gpencil_layer_active_set(gpd, gpl_current);
+
/* Now delete next layer */
BKE_gpencil_layer_delete(gpd, gpl_next);
BLI_ghash_free(gh_frames_cur, NULL, NULL);
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort(gpd, gpl_current);
+
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -1268,11 +1288,12 @@ static int gp_layer_change_exec(bContext *C, wmOperator *op)
}
/* Set active layer */
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
/* updates */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
@@ -1297,6 +1318,50 @@ void GPENCIL_OT_layer_change(wmOperatorType *ot)
RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
}
+static int gp_layer_active_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ int layer_num = RNA_int_get(op->ptr, "layer");
+
+ /* Try to get layer */
+ bGPDlayer *gpl = BLI_findlink(&gpd->layers, layer_num);
+
+ if (gpl == NULL) {
+ BKE_reportf(
+ op->reports, RPT_ERROR, "Cannot change to non-existent layer (index = %d)", layer_num);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Set active layer */
+ BKE_gpencil_layer_active_set(gpd, gpl);
+
+ /* updates */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_active(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Active Layer";
+ ot->idname = "GPENCIL_OT_layer_active";
+ ot->description = "Active Grease Pencil layer";
+
+ /* callbacks */
+ ot->exec = gp_layer_active_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* GPencil layer to use. */
+ ot->prop = RNA_def_int(ot->srna, "layer", 0, 0, INT_MAX, "Grease Pencil Layer", "", 0, INT_MAX);
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
/* ************************************************ */
/* ******************* Arrange Stroke Up/Down in drawing order ************************** */
@@ -1312,7 +1377,7 @@ static int gp_stroke_arrange_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl_act = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl_act = BKE_gpencil_layer_active_get(gpd);
/* sanity checks */
if (ELEM(NULL, gpd, gpl_act, gpl_act->actframe)) {
@@ -1372,7 +1437,7 @@ static int gp_stroke_arrange_exec(bContext *C, wmOperator *op)
switch (direction) {
/* Bring to Front */
case GP_STROKE_MOVE_TOP:
- for (LinkData *link = selected.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &selected) {
gps = link->data;
BLI_remlink(&gpf->strokes, gps);
BLI_addtail(&gpf->strokes, gps);
@@ -1387,7 +1452,7 @@ static int gp_stroke_arrange_exec(bContext *C, wmOperator *op)
break;
/* Send Backward */
case GP_STROKE_MOVE_DOWN:
- for (LinkData *link = selected.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &selected) {
gps = link->data;
BLI_listbase_link_move(&gpf->strokes, gps, -1);
}
@@ -1460,7 +1525,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
bGPdata *gpd = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
if (name[0] == '\0') {
- ma = BKE_material_gpencil_get(ob, ob->actcol);
+ ma = BKE_gpencil_material(ob, ob->actcol);
}
else {
ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
@@ -1469,7 +1534,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
}
}
/* try to find slot */
- int idx = BKE_gpencil_object_material_get_index(ob, ma);
+ int idx = BKE_gpencil_object_material_index_get(ob, ma);
if (idx < 0) {
return OPERATOR_CANCELLED;
}
@@ -1494,7 +1559,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* only if selected */
if (gps->flag & GP_STROKE_SELECT) {
/* skip strokes that are invalid for current view */
@@ -1545,13 +1610,13 @@ void GPENCIL_OT_stroke_change_color(wmOperatorType *ot)
/* ******************* Lock color of non selected Strokes colors ************************** */
-static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
+static int gp_material_lock_unsused_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
/* sanity checks */
if (ELEM(NULL, gpd)) {
@@ -1560,17 +1625,17 @@ 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);
+ Material *tmp_ma = BKE_object_material_get(ob, i + 1);
if (tmp_ma) {
- tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ tmp_ma->gp_style->flag |= GP_MATERIAL_LOCKED;
DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
/* loop all selected strokes and unlock any color */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
/* only if selected */
if (gps->flag & GP_STROKE_SELECT) {
@@ -1579,9 +1644,9 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
/* unlock color */
- Material *tmp_ma = give_current_material(ob, gps->mat_nr + 1);
+ Material *tmp_ma = BKE_object_material_get(ob, gps->mat_nr + 1);
if (tmp_ma) {
- tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ tmp_ma->gp_style->flag &= ~GP_MATERIAL_LOCKED;
DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -1601,15 +1666,15 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_stroke_lock_color(wmOperatorType *ot)
+void GPENCIL_OT_material_lock_unused(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Lock Unused Colors";
- ot->idname = "GPENCIL_OT_stroke_lock_color";
- ot->description = "Lock any color not used in any selected stroke";
+ ot->name = "Lock Unused Materials";
+ ot->idname = "GPENCIL_OT_material_lock_unused";
+ ot->description = "Lock any material not used in any selected stroke";
/* api callbacks */
- ot->exec = gp_stroke_lock_color_exec;
+ ot->exec = gp_material_lock_unsused_exec;
ot->poll = gp_active_layer_poll;
/* flags */
@@ -1619,28 +1684,273 @@ void GPENCIL_OT_stroke_lock_color(wmOperatorType *ot)
/* ************************************************ */
/* Drawing Brushes Operators */
-/* ******************* Brush create presets ************************** */
-static int gp_brush_presets_create_exec(bContext *C, wmOperator *UNUSED(op))
+/* ******************* Brush resets ************************** */
+static int gp_brush_reset_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
ToolSettings *ts = CTX_data_tool_settings(C);
- BKE_brush_gpencil_presets(bmain, ts);
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+ Brush *brush = NULL;
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL: {
+ Paint *paint = &ts->gp_paint->paint;
+ brush = paint->brush;
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
+ break;
+ }
+ case CTX_MODE_SCULPT_GPENCIL: {
+ Paint *paint = &ts->gp_sculptpaint->paint;
+ brush = paint->brush;
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
+ break;
+ }
+ case CTX_MODE_WEIGHT_GPENCIL: {
+ Paint *paint = &ts->gp_weightpaint->paint;
+ brush = paint->brush;
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
+ break;
+ }
+ case CTX_MODE_VERTEX_GPENCIL: {
+ Paint *paint = &ts->gp_vertexpaint->paint;
+ brush = paint->brush;
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
+ break;
+ }
+ default:
+ break;
+ }
/* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_brush_reset(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Reset Brush";
+ ot->idname = "GPENCIL_OT_brush_reset";
+ ot->description = "Reset Brush to default parameters";
+
+ /* api callbacks */
+ ot->exec = gp_brush_reset_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static Brush *gp_brush_get_first_by_mode(Main *bmain,
+ Paint *UNUSED(paint),
+ const enum eContextObjectMode mode,
+ char tool)
+{
+ Brush *brush_next = NULL;
+ for (Brush *brush = bmain->brushes.first; brush; brush = brush_next) {
+ brush_next = brush->id.next;
+
+ if (brush->gpencil_settings == NULL) {
+ continue;
+ }
+
+ if ((mode == CTX_MODE_PAINT_GPENCIL) && (brush->gpencil_tool == tool)) {
+ return brush;
+ }
+
+ if ((mode == CTX_MODE_SCULPT_GPENCIL) && (brush->gpencil_sculpt_tool == tool)) {
+ return brush;
+ }
+
+ if ((mode == CTX_MODE_WEIGHT_GPENCIL) && (brush->gpencil_weight_tool == tool)) {
+ return brush;
+ }
+
+ if ((mode == CTX_MODE_VERTEX_GPENCIL) && (brush->gpencil_vertex_tool == tool)) {
+ return brush;
+ }
+ }
+
+ return NULL;
+}
+
+static void gp_brush_delete_mode_brushes(Main *bmain,
+ Paint *paint,
+ const enum eContextObjectMode mode)
+{
+ Brush *brush_active = paint->brush;
+ Brush *brush_next = NULL;
+ for (Brush *brush = bmain->brushes.first; brush; brush = brush_next) {
+ brush_next = brush->id.next;
+
+ if ((brush->gpencil_settings == NULL) && (brush->ob_mode != OB_MODE_PAINT_GPENCIL)) {
+ continue;
+ }
+
+ short preset = (brush->gpencil_settings) ? brush->gpencil_settings->preset_type :
+ GP_BRUSH_PRESET_UNKNOWN;
+
+ if (preset != GP_BRUSH_PRESET_UNKNOWN) {
+ /* Verify to delete only the brushes of the current mode. */
+ if (mode == CTX_MODE_PAINT_GPENCIL) {
+ if ((preset < GP_BRUSH_PRESET_AIRBRUSH) || (preset > GP_BRUSH_PRESET_TINT)) {
+ continue;
+ }
+ if ((brush_active) && (brush_active->gpencil_tool != brush->gpencil_tool)) {
+ continue;
+ }
+ }
+
+ if (mode == CTX_MODE_SCULPT_GPENCIL) {
+ if ((preset < GP_BRUSH_PRESET_SMOOTH_STROKE) || (preset > GP_BRUSH_PRESET_CLONE_STROKE)) {
+ continue;
+ }
+ if ((brush_active) && (brush_active->gpencil_sculpt_tool != brush->gpencil_sculpt_tool)) {
+ continue;
+ }
+ }
+
+ if (mode == CTX_MODE_WEIGHT_GPENCIL) {
+ if (preset != GP_BRUSH_PRESET_DRAW_WEIGHT) {
+ continue;
+ }
+ if ((brush_active) && (brush_active->gpencil_weight_tool != brush->gpencil_weight_tool)) {
+ continue;
+ }
+ }
+
+ if (mode == CTX_MODE_VERTEX_GPENCIL) {
+ if ((preset < GP_BRUSH_PRESET_VERTEX_DRAW) || (preset > GP_BRUSH_PRESET_VERTEX_REPLACE)) {
+ continue;
+ }
+ if ((brush_active) && (brush_active->gpencil_vertex_tool != brush->gpencil_vertex_tool)) {
+ continue;
+ }
+ }
+ }
+
+ /* Before delete, unpinn any material of the brush. */
+ if ((brush->gpencil_settings) && (brush->gpencil_settings->material != NULL)) {
+ brush->gpencil_settings->material = NULL;
+ brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED;
+ }
+
+ BKE_brush_delete(bmain, brush);
+ }
+}
+
+static int gp_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+ Paint *paint = NULL;
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL: {
+ paint = &ts->gp_paint->paint;
+ break;
+ }
+ case CTX_MODE_SCULPT_GPENCIL: {
+ paint = &ts->gp_sculptpaint->paint;
+ break;
+ }
+ case CTX_MODE_WEIGHT_GPENCIL: {
+ paint = &ts->gp_weightpaint->paint;
+ break;
+ }
+ case CTX_MODE_VERTEX_GPENCIL: {
+ paint = &ts->gp_vertexpaint->paint;
+ break;
+ }
+ default:
+ break;
+ }
+
+ char tool = '0';
+ if (paint) {
+ Brush *brush_active = paint->brush;
+ if (brush_active) {
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL: {
+ tool = brush_active->gpencil_tool;
+ break;
+ }
+ case CTX_MODE_SCULPT_GPENCIL: {
+ tool = brush_active->gpencil_sculpt_tool;
+ break;
+ }
+ case CTX_MODE_WEIGHT_GPENCIL: {
+ tool = brush_active->gpencil_weight_tool;
+ break;
+ }
+ case CTX_MODE_VERTEX_GPENCIL: {
+ tool = brush_active->gpencil_vertex_tool;
+ break;
+ }
+ default: {
+ tool = brush_active->gpencil_tool;
+ break;
+ }
+ }
+ }
+
+ gp_brush_delete_mode_brushes(bmain, paint, mode);
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL: {
+ BKE_brush_gpencil_paint_presets(bmain, ts, true);
+ break;
+ }
+ case CTX_MODE_SCULPT_GPENCIL: {
+ BKE_brush_gpencil_sculpt_presets(bmain, ts, true);
+ break;
+ }
+ case CTX_MODE_WEIGHT_GPENCIL: {
+ BKE_brush_gpencil_weight_presets(bmain, ts, true);
+ break;
+ }
+ case CTX_MODE_VERTEX_GPENCIL: {
+ BKE_brush_gpencil_vertex_presets(bmain, ts, true);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ BKE_paint_toolslots_brush_validate(bmain, paint);
+
+ /* Set Again the first brush of the mode. */
+ Brush *deft_brush = gp_brush_get_first_by_mode(bmain, paint, mode, tool);
+ if (deft_brush) {
+ BKE_paint_brush_set(paint, deft_brush);
+ }
+ /* notifiers */
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, NULL);
+ }
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_brush_presets_create(wmOperatorType *ot)
+void GPENCIL_OT_brush_reset_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Create Preset Brushes";
- ot->idname = "GPENCIL_OT_brush_presets_create";
- ot->description = "Create a set of predefined Grease Pencil drawing brushes";
+ ot->name = "Reset All Brushes";
+ ot->idname = "GPENCIL_OT_brush_reset_all";
+ ot->description = "Delete all mode brushes and recreate a default set";
/* api callbacks */
- ot->exec = gp_brush_presets_create_exec;
+ ot->exec = gp_brush_reset_all_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1846,12 +2156,12 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op)
for (int i = 0; i < gps->totpoints; i++) {
dvert = &gps->dvert[i];
- MDeformWeight *dw = defvert_find_index(dvert, def_nr);
+ MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr);
if (dw == NULL) {
- defvert_add_index_notest(dvert, def_nr, 1.0f);
+ BKE_defvert_add_index_notest(dvert, def_nr, 1.0f);
}
else if (dw->weight == 1.0f) {
- defvert_remove_group(dvert, dw);
+ BKE_defvert_remove_group(dvert, dw);
}
else {
dw->weight = 1.0f - dw->weight;
@@ -1938,8 +2248,8 @@ static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op)
ptc = &gps->points[i];
}
- float wa = defvert_find_weight(dverta, def_nr);
- float wb = defvert_find_weight(dvertb, def_nr);
+ float wa = BKE_defvert_find_weight(dverta, def_nr);
+ float wb = BKE_defvert_find_weight(dvertb, def_nr);
/* the optimal value is the corresponding to the interpolation of the weight
* at the distance of point b
@@ -1947,7 +2257,7 @@ static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op)
const float opfac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
const float optimal = interpf(wa, wb, opfac);
/* Based on influence factor, blend between original and optimal */
- MDeformWeight *dw = defvert_verify_index(dvertb, def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvertb, def_nr);
if (dw) {
dw->weight = interpf(wb, optimal, fac);
CLAMP(dw->weight, 0.0, 1.0f);
@@ -2016,7 +2326,7 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op)
float maxvalue = 0.0f;
for (int i = 0; i < gps->totpoints; i++) {
dvert = &gps->dvert[i];
- dw = defvert_find_index(dvert, def_nr);
+ dw = BKE_defvert_find_index(dvert, def_nr);
if ((dw != NULL) && (dw->weight > maxvalue)) {
maxvalue = dw->weight;
}
@@ -2026,7 +2336,7 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op)
if (maxvalue > 0.0f) {
for (int i = 0; i < gps->totpoints; i++) {
dvert = &gps->dvert[i];
- dw = defvert_find_index(dvert, def_nr);
+ dw = BKE_defvert_find_index(dvert, def_nr);
if (dw != NULL) {
dw->weight = dw->weight / maxvalue;
}
@@ -2102,7 +2412,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
continue;
}
- dw = defvert_find_index(dvert, v);
+ dw = BKE_defvert_find_index(dvert, v);
if (dw != NULL) {
tot_values[i] += dw->weight;
}
@@ -2128,7 +2438,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
continue;
}
- dw = defvert_find_index(dvert, v);
+ dw = BKE_defvert_find_index(dvert, v);
if (dw != NULL) {
dw->weight = dw->weight / tot_values[i];
}
@@ -2217,7 +2527,7 @@ static void joined_gpencil_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data)
/* Fix driver targets */
if (fcu->driver) {
/* Fix driver references to invalid ID's */
- for (DriverVar *dvar = fcu->driver->variables.first; dvar; dvar = dvar->next) {
+ LISTBASE_FOREACH (DriverVar *, dvar, &fcu->driver->variables) {
/* Only change the used targets, since the others will need fixing manually anyway. */
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
/* Change the ID's used. */
@@ -2308,8 +2618,8 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
bGPdata *gpd_src = ob_iter->data;
/* Apply all GP modifiers before */
- for (GpencilModifierData *md = ob_iter->greasepencil_modifiers.first; md; md = md->next) {
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ LISTBASE_FOREACH (GpencilModifierData *, md, &ob_iter->greasepencil_modifiers) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
if (mti->bakeModifier) {
mti->bakeModifier(bmain, depsgraph, md, ob_iter);
}
@@ -2317,19 +2627,22 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
/* copy vertex groups to the base one's */
int old_idx = 0;
- for (bDeformGroup *dg = ob_iter->defbase.first; dg; dg = dg->next) {
+ LISTBASE_FOREACH (bDeformGroup *, dg, &ob_iter->defbase) {
bDeformGroup *vgroup = MEM_dupallocN(dg);
int idx = BLI_listbase_count(&ob_active->defbase);
- defgroup_unique_name(vgroup, ob_active);
+ BKE_object_defgroup_unique_name(vgroup, ob_active);
BLI_addtail(&ob_active->defbase, vgroup);
/* update vertex groups in strokes in original data */
- for (bGPDlayer *gpl_src = gpd->layers.first; gpl_src; gpl_src = gpl_src->next) {
- for (bGPDframe *gpf = gpl_src->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_src->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
MDeformVert *dvert;
int i;
+ if (gps->dvert == NULL) {
+ continue;
+ }
for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
- if ((dvert->dw) && (dvert->dw->def_nr == old_idx)) {
+ if ((dvert->dw != NULL) && (dvert->dw->def_nr == old_idx)) {
dvert->dw->def_nr = idx;
}
}
@@ -2343,10 +2656,10 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
}
/* add missing materials reading source materials and checking in destination object */
- short *totcol = give_totcolp(ob_src);
+ short *totcol = BKE_object_material_len_p(ob_src);
for (short i = 0; i < *totcol; i++) {
- Material *tmp_ma = BKE_material_gpencil_get(ob_src, i + 1);
+ Material *tmp_ma = BKE_gpencil_material(ob_src, i + 1);
BKE_gpencil_object_material_ensure(bmain, ob_dst, tmp_ma);
}
@@ -2366,21 +2679,21 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
mul_m3_v3(imat, offset_global);
mul_v3_m3v3(offset_local, imat, offset_global);
- for (bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src);
float diff_mat[4][4];
float inverse_diff_mat[4][4];
/* recalculate all stroke points */
- ED_gpencil_parent_location(depsgraph, ob_iter, gpd_src, gpl_src, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
Material *ma_src = NULL;
- for (bGPDframe *gpf = gpl_new->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_new->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* Reassign material. Look old material and try to find in destination. */
- ma_src = BKE_material_gpencil_get(ob_src, gps->mat_nr + 1);
+ ma_src = BKE_gpencil_material(ob_src, gps->mat_nr + 1);
gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
bGPDspoint *pt;
@@ -2458,17 +2771,18 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
}
/* Color Handle operator */
-static bool gpencil_active_color_poll(bContext *C)
+static bool gpencil_active_material_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if (ob && ob->data && (ob->type == OB_GPENCIL)) {
- short *totcolp = give_totcolp(ob);
+ short *totcolp = BKE_object_material_len_p(ob);
return *totcolp > 0;
}
return false;
}
-/* **************** Lock and hide any color non used in current layer ************************** */
+/* **************** Lock and hide any color non used in current layer **************************
+ */
static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
@@ -2482,25 +2796,25 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
/* first lock and hide all colors */
Material *ma = NULL;
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
if (totcol == 0) {
return OPERATOR_CANCELLED;
}
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- gp_style->flag |= GP_STYLE_COLOR_HIDE;
+ gp_style->flag |= GP_MATERIAL_LOCKED;
+ gp_style->flag |= GP_MATERIAL_HIDE;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
/* loop all selected strokes and unlock any color used in active layer */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL) &&
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL) &&
(gpl->flag & GP_LAYER_ACTIVE)) {
for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
/* skip strokes that are invalid for current view */
@@ -2508,14 +2822,14 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
- ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
+ ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
gp_style = ma->gp_style;
/* unlock/unhide color if not unlocked before */
if (gp_style != NULL) {
- gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
- gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
+ gp_style->flag &= ~GP_MATERIAL_LOCKED;
+ gp_style->flag &= ~GP_MATERIAL_HIDE;
}
}
}
@@ -2547,19 +2861,19 @@ void GPENCIL_OT_lock_layer(wmOperatorType *ot)
/* ********************** Isolate gpencil_ color **************************** */
-static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
+static int gpencil_material_isolate_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
- Material *active_ma = BKE_material_gpencil_get(ob, ob->actcol);
- MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
+ Material *active_ma = BKE_gpencil_material(ob, ob->actcol);
+ MaterialGPencilStyle *active_color = BKE_gpencil_material_settings(ob, ob->actcol);
MaterialGPencilStyle *gp_style;
- int flags = GP_STYLE_COLOR_LOCKED;
+ int flags = GP_MATERIAL_LOCKED;
bool isolate = false;
if (RNA_boolean_get(op->ptr, "affect_visibility")) {
- flags |= GP_STYLE_COLOR_HIDE;
+ flags |= GP_MATERIAL_HIDE;
}
if (ELEM(NULL, gpd, active_color)) {
@@ -2569,9 +2883,9 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
/* Test whether to isolate or clear all flags */
Material *ma = NULL;
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
/* Skip if this is the active one */
if ((ma == NULL) || (ma == active_ma)) {
continue;
@@ -2591,7 +2905,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
if (isolate) {
/* Set flags on all "other" colors */
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
if (ma == NULL) {
continue;
}
@@ -2608,7 +2922,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
else {
/* Clear flags - Restore everything else */
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
if (ma == NULL) {
continue;
}
@@ -2629,17 +2943,17 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_color_isolate(wmOperatorType *ot)
+void GPENCIL_OT_material_isolate(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Isolate Color";
- ot->idname = "GPENCIL_OT_color_isolate";
+ ot->name = "Isolate Material";
+ ot->idname = "GPENCIL_OT_material_isolate";
ot->description =
- "Toggle whether the active color is the only one that is editable and/or visible";
+ "Toggle whether the active material is the only one that is editable and/or visible";
/* callbacks */
- ot->exec = gpencil_color_isolate_exec;
- ot->poll = gpencil_active_color_poll;
+ ot->exec = gpencil_material_isolate_exec;
+ ot->poll = gpencil_active_material_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2655,16 +2969,16 @@ void GPENCIL_OT_color_isolate(wmOperatorType *ot)
/* *********************** Hide colors ******************************** */
-static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
+static int gpencil_material_hide_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = (bGPdata *)ob->data;
- MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
+ MaterialGPencilStyle *active_color = BKE_gpencil_material_settings(ob, ob->actcol);
bool unselected = RNA_boolean_get(op->ptr, "unselected");
Material *ma = NULL;
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
if (totcol == 0) {
return OPERATOR_CANCELLED;
}
@@ -2673,11 +2987,11 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
/* hide unselected */
MaterialGPencilStyle *color = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
color = ma->gp_style;
if (active_color != color) {
- color->flag |= GP_STYLE_COLOR_HIDE;
+ color->flag |= GP_MATERIAL_HIDE;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -2685,7 +2999,7 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
}
else {
/* hide selected/active */
- active_color->flag |= GP_STYLE_COLOR_HIDE;
+ active_color->flag |= GP_MATERIAL_HIDE;
}
/* updates */
@@ -2700,16 +3014,16 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_color_hide(wmOperatorType *ot)
+void GPENCIL_OT_material_hide(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Hide Color(s)";
- ot->idname = "GPENCIL_OT_color_hide";
- ot->description = "Hide selected/unselected Grease Pencil colors";
+ ot->name = "Hide Material(s)";
+ ot->idname = "GPENCIL_OT_material_hide";
+ ot->description = "Hide selected/unselected Grease Pencil materials";
/* callbacks */
- ot->exec = gpencil_color_hide_exec;
- ot->poll = gpencil_active_color_poll; /* NOTE: we need an active color to play with */
+ ot->exec = gpencil_material_hide_exec;
+ ot->poll = gpencil_active_material_poll; /* NOTE: we need an active color to play with */
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2721,12 +3035,12 @@ void GPENCIL_OT_color_hide(wmOperatorType *ot)
/* ********************** Show All Colors ***************************** */
-static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int gpencil_material_reveal_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = (bGPdata *)ob->data;
Material *ma = NULL;
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
if (totcol == 0) {
return OPERATOR_CANCELLED;
@@ -2736,10 +3050,10 @@ static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
MaterialGPencilStyle *gp_style = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
+ gp_style->flag &= ~GP_MATERIAL_HIDE;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -2756,16 +3070,16 @@ static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_color_reveal(wmOperatorType *ot)
+void GPENCIL_OT_material_reveal(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Show All Colors";
- ot->idname = "GPENCIL_OT_color_reveal";
- ot->description = "Unhide all hidden Grease Pencil colors";
+ ot->name = "Show All Materials";
+ ot->idname = "GPENCIL_OT_material_reveal";
+ ot->description = "Unhide all hidden Grease Pencil materials";
/* callbacks */
- ot->exec = gpencil_color_reveal_exec;
- ot->poll = gpencil_active_color_poll;
+ ot->exec = gpencil_material_reveal_exec;
+ ot->poll = gpencil_active_material_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2773,13 +3087,13 @@ void GPENCIL_OT_color_reveal(wmOperatorType *ot)
/* ***************** Lock/Unlock All colors ************************ */
-static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int gpencil_material_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = (bGPdata *)ob->data;
Material *ma = NULL;
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
if (totcol == 0) {
return OPERATOR_CANCELLED;
@@ -2789,10 +3103,10 @@ static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
MaterialGPencilStyle *gp_style = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ gp_style->flag |= GP_MATERIAL_LOCKED;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -2809,17 +3123,17 @@ static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_color_lock_all(wmOperatorType *ot)
+void GPENCIL_OT_material_lock_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Lock All Colors";
- ot->idname = "GPENCIL_OT_color_lock_all";
+ ot->name = "Lock All Materials";
+ ot->idname = "GPENCIL_OT_material_lock_all";
ot->description =
- "Lock all Grease Pencil colors to prevent them from being accidentally modified";
+ "Lock all Grease Pencil materials to prevent them from being accidentally modified";
/* callbacks */
- ot->exec = gpencil_color_lock_all_exec;
- ot->poll = gpencil_active_color_poll;
+ ot->exec = gpencil_material_lock_all_exec;
+ ot->poll = gpencil_active_material_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2827,12 +3141,12 @@ void GPENCIL_OT_color_lock_all(wmOperatorType *ot)
/* -------------------------- */
-static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int gpencil_material_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = (bGPdata *)ob->data;
Material *ma = NULL;
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
if (totcol == 0) {
return OPERATOR_CANCELLED;
@@ -2842,10 +3156,10 @@ static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
MaterialGPencilStyle *gp_style = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = BKE_material_gpencil_get(ob, i + 1);
+ ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ gp_style->flag &= ~GP_MATERIAL_LOCKED;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -2862,16 +3176,16 @@ static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_color_unlock_all(wmOperatorType *ot)
+void GPENCIL_OT_material_unlock_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Unlock All Colors";
- ot->idname = "GPENCIL_OT_color_unlock_all";
- ot->description = "Unlock all Grease Pencil colors so that they can be edited";
+ ot->name = "Unlock All Materials";
+ ot->idname = "GPENCIL_OT_material_unlock_all";
+ ot->description = "Unlock all Grease Pencil materials so that they can be edited";
/* callbacks */
- ot->exec = gpencil_color_unlock_all_exec;
- ot->poll = gpencil_active_color_poll;
+ ot->exec = gpencil_material_unlock_all_exec;
+ ot->poll = gpencil_active_material_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2879,11 +3193,11 @@ void GPENCIL_OT_color_unlock_all(wmOperatorType *ot)
/* ***************** Select all strokes using color ************************ */
-static int gpencil_color_select_exec(bContext *C, wmOperator *op)
+static int gpencil_material_select_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol);
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, ob->actcol);
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const bool deselected = RNA_boolean_get(op->ptr, "deselect");
@@ -2900,7 +3214,7 @@ static int gpencil_color_select_exec(bContext *C, wmOperator *op)
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
/* verify something to do */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -2949,16 +3263,16 @@ static int gpencil_color_select_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_color_select(wmOperatorType *ot)
+void GPENCIL_OT_material_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Color";
- ot->idname = "GPENCIL_OT_color_select";
- ot->description = "Select all Grease Pencil strokes using current color";
+ ot->name = "Select Material";
+ ot->idname = "GPENCIL_OT_material_select";
+ ot->description = "Select/Deselect all Grease Pencil strokes using current material";
/* callbacks */
- ot->exec = gpencil_color_select_exec;
- ot->poll = gpencil_active_color_poll;
+ ot->exec = gpencil_material_select_exec;
+ ot->poll = gpencil_active_material_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2968,6 +3282,48 @@ void GPENCIL_OT_color_select(wmOperatorType *ot)
RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+/* ***************** Set active material ************************* */
+static int gpencil_material_set_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ int slot = RNA_enum_get(op->ptr, "slot");
+
+ /* Try to get material */
+ if ((slot < 1) || (slot > ob->totcol)) {
+ BKE_reportf(
+ op->reports, RPT_ERROR, "Cannot change to non-existent material (index = %d)", slot);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Set active material. */
+ ob->actcol = slot;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_material_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Material";
+ ot->idname = "GPENCIL_OT_material_set";
+ ot->description = "Set active material";
+
+ /* callbacks */
+ ot->exec = gpencil_material_set_exec;
+ ot->poll = gpencil_active_material_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Material to use (dynamic enum) */
+ ot->prop = RNA_def_enum(ot->srna, "slot", DummyRNA_DEFAULT_items, 0, "Material Slot", "");
+ RNA_def_enum_funcs(ot->prop, ED_gpencil_material_enum_itemf);
+}
+
/* ***************** Set selected stroke material the active material ************************ */
static int gpencil_set_active_material_exec(bContext *C, wmOperator *op)
@@ -3010,7 +3366,7 @@ void GPENCIL_OT_set_active_material(wmOperatorType *ot)
/* callbacks */
ot->exec = gpencil_set_active_material_exec;
- ot->poll = gpencil_active_color_poll;
+ ot->poll = gpencil_active_material_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -3030,7 +3386,7 @@ bool ED_gpencil_add_lattice_modifier(const bContext *C,
}
/* if no lattice modifier, add a new one */
- GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob, eGpencilModifierType_Lattice);
+ GpencilModifierData *md = BKE_gpencil_modifiers_findby_type(ob, eGpencilModifierType_Lattice);
if (md == NULL) {
md = ED_object_gpencil_modifier_add(
reports, bmain, scene, ob, "Lattice", eGpencilModifierType_Lattice);
@@ -3057,3 +3413,118 @@ bool ED_gpencil_add_lattice_modifier(const bContext *C,
return true;
}
+
+/* Masking operators */
+static int gp_layer_mask_add_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
+ if (gpl_active == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ char name[128];
+ RNA_string_get(op->ptr, "name", name);
+ bGPDlayer *gpl = BKE_gpencil_layer_named_get(gpd, name);
+
+ if (gpl == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to find layer to add");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (gpl == gpl_active) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot add active layer as mask");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (BKE_gpencil_layer_mask_named_get(gpl_active, name)) {
+ BKE_report(op->reports, RPT_ERROR, "Layer already added");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (gpl_active->act_mask == 256) {
+ BKE_report(op->reports, RPT_ERROR, "Maximum number of masking layers reached");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_gpencil_layer_mask_add(gpl_active, name);
+
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort(gpd, gpl_active);
+
+ /* notifiers */
+ if (gpd) {
+ DEG_id_tag_update(&gpd->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ }
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_mask_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Mask Layer";
+ ot->idname = "GPENCIL_OT_layer_mask_add";
+ ot->description = "Add new layer as masking";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_layer_mask_add_exec;
+ ot->poll = gp_add_poll;
+
+ /* properties */
+ RNA_def_string(ot->srna, "name", NULL, 128, "Layer", "Name of the layer");
+}
+
+static int gp_layer_mask_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
+ if (gpl == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ if (gpl->act_mask > 0) {
+ bGPDlayer_Mask *mask = BLI_findlink(&gpl->mask_layers, gpl->act_mask - 1);
+ if (mask != NULL) {
+ BKE_gpencil_layer_mask_remove(gpl, mask);
+ if ((gpl->mask_layers.first != NULL) && (gpl->act_mask == 0)) {
+ gpl->act_mask = 1;
+ }
+ }
+ }
+
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort(gpd, gpl);
+
+ /* notifiers */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_mask_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Mask Layer";
+ ot->idname = "GPENCIL_OT_layer_mask_remove";
+ ot->description = "Remove Layer Mask";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_layer_mask_remove_exec;
+ ot->poll = gp_active_layer_poll;
+}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 8d0fe73572f..4444396558b 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -22,11 +22,11 @@
* \ingroup edgpencil
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -39,34 +39,35 @@
#include "BLT_translation.h"
+#include "DNA_gpencil_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_gpencil_types.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_library.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_report.h"
-#include "BKE_workspace.h"
#include "BKE_scene.h"
+#include "BKE_workspace.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -76,11 +77,12 @@
#include "ED_gpencil.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
-#include "ED_transform_snap_object_context.h"
-#include "ED_view3d.h"
#include "ED_select_utils.h"
#include "ED_space_api.h"
+#include "ED_transform_snap_object_context.h"
+#include "ED_view3d.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -88,8 +90,9 @@
#include "gpencil_intern.h"
-/* ************************************************ */
-/* Stroke Edit Mode Management */
+/* -------------------------------------------------------------------- */
+/** \name Stroke Edit Mode Management
+ * \{ */
/* poll callback for all stroke editing operators */
static bool gp_stroke_edit_poll(bContext *C)
@@ -136,6 +139,12 @@ static bool gpencil_editmode_toggle_poll(bContext *C)
return ED_gpencil_data_get_active(C) != NULL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Edit Mode Operator
+ * \{ */
+
static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *op)
{
const int back = RNA_boolean_get(op->ptr, "back");
@@ -221,6 +230,12 @@ void GPENCIL_OT_editmode_toggle(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Select Mode Operator
+ * \{ */
+
/* set select mode */
static bool gpencil_selectmode_toggle_poll(bContext *C)
{
@@ -296,7 +311,11 @@ void GPENCIL_OT_selectmode_toggle(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
-/* Stroke Paint Mode Management */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Stroke Paint Mode Operator
+ * \{ */
static bool gpencil_paintmode_toggle_poll(bContext *C)
{
@@ -335,6 +354,10 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
/* set mode */
if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
mode = OB_MODE_PAINT_GPENCIL;
+ BKE_brush_gpencil_paint_presets(bmain, ts, false);
+
+ /* Ensure Palette by default. */
+ BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));
}
else {
mode = OB_MODE_OBJECT;
@@ -355,7 +378,7 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
- BKE_brush_gpencil_presets(bmain, ts);
+ BKE_brush_gpencil_paint_presets(bmain, ts, true);
}
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_paint->paint);
}
@@ -400,7 +423,11 @@ void GPENCIL_OT_paintmode_toggle(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
-/* Stroke Sculpt Mode Management */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Stroke Sculpt Mode Operator
+ * \{ */
static bool gpencil_sculptmode_toggle_poll(bContext *C)
{
@@ -414,6 +441,9 @@ static bool gpencil_sculptmode_toggle_poll(bContext *C)
static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
const bool back = RNA_boolean_get(op->ptr, "back");
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
@@ -436,6 +466,7 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
/* set mode */
if (gpd->flag & GP_DATA_STROKE_SCULPTMODE) {
mode = OB_MODE_SCULPT_GPENCIL;
+ BKE_brush_gpencil_sculpt_presets(bmain, ts, false);
}
else {
mode = OB_MODE_OBJECT;
@@ -450,6 +481,12 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
ob->mode = mode;
}
+ if (mode == OB_MODE_SCULPT_GPENCIL) {
+ /* be sure we have brushes */
+ BKE_paint_ensure(ts, (Paint **)&ts->gp_sculptpaint);
+ BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint);
+ }
+
/* setup other modes */
ED_gpencil_setup_modes(C, gpd, mode);
/* set cache as dirty */
@@ -468,6 +505,12 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Weight Paint Mode Operator
+ * \{ */
+
void GPENCIL_OT_sculptmode_toggle(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -504,6 +547,9 @@ static bool gpencil_weightmode_toggle_poll(bContext *C)
static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
const bool back = RNA_boolean_get(op->ptr, "back");
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
@@ -526,6 +572,7 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
/* set mode */
if (gpd->flag & GP_DATA_STROKE_WEIGHTMODE) {
mode = OB_MODE_WEIGHT_GPENCIL;
+ BKE_brush_gpencil_weight_presets(bmain, ts, false);
}
else {
mode = OB_MODE_OBJECT;
@@ -540,6 +587,12 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
ob->mode = mode;
}
+ if (mode == OB_MODE_WEIGHT_GPENCIL) {
+ /* be sure we have brushes */
+ BKE_paint_ensure(ts, (Paint **)&ts->gp_weightpaint);
+ BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint);
+ }
+
/* setup other modes */
ED_gpencil_setup_modes(C, gpd, mode);
/* set cache as dirty */
@@ -580,10 +633,117 @@ void GPENCIL_OT_weightmode_toggle(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
-/* ************************************************ */
-/* Stroke Editing Operators */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Vertex Paint Mode Operator
+ * \{ */
+
+static bool gpencil_vertexmode_toggle_poll(bContext *C)
+{
+ /* if using gpencil object, use this gpd */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ return ob->data != NULL;
+ }
+ return ED_gpencil_data_get_active(C) != NULL;
+}
+static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op)
+{
+ const bool back = RNA_boolean_get(op->ptr, "back");
+
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Main *bmain = CTX_data_main(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ bool is_object = false;
+ short mode;
+ /* if using a gpencil object, use this datablock */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ gpd = ob->data;
+ is_object = true;
+ }
-/* ************ Stroke Hide selection Toggle ************** */
+ if (gpd == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Just toggle paintmode flag... */
+ gpd->flag ^= GP_DATA_STROKE_VERTEXMODE;
+ /* set mode */
+ if (gpd->flag & GP_DATA_STROKE_VERTEXMODE) {
+ mode = OB_MODE_VERTEX_GPENCIL;
+ BKE_brush_gpencil_vertex_presets(bmain, ts, false);
+
+ /* Ensure Palette by default. */
+ BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));
+ }
+ else {
+ mode = OB_MODE_OBJECT;
+ }
+
+ if (is_object) {
+ /* try to back previous mode */
+ if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_VERTEXMODE) == 0) && (back == 1)) {
+ mode = ob->restore_mode;
+ }
+ ob->restore_mode = ob->mode;
+ ob->mode = mode;
+ }
+
+ if (mode == OB_MODE_VERTEX_GPENCIL) {
+ /* be sure we have brushes */
+ BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint);
+ BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint);
+ }
+
+ /* setup other modes */
+ ED_gpencil_setup_modes(C, gpd, mode);
+ /* set cache as dirty */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
+
+ if (is_object) {
+ WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ }
+ if (G.background == false) {
+ WM_toolsystem_update_from_context_view3d(C);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_vertexmode_toggle(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Strokes Vertex Mode Toggle";
+ ot->idname = "GPENCIL_OT_vertexmode_toggle";
+ ot->description = "Enter/Exit vertex paint mode for Grease Pencil strokes";
+
+ /* callbacks */
+ ot->exec = gpencil_vertexmode_toggle_exec;
+ ot->poll = gpencil_vertexmode_toggle_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ prop = RNA_def_boolean(
+ ot->srna, "back", 0, "Return to Previous Mode", "Return to previous mode");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Hide Selection Toggle Operator
+ * \{ */
static int gpencil_hideselect_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -622,7 +782,11 @@ void GPENCIL_OT_selection_opacity_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
}
-/* ************** Duplicate Selected Strokes **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Duplicate Selected Strokes Operator
+ * \{ */
/* Make copies of selected point segments in a selected stroke */
static void gp_duplicate_points(const bGPDstroke *gps,
@@ -659,30 +823,24 @@ static void gp_duplicate_points(const bGPDstroke *gps,
else if (i == gps->totpoints - 1) {
len = i - start_idx + 1;
}
- // printf("copying from %d to %d = %d\n", start_idx, i, len);
/* make copies of the relevant data */
if (len) {
bGPDstroke *gpsd;
/* make a stupid copy first of the entire stroke (to get the flags too) */
- gpsd = MEM_dupallocN(gps);
+ gpsd = BKE_gpencil_stroke_duplicate((bGPDstroke *)gps, false);
/* saves original layer name */
BLI_strncpy(gpsd->runtime.tmp_layerinfo, layername, sizeof(gpsd->runtime.tmp_layerinfo));
- /* initialize triangle memory - will be calculated on next redraw */
- gpsd->triangles = NULL;
- gpsd->flag |= GP_STROKE_RECALC_GEOMETRY;
- gpsd->tot_triangles = 0;
-
/* now, make a new points array, and copy of the relevant parts */
- gpsd->points = MEM_callocN(sizeof(bGPDspoint) * len, "gps stroke points copy");
+ gpsd->points = MEM_mallocN(sizeof(bGPDspoint) * len, "gps stroke points copy");
memcpy(gpsd->points, gps->points + start_idx, sizeof(bGPDspoint) * len);
gpsd->totpoints = len;
if (gps->dvert != NULL) {
- gpsd->dvert = MEM_callocN(sizeof(MDeformVert) * len, "gps stroke weights copy");
+ gpsd->dvert = MEM_mallocN(sizeof(MDeformVert) * len, "gps stroke weights copy");
memcpy(gpsd->dvert, gps->dvert + start_idx, sizeof(MDeformVert) * len);
/* Copy weights */
@@ -695,8 +853,11 @@ static void gp_duplicate_points(const bGPDstroke *gps,
}
}
+ BKE_gpencil_stroke_geometry_update(gpsd);
+
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
+
BLI_addtail(new_strokes, gpsd);
/* cleanup + reset for next */
@@ -746,17 +907,12 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
bGPDstroke *gpsd;
/* make direct copies of the stroke and its points */
- gpsd = MEM_dupallocN(gps);
+ gpsd = BKE_gpencil_stroke_duplicate(gps, true);
+
BLI_strncpy(gpsd->runtime.tmp_layerinfo, gpl->info, sizeof(gpsd->runtime.tmp_layerinfo));
- gpsd->points = MEM_dupallocN(gps->points);
- if (gps->dvert != NULL) {
- gpsd->dvert = MEM_dupallocN(gps->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps, gpsd);
- }
- /* triangle information - will be calculated on next redraw */
- gpsd->flag |= GP_STROKE_RECALC_GEOMETRY;
- gpsd->triangles = NULL;
+ /* Initialize triangle information. */
+ BKE_gpencil_stroke_geometry_update(gpsd);
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
@@ -807,7 +963,11 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ************** Extrude Selected Strokes **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Extrude Selected Strokes Operator
+ * \{ */
/* helper to copy a point to temp area */
static void copy_move_point(bGPDstroke *gps,
@@ -827,6 +987,7 @@ static void copy_move_point(bGPDstroke *gps,
pt_final->flag = pt->flag;
pt_final->uv_fac = pt->uv_fac;
pt_final->uv_rot = pt->uv_rot;
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
MDeformVert *dvert = &temp_dverts[from_idx];
@@ -864,7 +1025,7 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
pt = &gps->points[i];
if (pt->flag == GP_SPOINT_SELECT) {
/* duplicate original stroke data */
- bGPDstroke *gps_new = MEM_dupallocN(gps);
+ bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, false);
gps_new->prev = gps_new->next = NULL;
/* add new points array */
@@ -876,14 +1037,15 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
gps_new->dvert = MEM_callocN(sizeof(MDeformVert), __func__);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps_new->triangles = NULL;
- gps_new->tot_triangles = 0;
BLI_insertlinkafter(&gpf->strokes, gps, gps_new);
/* copy selected point data to new stroke */
copy_move_point(gps_new, gps->points, gps->dvert, i, 0, true);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+ BKE_gpencil_stroke_geometry_update(gps_new);
+
/* deselect orinal point */
pt->flag &= ~GP_SPOINT_SELECT;
}
@@ -926,7 +1088,6 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
copy_move_point(gps, temp_points, temp_dverts, i, i2, false);
i2++;
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* If first point, add new point at the beginning. */
if (do_first) {
@@ -951,6 +1112,9 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
pt->flag |= GP_SPOINT_SELECT;
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+
MEM_SAFE_FREE(temp_points);
MEM_SAFE_FREE(temp_dverts);
}
@@ -1024,14 +1188,18 @@ void GPENCIL_OT_extrude(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************* Copy/Paste Strokes ************************* */
-/* Grease Pencil stroke data copy/paste buffer:
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy/Paste Strokes Utilities
+ *
+ * Grease Pencil stroke data copy/paste buffer:
* - The copy operation collects all segments of selected strokes,
* dumping "ready to be copied" copies of the strokes into the buffer.
* - The paste operation makes a copy of those elements, and adds them
* to the active layer. This effectively flattens down the strokes
* from several different layers into a single layer.
- */
+ * \{ */
/* list of bGPDstroke instances */
/* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */
@@ -1143,8 +1311,11 @@ GHash *gp_copybuf_validate_colormap(bContext *C)
return new_colors;
}
-/* --------------------- */
-/* Copy selected strokes */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy Selected Strokes Operator
+ * \{ */
static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
{
@@ -1190,7 +1361,8 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
bGPDstroke *gpsd;
/* make direct copies of the stroke and its points */
- gpsd = MEM_dupallocN(gps);
+ gpsd = BKE_gpencil_stroke_duplicate(gps, false);
+
/* saves original layer name */
BLI_strncpy(gpsd->runtime.tmp_layerinfo, gpl->info, sizeof(gpsd->runtime.tmp_layerinfo));
gpsd->points = MEM_dupallocN(gps->points);
@@ -1199,10 +1371,8 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
BKE_gpencil_stroke_weights_duplicate(gps, gpsd);
}
- /* triangles cache - will be recalculated on next redraw */
- gpsd->flag |= GP_STROKE_RECALC_GEOMETRY;
- gpsd->tot_triangles = 0;
- gpsd->triangles = NULL;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gpsd);
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
@@ -1221,9 +1391,9 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
if (gp_strokes_copypastebuf.first) {
gp_strokes_copypastebuf_colors = BLI_ghash_int_new("GPencil CopyBuf Colors");
GHash *ma_to_name = gp_strokes_copypastebuf_colors_material_to_name_create(bmain);
- for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gp_strokes_copypastebuf) {
if (ED_gpencil_stroke_can_use(C, gps)) {
- Material *ma = give_current_material(ob, gps->mat_nr + 1);
+ Material *ma = BKE_object_material_get(ob, gps->mat_nr + 1);
/* Avoid default material. */
if (ma == NULL) {
continue;
@@ -1262,11 +1432,18 @@ void GPENCIL_OT_copy(wmOperatorType *ot)
// ot->flag = OPTYPE_REGISTER;
}
-/* --------------------- */
-/* Paste selected strokes */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Paste Selected Strokes Operator
+ * \{ */
static bool gp_strokes_paste_poll(bContext *C)
{
+ ScrArea *area = CTX_wm_area(C);
+ if (!((area != NULL) && (area->spacetype == SPACE_VIEW3D))) {
+ return false;
+ }
/* 1) Must have GP datablock to paste to
* - We don't need to have an active layer though, as that can easily get added
* - If the active layer is locked, we can't paste there,
@@ -1285,20 +1462,17 @@ typedef enum eGP_PasteMode {
static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); /* only use active for copy merge */
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); /* only use active for copy merge */
Scene *scene = CTX_data_scene(C);
bGPDframe *gpf;
eGP_PasteMode type = RNA_enum_get(op->ptr, "type");
+ const bool on_back = RNA_boolean_get(op->ptr, "paste_back");
GHash *new_colors;
- /* check for various error conditions */
- if (gpd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
- return OPERATOR_CANCELLED;
- }
- else if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
+ /* Check for various error conditions. */
+ if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
return OPERATOR_CANCELLED;
}
@@ -1312,7 +1486,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
/* no active layer - let's just create one */
gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
}
- else if ((gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_TO_ACTIVE)) {
+ else if ((BKE_gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_TO_ACTIVE)) {
BKE_report(
op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked");
return OPERATOR_CANCELLED;
@@ -1330,17 +1504,6 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
}
if (ok == false) {
- /* XXX: this check is not 100% accurate
- * (i.e. image editor is incompatible with normal 2D strokes),
- * but should be enough to give users a good idea of what's going on.
- */
- if (CTX_wm_area(C)->spacetype == SPACE_VIEW3D) {
- BKE_report(op->reports, RPT_ERROR, "Cannot paste 2D strokes in 3D View");
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Cannot paste 3D strokes in 2D editors");
- }
-
return OPERATOR_CANCELLED;
}
}
@@ -1362,14 +1525,15 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
new_colors = gp_copybuf_validate_colormap(C);
/* Copy over the strokes from the buffer (and adjust the colors) */
- for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ bGPDstroke *gps_init = (!on_back) ? gp_strokes_copypastebuf.first : gp_strokes_copypastebuf.last;
+ for (bGPDstroke *gps = gps_init; gps; gps = (!on_back) ? gps->next : gps->prev) {
if (ED_gpencil_stroke_can_use(C, gps)) {
/* Need to verify if layer exists */
if (type != GP_COPY_TO_ACTIVE) {
gpl = BLI_findstring(&gpd->layers, gps->runtime.tmp_layerinfo, offsetof(bGPDlayer, info));
if (gpl == NULL) {
/* no layer - use active (only if layer deleted before paste) */
- gpl = CTX_data_active_gpencil_layer(C);
+ gpl = BKE_gpencil_layer_active_get(gpd);
}
}
@@ -1378,26 +1542,26 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
* we are obliged to add a new frame if one
* doesn't exist already
*/
- gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
if (gpf) {
/* Create new stroke */
- bGPDstroke *new_stroke = MEM_dupallocN(gps);
+ bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, true);
new_stroke->runtime.tmp_layerinfo[0] = '\0';
+ new_stroke->next = new_stroke->prev = NULL;
- new_stroke->points = MEM_dupallocN(gps->points);
- if (gps->dvert != NULL) {
- new_stroke->dvert = MEM_dupallocN(gps->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps, new_stroke);
- }
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
- new_stroke->triangles = NULL;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
- new_stroke->next = new_stroke->prev = NULL;
- BLI_addtail(&gpf->strokes, new_stroke);
+ if (on_back) {
+ BLI_addhead(&gpf->strokes, new_stroke);
+ }
+ else {
+ BLI_addtail(&gpf->strokes, new_stroke);
+ }
/* Remap material */
Material *ma = BLI_ghash_lookup(new_colors, POINTER_FROM_INT(new_stroke->mat_nr));
- new_stroke->mat_nr = BKE_gpencil_object_material_get_index(ob, ma);
+ new_stroke->mat_nr = BKE_gpencil_object_material_index_get(ob, ma);
CLAMP_MIN(new_stroke->mat_nr, 0);
}
}
@@ -1415,6 +1579,8 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_paste(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
static const EnumPropertyItem copy_type[] = {
{GP_COPY_TO_ACTIVE, "ACTIVE", 0, "Paste to Active", ""},
{GP_COPY_BY_LAYER, "LAYER", 0, "Paste by Layer", ""},
@@ -1435,13 +1601,22 @@ void GPENCIL_OT_paste(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", copy_type, GP_COPY_TO_ACTIVE, "Type", "");
+
+ prop = RNA_def_boolean(
+ ot->srna, "paste_back", 0, "Paste on Back", "Add pasted strokes behind all strokes");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ******************* Move To Layer ****************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Move To Layer Operator
+ * \{ */
static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
Scene *scene = CTX_data_scene(C);
bGPDlayer *target_layer = NULL;
ListBase strokes = {NULL, NULL};
@@ -1459,7 +1634,13 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
}
/* Try to get layer */
- target_layer = BLI_findlink(&gpd->layers, layer_num);
+ if (layer_num > -1) {
+ target_layer = BLI_findlink(&gpd->layers, layer_num);
+ }
+ else {
+ /* Create a new layer. */
+ target_layer = BKE_gpencil_layer_addnew(gpd, "GP_Layer", true);
+ }
if (target_layer == NULL) {
/* back autolock status */
@@ -1476,7 +1657,6 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
*/
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps, *gpsn;
/* skip if no frame with strokes, or if this is the layer we're moving strokes to */
if ((gpl == target_layer) || (gpf == NULL)) {
@@ -1484,14 +1664,18 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
}
/* make copies of selected strokes, and deselect these once we're done */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
+ /* Check if the color is editable. */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+
/* TODO: Don't just move entire strokes - instead, only copy the selected portions... */
if (gps->flag & GP_STROKE_SELECT) {
BLI_remlink(&gpf->strokes, gps);
@@ -1508,7 +1692,7 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
/* Paste them all in one go */
if (strokes.first) {
- bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, CFRA, GP_GETFRAME_ADD_NEW);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(target_layer, CFRA, GP_GETFRAME_ADD_NEW);
BLI_movelisttolist(&gpf->strokes, &strokes);
BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL));
@@ -1542,30 +1726,16 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* GPencil layer to use. */
- ot->prop = RNA_def_int(ot->srna, "layer", 0, 0, INT_MAX, "Grease Pencil Layer", "", 0, INT_MAX);
+ ot->prop = RNA_def_int(
+ ot->srna, "layer", 0, -1, INT_MAX, "Grease Pencil Layer", "", -1, INT_MAX);
RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
-/* ********************* Add Blank Frame *************************** */
+/** \} */
-/* Basically the same as the drawing op */
-static bool UNUSED_FUNCTION(gp_blank_frame_add_poll)(bContext *C)
-{
- if (ED_operator_regionactive(C)) {
- /* check if current context can support GPencil data */
- if (ED_gpencil_data_get_pointers(C, NULL) != NULL) {
- return 1;
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Failed to find Grease Pencil data to draw into");
- }
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Active region not set");
- }
-
- return 0;
-}
+/* -------------------------------------------------------------------- */
+/** \name Add Blank Frame Operator
+ * \{ */
static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
{
@@ -1573,7 +1743,7 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
int cfra = CFRA;
- bGPDlayer *active_gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *active_gpl = BKE_gpencil_layer_active_get(gpd);
const bool all_layers = RNA_boolean_get(op->ptr, "all_layers");
@@ -1593,7 +1763,7 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
}
/* 1) Check for an existing frame on the current frame */
- bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, cfra);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_find(gpl, cfra);
if (gpf) {
/* Shunt all frames after (and including) the existing one later by 1-frame */
for (; gpf; gpf = gpf->next) {
@@ -1602,7 +1772,7 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
}
/* 2) Now add a new frame, with nothing in it */
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_ADD_NEW);
+ gpl->actframe = BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_ADD_NEW);
}
CTX_DATA_END;
@@ -1639,12 +1809,16 @@ void GPENCIL_OT_blank_frame_add(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ******************* Delete Active Frame ************************ */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Active Frame Operator
+ * \{ */
static bool gp_actframe_delete_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
/* only if there's an active layer with an active frame */
return (gpl && gpl->actframe);
@@ -1653,7 +1827,7 @@ static bool gp_actframe_delete_poll(bContext *C)
static bool gp_annotation_actframe_delete_poll(bContext *C)
{
bGPdata *gpd = ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
/* only if there's an active layer with an active frame */
return (gpl && gpl->actframe);
@@ -1667,11 +1841,11 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
/* if there's no existing Grease-Pencil data there, add some */
if (gpd == NULL) {
@@ -1684,7 +1858,7 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
}
/* delete it... */
- BKE_gpencil_layer_delframe(gpl, gpf);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -1720,7 +1894,12 @@ void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot)
ot->exec = gp_actframe_delete_exec;
ot->poll = gp_annotation_actframe_delete_poll;
}
-/* **************** Delete All Active Frames ****************** */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete All Active Frames
+ * \{ */
static bool gp_actframe_delete_all_poll(bContext *C)
{
@@ -1741,14 +1920,14 @@ static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
/* try to get the "active" frame - but only if it actually occurs on this frame */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
if (gpf == NULL) {
continue;
}
/* delete it... */
- BKE_gpencil_layer_delframe(gpl, gpf);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
/* we successfully modified something */
success = true;
@@ -1781,7 +1960,11 @@ void GPENCIL_OT_active_frames_delete_all(wmOperatorType *ot)
ot->poll = gp_actframe_delete_all_poll;
}
-/* ******************* Delete Operator ************************ */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete/Dissolve Utilities
+ * \{ */
typedef enum eGP_DeleteMode {
/* delete selected stroke points */
@@ -1801,8 +1984,6 @@ typedef enum eGP_DissolveMode {
GP_DISSOLVE_UNSELECT = 2,
} eGP_DissolveMode;
-/* ----------------------------------- */
-
/* Delete selected strokes */
static int gp_delete_selected_strokes(bContext *C)
{
@@ -1815,15 +1996,13 @@ static int gp_delete_selected_strokes(bContext *C)
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
- bGPDstroke *gps, *gpsn;
if (gpf == NULL) {
continue;
}
/* simply delete strokes which are selected */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -2054,9 +2233,8 @@ static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode)
gps->dvert = new_dvert;
gps->totpoints = tot;
- /* triangles cache needs to be recalculated */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
/* deselect the stroke, since none of its selected points will still be selected */
gps->flag &= ~GP_STROKE_SELECT;
@@ -2098,7 +2276,7 @@ static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDst
const int totpoints = gps_first->totpoints + gps_last->totpoints;
/* create new stroke */
- bGPDstroke *join_stroke = MEM_dupallocN(gps_first);
+ bGPDstroke *join_stroke = BKE_gpencil_stroke_duplicate(gps_first, false);
join_stroke->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__);
join_stroke->totpoints = totpoints;
@@ -2126,6 +2304,7 @@ static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDst
pt_final->strength = pt->strength;
pt_final->time = delta;
pt_final->flag = pt->flag;
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
/* retiming with fixed time interval (we cannot determine real time) */
delta += 0.01f;
@@ -2164,6 +2343,8 @@ static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDst
/* add new stroke at head */
BLI_addhead(&gpf->strokes, join_stroke);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(join_stroke);
/* remove first stroke */
BLI_remlink(&gpf->strokes, gps_first);
@@ -2240,18 +2421,14 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf,
/* Create each new stroke... */
for (idx = 0; idx < num_islands; idx++) {
tGPDeleteIsland *island = &islands[idx];
- new_stroke = MEM_dupallocN(gps);
+ new_stroke = BKE_gpencil_stroke_duplicate(gps, false);
/* if cyclic and first stroke, save to join later */
if ((is_cyclic) && (gps_first == NULL)) {
gps_first = new_stroke;
}
- /* initialize triangle memory - to be calculated on next redraw */
- new_stroke->triangles = NULL;
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
new_stroke->flag &= ~GP_STROKE_CYCLIC;
- new_stroke->tot_triangles = 0;
/* Compute new buffer size (+ 1 needed as the endpoint index is "inclusive") */
new_stroke->totpoints = island->end_idx - island->start_idx + 1;
@@ -2314,6 +2491,9 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf,
BKE_gpencil_free_stroke(new_stroke);
}
else {
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
+
if (next_stroke) {
BLI_insertlinkbefore(&gpf->strokes, next_stroke, new_stroke);
}
@@ -2349,15 +2529,13 @@ static int gp_delete_selected_points(bContext *C)
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
- bGPDstroke *gps, *gpsn;
if (gpf == NULL) {
continue;
}
/* simply delete strokes which are selected */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -2373,7 +2551,7 @@ static int gp_delete_selected_points(bContext *C)
gps->flag &= ~GP_STROKE_SELECT;
/* delete unwanted points by splitting stroke into several smaller ones */
- gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_SELECT, false, 0);
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
changed = true;
}
@@ -2399,7 +2577,11 @@ int gp_delete_selected_point_wrap(bContext *C)
return gp_delete_selected_points(C);
}
-/* ----------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Operator
+ * \{ */
static int gp_delete_exec(bContext *C, wmOperator *op)
{
@@ -2458,6 +2640,12 @@ void GPENCIL_OT_delete(wmOperatorType *ot)
"Method used for deleting Grease Pencil data");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Dissolve Operator
+ * \{ */
+
static int gp_dissolve_exec(bContext *C, wmOperator *op)
{
eGP_DissolveMode mode = RNA_enum_get(op->ptr, "type");
@@ -2500,7 +2688,11 @@ void GPENCIL_OT_dissolve(wmOperatorType *ot)
"Method used for dissolving Stroke points");
}
-/* ****************** Snapping - Strokes <-> Cursor ************************ */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snapping Selection to Grid Operator
+ * \{ */
/* Poll callback for snap operators */
/* NOTE: For now, we only allow these in the 3D view, as other editors do not
@@ -2508,14 +2700,13 @@ void GPENCIL_OT_dissolve(wmOperatorType *ot)
*/
static bool gp_snap_poll(bContext *C)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
+ Object *ob = CTX_data_active_object(C);
- return (gpd != NULL) && ((sa != NULL) && (sa->spacetype == SPACE_VIEW3D));
+ return (ob != NULL) && (ob->type == OB_GPENCIL) &&
+ ((area != NULL) && (area->spacetype == SPACE_VIEW3D));
}
-/* --------------------------------- */
-
static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
@@ -2526,16 +2717,16 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
Object *obact = CTX_data_active_object(C);
const float gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
float diff_mat[4][4];
/* calculate difference matrix object */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDspoint *pt;
int i;
@@ -2562,7 +2753,7 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
/* return data */
copy_v3_v3(&pt->x, fpt);
- gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
+ gp_apply_parent_point(depsgraph, obact, gpl, pt);
}
}
}
@@ -2590,7 +2781,11 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snapping Selection to Cursor Operator
+ * \{ */
static int gp_snap_to_cursor(bContext *C, wmOperator *op)
{
@@ -2603,16 +2798,16 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
const float *cursor_global = scene->cursor.location;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
float diff_mat[4][4];
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDspoint *pt;
int i;
@@ -2646,7 +2841,7 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
copy_v3_v3(&pt->x, cursor_global);
- gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
+ gp_apply_parent_point(depsgraph, obact, gpl, pt);
}
}
}
@@ -2682,16 +2877,21 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot)
"Offset the entire stroke instead of selected points only");
}
-/* ------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snapping Cursor to Selection Operator
+ * \{ */
static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
{
- bGPdata *gpd = ED_gpencil_data_get_active(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Object *obact = CTX_data_active_object(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, obact);
+ bGPdata *gpd = (bGPdata *)ob_eval->data;
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Object *obact = CTX_data_active_object(C);
float *cursor = scene->cursor.location;
float centroid[3] = {0.0f};
@@ -2701,16 +2901,16 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
INIT_MINMAX(min, max);
/* calculate midpoints from selected points */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
float diff_mat[4][4];
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDspoint *pt;
int i;
@@ -2772,12 +2972,16 @@ void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************* Apply layer thickness change to strokes ************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Apply Layer Thickness Change to Strokes Operator
+ * \{ */
static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
/* sanity checks */
if (ELEM(NULL, gpd, gpl, gpl->frames.first)) {
@@ -2785,8 +2989,8 @@ static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op))
}
/* loop all strokes */
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* Apply thickness */
if ((gps->thickness == 0) && (gpl->line_change == 0)) {
gps->thickness = gpl->thickness;
@@ -2819,7 +3023,11 @@ void GPENCIL_OT_stroke_apply_thickness(wmOperatorType *ot)
ot->poll = gp_active_layer_poll;
}
-/* ******************* Close Strokes ************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Toggle Cyclic Operator
+ * \{ */
enum {
GP_STROKE_CYCLIC_CLOSE = 1,
@@ -2853,15 +3061,15 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
}
for (gps = gpf->strokes.first; gps; gps = gps->next) {
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(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)) {
+ if (!gp_style || (gp_style->flag & GP_MATERIAL_HIDE) ||
+ (gp_style->flag & GP_MATERIAL_LOCKED)) {
continue;
}
@@ -2885,7 +3093,7 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
/* Create new geometry. */
if ((gps->flag & GP_STROKE_CYCLIC) && (geometry)) {
- BKE_gpencil_close_stroke(gps);
+ BKE_gpencil_stroke_close(gps);
}
}
@@ -2939,7 +3147,11 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ******************* Flat Stroke Caps ************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Toggle Flat Caps Operator
+ * \{ */
enum {
GP_STROKE_CAPS_TOGGLE_BOTH = 0,
@@ -2967,15 +3179,15 @@ static int gp_stroke_caps_set_exec(bContext *C, wmOperator *op)
}
for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(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)) {
+ if (!gp_style || (gp_style->flag & GP_MATERIAL_HIDE) ||
+ (gp_style->flag & GP_MATERIAL_LOCKED)) {
continue;
}
@@ -3035,7 +3247,11 @@ void GPENCIL_OT_stroke_caps_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", toggle_type, GP_STROKE_CAPS_TOGGLE_BOTH, "Type", "");
}
-/* ******************* Stroke join ************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Join Operator
+ * \{ */
/* Helper: flip stroke */
static void gpencil_flip_stroke(bGPDstroke *gps)
@@ -3055,6 +3271,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
pt.pressure = point->pressure;
pt.strength = point->strength;
pt.time = point->time;
+ copy_v4_v4(pt.vert_color, point->vert_color);
/* replace first point with last point */
point2 = &gps->points[end];
@@ -3065,6 +3282,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
point->pressure = point2->pressure;
point->strength = point2->strength;
point->time = point2->time;
+ copy_v4_v4(point->vert_color, point2->vert_color);
/* replace last point with first saved before */
point = &gps->points[end];
@@ -3075,6 +3293,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
point->pressure = pt.pressure;
point->strength = pt.strength;
point->time = pt.time;
+ copy_v4_v4(point->vert_color, pt.vert_color);
end--;
}
@@ -3082,8 +3301,8 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
/* Helper: copy point between strokes */
static void gpencil_stroke_copy_point(bGPDstroke *gps,
+ MDeformVert *dvert,
bGPDspoint *point,
- int idx,
const float delta[3],
float pressure,
float strength,
@@ -3095,6 +3314,13 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps,
if (gps->dvert != NULL) {
gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1));
}
+ else {
+ /* If destination has weight add weight to origin. */
+ if (dvert != NULL) {
+ gps->dvert = MEM_callocN(sizeof(MDeformVert) * (gps->totpoints + 1), __func__);
+ }
+ }
+
gps->totpoints++;
newpoint = &gps->points[gps->totpoints - 1];
@@ -3105,13 +3331,19 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps,
newpoint->pressure = pressure;
newpoint->strength = strength;
newpoint->time = point->time + deltatime;
+ copy_v4_v4(newpoint->vert_color, point->vert_color);
if (gps->dvert != NULL) {
- MDeformVert *dvert = &gps->dvert[idx];
MDeformVert *newdvert = &gps->dvert[gps->totpoints - 1];
- newdvert->totweight = dvert->totweight;
- newdvert->dw = MEM_dupallocN(dvert->dw);
+ if (dvert != NULL) {
+ newdvert->totweight = dvert->totweight;
+ newdvert->dw = MEM_dupallocN(dvert->dw);
+ }
+ else {
+ newdvert->totweight = 0;
+ newdvert->dw = NULL;
+ }
}
}
@@ -3136,9 +3368,9 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a,
}
/* define start and end points of each stroke */
- float sa[3], sb[3], ea[3], eb[3];
+ float area[3], sb[3], ea[3], eb[3];
pt = &gps_a->points[0];
- copy_v3_v3(sa, &pt->x);
+ copy_v3_v3(area, &pt->x);
pt = &gps_a->points[gps_a->totpoints - 1];
copy_v3_v3(ea, &pt->x);
@@ -3162,24 +3394,25 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a,
/* 1st: add one tail point to start invisible area */
point = gps_a->points[gps_a->totpoints - 1];
deltatime = point.time;
- gpencil_stroke_copy_point(gps_a, &point, gps_a->totpoints - 1, delta, 0.0f, 0.0f, 0.0f);
+
+ gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, 0.0f);
/* 2nd: add one head point to finish invisible area */
point = gps_b->points[0];
- gpencil_stroke_copy_point(gps_a, &point, 0, delta, 0.0f, 0.0f, deltatime);
+ gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, deltatime);
}
/* 3rd: add all points */
for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) {
- gpencil_stroke_copy_point(gps_a, pt, i, delta, pt->pressure, pt->strength, deltatime);
+ MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : NULL;
+ gpencil_stroke_copy_point(gps_a, dvert, pt, delta, pt->pressure, pt->strength, deltatime);
}
}
static int gp_stroke_join_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *activegpl = BKE_gpencil_layer_getactive(gpd);
- bGPDstroke *gps, *gpsn;
+ bGPDlayer *activegpl = BKE_gpencil_layer_active_get(gpd);
Object *ob = CTX_data_active_object(C);
bGPDframe *gpf_a = NULL;
@@ -3209,8 +3442,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
continue;
}
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -3235,15 +3467,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
/* create a new stroke if was not created before (only created if something to join) */
if (new_stroke == NULL) {
- new_stroke = MEM_dupallocN(stroke_a);
- new_stroke->points = MEM_dupallocN(stroke_a->points);
- if (stroke_a->dvert != NULL) {
- new_stroke->dvert = MEM_dupallocN(stroke_a->dvert);
- BKE_gpencil_stroke_weights_duplicate(stroke_a, new_stroke);
- }
- new_stroke->triangles = NULL;
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
+ new_stroke = BKE_gpencil_stroke_duplicate(stroke_a, true);
/* if new, set current color */
if (type == GP_STROKE_JOINCOPY) {
@@ -3257,6 +3481,9 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
/* if join only, delete old strokes */
if (type == GP_STROKE_JOIN) {
if (stroke_a) {
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
+
BLI_insertlinkbefore(&gpf_a->strokes, stroke_a, new_stroke);
BLI_remlink(&gpf->strokes, stroke_a);
BKE_gpencil_free_stroke(stroke_a);
@@ -3281,6 +3508,8 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
if (activegpl->actframe == NULL) {
activegpl->actframe = BKE_gpencil_frame_addnew(activegpl, gpf_a->framenum);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
BLI_addtail(&activegpl->actframe->strokes, new_stroke);
}
@@ -3322,7 +3551,11 @@ void GPENCIL_OT_stroke_join(wmOperatorType *ot)
"Leave gaps between joined strokes instead of linking them");
}
-/* ******************* Stroke flip ************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Flip Operator
+ * \{ */
static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -3341,7 +3574,7 @@ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -3381,7 +3614,11 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ***************** Reproject Strokes ********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Re-project Operator
+ * \{ */
typedef enum eGP_ReprojectModes {
/* Axis */
@@ -3404,8 +3641,8 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob = CTX_data_active_object(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
SnapObjectContext *sctx = NULL;
int oldframe = (int)DEG_get_ctime(depsgraph);
@@ -3419,8 +3656,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
int cfra_prv = INT_MIN;
/* init snap context for geometry projection */
- sctx = ED_transform_snap_object_context_create_view3d(
- bmain, scene, depsgraph, 0, ar, CTX_wm_view3d(C));
+ sctx = ED_transform_snap_object_context_create_view3d(bmain, scene, 0, region, CTX_wm_view3d(C));
/* Go through each editable + selected stroke, adjusting each of its points one by one... */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
@@ -3455,7 +3691,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
GP_REPROJECT_TOP,
GP_REPROJECT_CURSOR)) {
if (mode != GP_REPROJECT_CURSOR) {
- ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin);
+ ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, origin);
}
else {
copy_v3_v3(origin, scene->cursor.location);
@@ -3490,7 +3726,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
copy_v3_v3(&pt->x, &pt2.x);
/* apply parent again */
- gp_apply_parent_point(depsgraph, ob, gpd, gpl, pt);
+ gp_apply_parent_point(depsgraph, ob, gpl, pt);
}
/* Project screen-space back to 3D space (from current perspective)
* so that all points have been treated the same way. */
@@ -3509,8 +3745,9 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
float location[3] = {0.0f, 0.0f, 0.0f};
float normal[3] = {0.0f, 0.0f, 0.0f};
- ED_view3d_win_to_ray(ar, xy, &ray_start[0], &ray_normal[0]);
+ ED_view3d_win_to_ray(region, xy, &ray_start[0], &ray_normal[0]);
if (ED_transform_snap_object_project_ray(sctx,
+ depsgraph,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
},
@@ -3596,7 +3833,48 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", "");
}
-/* ******************* Stroke subdivide ************************** */
+static int gp_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ BKE_gpencil_stroke_geometry_update(gps);
+ }
+ }
+ }
+ /* update changed data */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_recalc_geometry(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Recalculate internal geometry";
+ ot->idname = "GPENCIL_OT_recalc_geometry";
+ ot->description = "Update all internal geometry data";
+
+ /* callbacks */
+ ot->exec = gp_recalc_geometry_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Subdivide Operator
+ * \{ */
+
/* helper to smooth */
static void gp_smooth_stroke(bContext *C, wmOperator *op)
{
@@ -3623,19 +3901,19 @@ static void gp_smooth_stroke(bContext *C, wmOperator *op)
/* perform smoothing */
if (smooth_position) {
- BKE_gpencil_smooth_stroke(gps, i, factor);
+ BKE_gpencil_stroke_smooth(gps, i, factor);
}
if (smooth_strength) {
- BKE_gpencil_smooth_stroke_strength(gps, i, factor);
+ BKE_gpencil_stroke_smooth_strength(gps, i, factor);
}
if (smooth_thickness) {
/* thickness need to repeat process several times */
for (int r2 = 0; r2 < r * 20; r2++) {
- BKE_gpencil_smooth_stroke_thickness(gps, i, factor);
+ BKE_gpencil_stroke_smooth_thickness(gps, i, factor);
}
}
if (smooth_uv) {
- BKE_gpencil_smooth_stroke_uv(gps, i, factor);
+ BKE_gpencil_stroke_smooth_uv(gps, i, factor);
}
}
}
@@ -3704,7 +3982,6 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* loop and interpolate */
i2 = 0;
@@ -3718,6 +3995,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
pt_final->strength = pt->strength;
pt_final->time = pt->time;
pt_final->flag = pt->flag;
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
@@ -3741,6 +4019,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->flag |= GP_SPOINT_SELECT;
@@ -3774,9 +4053,8 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
MEM_SAFE_FREE(temp_dverts);
}
- /* triangles cache needs to be recalculated */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
@@ -3844,7 +4122,7 @@ static int gp_stroke_simplify_exec(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
/* simplify stroke using Ramer-Douglas-Peucker algorithm */
- BKE_gpencil_simplify_stroke(gps, factor);
+ BKE_gpencil_stroke_simplify_adaptive(gps, factor);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
@@ -3893,7 +4171,7 @@ static int gp_stroke_simplify_fixed_exec(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
for (int i = 0; i < steps; i++) {
- BKE_gpencil_simplify_fixed(gps);
+ BKE_gpencil_stroke_simplify_fixed(gps);
}
}
}
@@ -3943,7 +4221,7 @@ static int gp_stroke_sample_exec(bContext *C, wmOperator *op)
/* Go through each editable + selected stroke */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
- BKE_gpencil_sample_stroke(gps, length, true);
+ BKE_gpencil_stroke_sample(gps, length, true);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
@@ -3977,7 +4255,12 @@ void GPENCIL_OT_stroke_sample(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ******************* Stroke trim ************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Trim Operator
+ * \{ */
+
static int gp_stroke_trim_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
@@ -3995,14 +4278,12 @@ static int gp_stroke_trim_exec(bContext *C, wmOperator *UNUSED(op))
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
- bGPDstroke *gps, *gpsn;
if (gpf == NULL) {
continue;
}
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -4010,7 +4291,7 @@ static int gp_stroke_trim_exec(bContext *C, wmOperator *UNUSED(op))
}
if (gps->flag & GP_STROKE_SELECT) {
- BKE_gpencil_trim_stroke(gps);
+ BKE_gpencil_stroke_trim(gps);
}
}
/* if not multiedit, exit loop*/
@@ -4044,7 +4325,12 @@ void GPENCIL_OT_stroke_trim(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ***************** Separate Strokes ********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Separate Operator
+ * \{ */
+
typedef enum eGP_SeparateModes {
/* Points */
GP_SEPARATE_POINT = 0,
@@ -4060,7 +4346,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base_old = CTX_data_active_base(C);
+ Base *base_prev = CTX_data_active_base(C);
bGPdata *gpd_src = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
@@ -4086,8 +4372,11 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_src);
- /* create a new object */
- base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, 0);
+ /* Create a new object. */
+ /* Take into account user preferences for duplicating actions. */
+ short dupflag = (U.dupflag & USER_DUP_ACT);
+
+ base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_prev, dupflag);
ob_dst = base_new->object;
ob_dst->mode = OB_MODE_OBJECT;
/* create new grease pencil datablock */
@@ -4102,7 +4391,6 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
- bGPDstroke *gps, *gpsn;
if (gpf == NULL) {
continue;
@@ -4110,8 +4398,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
gpf_dst = NULL;
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -4121,7 +4408,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
continue;
}
- /* separate selected strokes */
+ /* Separate selected strokes. */
if (gps->flag & GP_STROKE_SELECT) {
/* add layer if not created before */
if (gpl_dst == NULL) {
@@ -4130,20 +4417,20 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
/* add frame if not created before */
if (gpf_dst == NULL) {
- gpf_dst = BKE_gpencil_layer_getframe(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
+ gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
}
/* add duplicate materials */
/* XXX same material can be in multiple slots. */
- ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
+ ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
/* selected points mode */
if (mode == GP_SEPARATE_POINT) {
/* make copy of source stroke */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps, true);
/* Reassign material. */
gps_dst->mat_nr = idx;
@@ -4160,7 +4447,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
gp_stroke_delete_tagged_points(gpf_dst, gps_dst, NULL, GP_SPOINT_SELECT, false, 0);
/* delete selected points from origin stroke */
- gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_SELECT, false, 0);
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
}
/* selected strokes mode */
else if (mode == GP_SEPARATE_STROKE) {
@@ -4191,10 +4478,10 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
if (gpl) {
/* try to set a new active layer in source datablock */
if (gpl->prev) {
- BKE_gpencil_layer_setactive(gpd_src, gpl->prev);
+ BKE_gpencil_layer_active_set(gpd_src, gpl->prev);
}
else if (gpl->next) {
- BKE_gpencil_layer_setactive(gpd_src, gpl->next);
+ BKE_gpencil_layer_active_set(gpd_src, gpl->next);
}
/* unlink from source datablock */
BLI_remlink(&gpd_src->layers, gpl);
@@ -4203,25 +4490,34 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
BLI_addtail(&gpd_dst->layers, gpl);
/* add duplicate materials */
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
- ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
+ ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
}
}
}
}
+ /* Ensure destination object has one active layer. */
+ if (gpd_dst->layers.first != NULL) {
+ if (BKE_gpencil_layer_active_get(gpd_dst) == NULL) {
+ BKE_gpencil_layer_active_set(gpd_dst, gpd_dst->layers.first);
+ }
+ }
+
DEG_id_tag_update(&gpd_src->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
DEG_id_tag_update(&gpd_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL);
+ ED_outliner_select_sync_from_object_tag(C);
return OPERATOR_FINISHED;
}
@@ -4252,7 +4548,12 @@ void GPENCIL_OT_stroke_separate(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "mode", separate_type, GP_SEPARATE_POINT, "Mode", "");
}
-/* ***************** Split Strokes ********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Split Operator
+ * \{ */
+
static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_active_object(C);
@@ -4272,14 +4573,12 @@ static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op))
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
- bGPDstroke *gps, *gpsn;
if (gpf == NULL) {
continue;
}
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -4289,10 +4588,10 @@ static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op))
if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
continue;
}
- /* split selected strokes */
+ /* Split selected strokes. */
if (gps->flag & GP_STROKE_SELECT) {
/* make copy of source stroke */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps, true);
/* link to same frame */
BLI_addtail(&gpf->strokes, gps_dst);
@@ -4306,11 +4605,11 @@ static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op))
gp_stroke_delete_tagged_points(gpf, gps_dst, NULL, GP_SPOINT_SELECT, true, 0);
/* delete selected points from origin stroke */
- gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_SELECT, false, 0);
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
}
}
/* select again tagged points */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDspoint *ptn = gps->points;
for (int i2 = 0; i2 < gps->totpoints; i2++, ptn++) {
if (ptn->flag & GP_SPOINT_TAG) {
@@ -4351,6 +4650,12 @@ void GPENCIL_OT_stroke_split(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Smooth Operator
+ * \{ */
+
static int gp_stroke_smooth_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
@@ -4401,11 +4706,17 @@ void GPENCIL_OT_stroke_smooth(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "smooth_uv", false, "UV", "");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Cutter Operator
+ * \{ */
+
/* smart stroke cutter for trimming stroke ends */
struct GP_SelectLassoUserData {
rcti rect;
- const int (*mcords)[2];
- int mcords_len;
+ const int (*mcoords)[2];
+ int mcoords_len;
};
static bool gpencil_test_lasso(bGPDstroke *gps,
@@ -4421,7 +4732,7 @@ static bool gpencil_test_lasso(bGPDstroke *gps,
gp_point_to_xy(gsc, gps, &pt2, &x0, &y0);
/* test if in lasso */
return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0) &&
- BLI_lasso_is_point_inside(data->mcords, data->mcords_len, x0, y0, INT_MAX));
+ BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, x0, y0, INT_MAX));
}
typedef bool (*GPencilTestFn)(bGPDstroke *gps,
@@ -4484,7 +4795,7 @@ static int gpencil_cutter_lasso_select(bContext *C,
void *user_data)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
ToolSettings *ts = CTX_data_tool_settings(C);
const float scale = ts->gp_sculpt.isect_threshold;
@@ -4495,7 +4806,7 @@ static int gpencil_cutter_lasso_select(bContext *C,
bool changed = false;
/* sanity checks */
- if (sa == NULL) {
+ if (area == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active area");
return OPERATOR_CANCELLED;
}
@@ -4550,8 +4861,7 @@ static int gpencil_cutter_lasso_select(bContext *C,
GP_EDITABLE_STROKES_END(gpstroke_iter);
/* dissolve selected points */
- bGPDstroke *gpsn;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->flag & GP_LAYER_LOCKED) {
continue;
}
@@ -4560,8 +4870,7 @@ static int gpencil_cutter_lasso_select(bContext *C,
if (gpf == NULL) {
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
gpencil_cutter_dissolve(gpl, gps);
}
@@ -4593,27 +4902,27 @@ static bool gpencil_cutter_poll(bContext *C)
static int gpencil_cutter_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* sanity checks */
- if (sa == NULL) {
+ if (area == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active area");
return OPERATOR_CANCELLED;
}
struct GP_SelectLassoUserData data = {0};
- data.mcords = WM_gesture_lasso_path_to_array(C, op, &data.mcords_len);
+ data.mcoords = WM_gesture_lasso_path_to_array(C, op, &data.mcoords_len);
/* Sanity check. */
- if (data.mcords == NULL) {
+ if (data.mcoords == NULL) {
return OPERATOR_PASS_THROUGH;
}
/* Compute boundbox of lasso (for faster testing later). */
- BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len);
+ BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len);
gpencil_cutter_lasso_select(C, op, gpencil_test_lasso, &data);
- MEM_freeN((void *)data.mcords);
+ MEM_freeN((void *)data.mcoords);
return OPERATOR_FINISHED;
}
@@ -4646,11 +4955,11 @@ bool ED_object_gpencil_exit(struct Main *bmain, Object *ob)
bGPdata *gpd = (bGPdata *)ob->data;
gpd->flag &= ~(GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE | GP_DATA_STROKE_SCULPTMODE |
- GP_DATA_STROKE_WEIGHTMODE);
+ GP_DATA_STROKE_WEIGHTMODE | GP_DATA_STROKE_VERTEXMODE);
ob->restore_mode = ob->mode;
ob->mode &= ~(OB_MODE_PAINT_GPENCIL | OB_MODE_EDIT_GPENCIL | OB_MODE_SCULPT_GPENCIL |
- OB_MODE_WEIGHT_GPENCIL);
+ OB_MODE_WEIGHT_GPENCIL | OB_MODE_VERTEX_GPENCIL);
/* Inform all CoW versions that we changed the mode. */
DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
@@ -4659,7 +4968,12 @@ bool ED_object_gpencil_exit(struct Main *bmain, Object *ob)
return ok;
}
-/* ** merge by distance *** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Merge By Distance Operator
+ * \{ */
+
static bool gp_merge_by_distance_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
@@ -4671,7 +4985,7 @@ static bool gp_merge_by_distance_poll(bContext *C)
return false;
}
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return ((gpl != NULL) && (ob->mode == OB_MODE_EDIT_GPENCIL));
}
@@ -4691,7 +5005,7 @@ static int gp_merge_by_distance_exec(bContext *C, wmOperator *op)
/* Go through each editable selected stroke */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
- BKE_gpencil_merge_distance_stroke(gpf_, gps, threshold, unselected);
+ BKE_gpencil_stroke_merge_distance(gpf_, gps, threshold, unselected);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
@@ -4728,3 +5042,5 @@ void GPENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot)
ot->srna, "use_unselected", 0, "Unselected", "Use whole stroke, not only selected points");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+
+/** \} */
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 993ec15248f..d23a914fc49 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -25,10 +25,10 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_stack.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -39,16 +39,18 @@
#include "DNA_object_types.h"
#include "DNA_windowmanager_types.h"
-#include "BKE_main.h"
#include "BKE_brush.h"
+#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_image.h"
#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_image.h"
+#include "BKE_lib_id.h"
+#include "BKE_main.h"
#include "BKE_material.h"
-#include "BKE_context.h"
-#include "BKE_screen.h"
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
@@ -61,9 +63,9 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
-#include "GPU_framebuffer.h"
#include "GPU_state.h"
#include "UI_interface.h"
@@ -91,13 +93,13 @@ typedef struct tGPDfill {
/** current active gp object */
struct Object *ob;
/** area where painting originated */
- struct ScrArea *sa;
+ struct ScrArea *area;
/** region where painting originated */
struct RegionView3D *rv3d;
/** view3 where painting originated */
struct View3D *v3d;
/** region where painting originated */
- struct ARegion *ar;
+ struct ARegion *region;
/** current GP datablock */
struct bGPdata *gpd;
/** current material */
@@ -134,6 +136,9 @@ typedef struct tGPDfill {
/* scaling factor */
short fill_factor;
+ /* Frame to use. */
+ int active_cfra;
+
/** number of elements currently in cache */
short sbuffer_used;
/** temporary points */
@@ -228,7 +233,6 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
Object *ob = tgpf->ob;
bGPdata *gpd = tgpf->gpd;
- int cfra_eval = (int)DEG_get_ctime(tgpf->depsgraph);
tGPDdraw tgpw;
tgpw.rv3d = tgpf->rv3d;
@@ -237,17 +241,17 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
tgpw.gpd = gpd;
tgpw.offsx = 0;
tgpw.offsy = 0;
- tgpw.winx = tgpf->ar->winx;
- tgpw.winy = tgpf->ar->winy;
+ tgpw.winx = tgpf->region->winx;
+ tgpw.winy = tgpf->region->winy;
tgpw.dflag = 0;
tgpw.disable_fill = 1;
tgpw.dflag |= (GP_DRAWFILLS_ONLY3D | GP_DRAWFILLS_NOSTATUS);
GPU_blend(true);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* calculate parent position */
- ED_gpencil_parent_location(tgpw.depsgraph, ob, gpd, gpl, tgpw.diff_mat);
+ BKE_gpencil_parent_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat);
/* do not draw layer if hidden */
if (gpl->flag & GP_LAYER_HIDE) {
@@ -256,25 +260,25 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
/* if active layer and no keyframe, create a new one */
if (gpl == tgpf->gpl) {
- if ((gpl->actframe == NULL) || (gpl->actframe->framenum != cfra_eval)) {
- BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
+ if ((gpl->actframe == NULL) || (gpl->actframe->framenum != tgpf->active_cfra)) {
+ BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW);
}
}
/* get frame to draw */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV);
if (gpf == NULL) {
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* check if stroke can be drawn */
if ((gps->points == NULL) || (gps->totpoints < 2)) {
continue;
}
/* check if the color is visible */
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
- if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE)) {
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) {
continue;
}
@@ -291,18 +295,15 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
tgpw.onion = true;
tgpw.custonion = true;
- bool textured_stroke = (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE);
-
/* normal strokes */
- if (((tgpf->fill_draw_mode == GP_FILL_DMODE_STROKE) ||
- (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH)) &&
- !textured_stroke) {
+ if ((tgpf->fill_draw_mode == GP_FILL_DMODE_STROKE) ||
+ (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH)) {
ED_gp_draw_fill(&tgpw);
}
/* 3D Lines with basic shapes and invisible lines */
if ((tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) ||
- (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH) || textured_stroke) {
+ (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH)) {
gp_draw_basic_stroke(tgpf,
gps,
tgpw.diff_mat,
@@ -328,26 +329,26 @@ static bool gp_render_offscreen(tGPDfill *tgpf)
}
/* set temporary new size */
- tgpf->bwinx = tgpf->ar->winx;
- tgpf->bwiny = tgpf->ar->winy;
- tgpf->brect = tgpf->ar->winrct;
-
- /* resize ar */
- tgpf->ar->winrct.xmin = 0;
- tgpf->ar->winrct.ymin = 0;
- tgpf->ar->winrct.xmax = (int)tgpf->ar->winx * tgpf->fill_factor;
- tgpf->ar->winrct.ymax = (int)tgpf->ar->winy * tgpf->fill_factor;
- tgpf->ar->winx = (short)abs(tgpf->ar->winrct.xmax - tgpf->ar->winrct.xmin);
- tgpf->ar->winy = (short)abs(tgpf->ar->winrct.ymax - tgpf->ar->winrct.ymin);
+ tgpf->bwinx = tgpf->region->winx;
+ tgpf->bwiny = tgpf->region->winy;
+ tgpf->brect = tgpf->region->winrct;
+
+ /* resize region */
+ tgpf->region->winrct.xmin = 0;
+ tgpf->region->winrct.ymin = 0;
+ tgpf->region->winrct.xmax = (int)tgpf->region->winx * tgpf->fill_factor;
+ tgpf->region->winrct.ymax = (int)tgpf->region->winy * tgpf->fill_factor;
+ tgpf->region->winx = (short)abs(tgpf->region->winrct.xmax - tgpf->region->winrct.xmin);
+ tgpf->region->winy = (short)abs(tgpf->region->winrct.ymax - tgpf->region->winrct.ymin);
/* save new size */
- tgpf->sizex = (int)tgpf->ar->winx;
- tgpf->sizey = (int)tgpf->ar->winy;
+ tgpf->sizex = (int)tgpf->region->winx;
+ tgpf->sizey = (int)tgpf->region->winy;
/* adjust center */
float center[2];
- center[0] = (float)tgpf->center[0] * ((float)tgpf->ar->winx / (float)tgpf->bwinx);
- center[1] = (float)tgpf->center[1] * ((float)tgpf->ar->winy / (float)tgpf->bwiny);
+ center[0] = (float)tgpf->center[0] * ((float)tgpf->region->winx / (float)tgpf->bwinx);
+ center[1] = (float)tgpf->center[1] * ((float)tgpf->region->winy / (float)tgpf->bwiny);
round_v2i_v2fl(tgpf->center, center);
char err_out[256] = "unknown";
@@ -402,7 +403,7 @@ static bool gp_render_offscreen(tGPDfill *tgpf)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ED_view3d_update_viewmat(
- tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar, NULL, winmat, NULL, true);
+ tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->region, NULL, winmat, NULL, true);
/* set for opengl */
GPU_matrix_projection_set(tgpf->rv3d->winmat);
GPU_matrix_set(tgpf->rv3d->viewmat);
@@ -617,40 +618,38 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf)
get_pixel(ibuf, v, rgba);
- if (true) { /* Was: 'rgba' */
- /* check if no border(red) or already filled color(green) */
- if ((rgba[0] != 1.0f) && (rgba[1] != 1.0f)) {
- /* fill current pixel with green */
- set_pixel(ibuf, v, fill_col);
-
- /* add contact pixels */
- /* pixel left */
- if (v - 1 >= 0) {
- index = v - 1;
- if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_HORZ)) {
- BLI_stack_push(stack, &index);
- }
+ /* check if no border(red) or already filled color(green) */
+ if ((rgba[0] != 1.0f) && (rgba[1] != 1.0f)) {
+ /* fill current pixel with green */
+ set_pixel(ibuf, v, fill_col);
+
+ /* add contact pixels */
+ /* pixel left */
+ if (v - 1 >= 0) {
+ index = v - 1;
+ if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_HORZ)) {
+ BLI_stack_push(stack, &index);
}
- /* pixel right */
- if (v + 1 <= maxpixel) {
- index = v + 1;
- if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_HORZ)) {
- BLI_stack_push(stack, &index);
- }
+ }
+ /* pixel right */
+ if (v + 1 <= maxpixel) {
+ index = v + 1;
+ if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_HORZ)) {
+ BLI_stack_push(stack, &index);
}
- /* pixel top */
- if (v + ibuf->x <= maxpixel) {
- index = v + ibuf->x;
- if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
- BLI_stack_push(stack, &index);
- }
+ }
+ /* pixel top */
+ if (v + ibuf->x <= maxpixel) {
+ index = v + ibuf->x;
+ if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
+ BLI_stack_push(stack, &index);
}
- /* pixel bottom */
- if (v - ibuf->x >= 0) {
- index = v - ibuf->x;
- if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
- BLI_stack_push(stack, &index);
- }
+ }
+ /* pixel bottom */
+ if (v - ibuf->x >= 0) {
+ index = v - ibuf->x;
+ if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
+ BLI_stack_push(stack, &index);
}
}
}
@@ -666,31 +665,88 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf)
BLI_stack_free(stack);
}
-/* clean external border of image to avoid infinite loops */
-static void gpencil_clean_borders(tGPDfill *tgpf)
+/* Check if there are some pixel not filled with green. If no points, means nothing to fill. */
+static bool UNUSED_FUNCTION(gpencil_check_borders)(tGPDfill *tgpf)
+{
+ ImBuf *ibuf;
+ void *lock;
+ ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
+ int idx;
+ int pixel = 0;
+ float color[4];
+ bool found = false;
+
+ /* horizontal lines */
+ for (idx = 0; idx < ibuf->x; idx++) {
+ /* bottom line */
+ get_pixel(ibuf, idx, color);
+ if (color[1] != 1.0f) {
+ found = true;
+ break;
+ }
+ /* top line */
+ pixel = idx + (ibuf->x * (ibuf->y - 1));
+ get_pixel(ibuf, pixel, color);
+ if (color[1] != 1.0f) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ /* vertical lines */
+ for (idx = 0; idx < ibuf->y; idx++) {
+ /* left line */
+ get_pixel(ibuf, ibuf->x * idx, color);
+ if (color[1] != 1.0f) {
+ found = true;
+ break;
+ }
+ /* right line */
+ pixel = ibuf->x * idx + (ibuf->x - 1);
+ get_pixel(ibuf, pixel, color);
+ if (color[1] != 1.0f) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ /* release ibuf */
+ if (ibuf) {
+ BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
+ }
+
+ tgpf->ima->id.tag |= LIB_TAG_DOIT;
+
+ return found;
+}
+
+/* Set a border to create image limits. */
+static void gpencil_set_borders(tGPDfill *tgpf, const bool transparent)
{
ImBuf *ibuf;
void *lock;
- const float fill_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float fill_col[2][4] = {{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}};
ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
int idx;
int pixel = 0;
+ const int coloridx = transparent ? 0 : 1;
/* horizontal lines */
for (idx = 0; idx < ibuf->x; idx++) {
/* bottom line */
- set_pixel(ibuf, idx, fill_col);
+ set_pixel(ibuf, idx, fill_col[coloridx]);
/* top line */
pixel = idx + (ibuf->x * (ibuf->y - 1));
- set_pixel(ibuf, pixel, fill_col);
+ set_pixel(ibuf, pixel, fill_col[coloridx]);
}
/* vertical lines */
for (idx = 0; idx < ibuf->y; idx++) {
/* left line */
- set_pixel(ibuf, ibuf->x * idx, fill_col);
+ set_pixel(ibuf, ibuf->x * idx, fill_col[coloridx]);
/* right line */
pixel = ibuf->x * idx + (ibuf->x - 1);
- set_pixel(ibuf, pixel, fill_col);
+ set_pixel(ibuf, pixel, fill_col[coloridx]);
}
/* release ibuf */
@@ -930,8 +986,8 @@ static void gpencil_get_depth_array(tGPDfill *tgpf)
*/
if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) {
/* need to restore the original projection settings before packing up */
- view3d_region_operator_needs_opengl(tgpf->win, tgpf->ar);
- ED_view3d_autodist_init(tgpf->depsgraph, tgpf->ar, tgpf->v3d, 0);
+ view3d_region_operator_needs_opengl(tgpf->win, tgpf->region);
+ ED_view3d_autodist_init(tgpf->depsgraph, tgpf->region, tgpf->v3d, 0);
/* Since strokes are so fine, when using their depth we need a margin
* otherwise they might get missed. */
@@ -949,9 +1005,11 @@ static void gpencil_get_depth_array(tGPDfill *tgpf)
int mval_i[2];
round_v2i_v2fl(mval_i, &ptc->x);
- if ((ED_view3d_autodist_depth(tgpf->ar, mval_i, depth_margin, tgpf->depth_arr + i) == 0) &&
- (i && (ED_view3d_autodist_depth_seg(
- tgpf->ar, mval_i, mval_prev, depth_margin + 1, tgpf->depth_arr + i) == 0))) {
+ if ((ED_view3d_autodist_depth(tgpf->region, mval_i, depth_margin, tgpf->depth_arr + i) ==
+ 0) &&
+ (i &&
+ (ED_view3d_autodist_depth_seg(
+ tgpf->region, mval_i, mval_prev, depth_margin + 1, tgpf->depth_arr + i) == 0))) {
interp_depth = true;
}
else {
@@ -1004,8 +1062,6 @@ static void gpencil_points_from_stack(tGPDfill *tgpf)
/* create a grease pencil stroke using points in buffer */
static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
{
- const int cfra_eval = (int)DEG_get_ctime(tgpf->depsgraph);
-
ToolSettings *ts = tgpf->scene->toolsettings;
const char *align_flag = &ts->gpencil_v3d_align;
const bool is_depth = (bool)(*align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
@@ -1024,16 +1080,23 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
return;
}
- /* get frame or create a new one */
- tgpf->gpf = BKE_gpencil_layer_getframe(tgpf->gpl, cfra_eval, GP_GETFRAME_ADD_NEW);
+ /* Get frame or create a new one. */
+ tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW);
+
+ /* Set frame as selected. */
+ tgpf->gpf->flag |= GP_FRAME_SELECT;
/* create new stroke */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
gps->thickness = brush->size;
- gps->gradient_f = brush->gpencil_settings->gradient_f;
- copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s);
+ gps->fill_opacity_fac = 1.0f;
+ gps->hardeness = brush->gpencil_settings->hardeness;
+ copy_v2_v2(gps->aspect_ratio, brush->gpencil_settings->aspect_ratio);
gps->inittime = 0.0f;
+ /* Apply the vertex color to fill. */
+ ED_gpencil_fill_vertex_color_set(ts, brush, gps);
+
/* the polygon must be closed, so enabled cyclic */
gps->flag |= GP_STROKE_CYCLIC;
gps->flag |= GP_STROKE_3DSPACE;
@@ -1052,11 +1115,6 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
gps->totpoints = tgpf->sbuffer_used;
gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_used, "gp_stroke_points");
- /* initialize triangle memory to dummy data */
- gps->tot_triangles = 0;
- gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
/* add stroke to frame */
if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) || (tgpf->on_back == true)) {
BLI_addhead(&tgpf->gpf->strokes, gps);
@@ -1080,9 +1138,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
for (int i = 0; i < tgpf->sbuffer_used && point2D; i++, point2D++, pt++) {
/* convert screen-coordinates to 3D coordinates */
gp_stroke_convertcoords_tpoint(tgpf->scene,
- tgpf->ar,
+ tgpf->region,
tgpf->ob,
- tgpf->gpl,
point2D,
tgpf->depth_arr ? tgpf->depth_arr + i : NULL,
&pt->x);
@@ -1091,8 +1148,11 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
pt->strength = 1.0f;
pt->time = 0.0f;
+ /* Apply the vertex color to point. */
+ ED_gpencil_point_vertex_color_set(ts, brush, pt, NULL);
+
if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr);
if (dw) {
dw->weight = ts->vgroup_weight;
}
@@ -1113,7 +1173,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
float smoothfac = 1.0f;
for (int r = 0; r < 1; r++) {
for (int i = 0; i < gps->totpoints; i++) {
- BKE_gpencil_smooth_stroke(gps, i, smoothfac - reduce);
+ BKE_gpencil_stroke_smooth(gps, i, smoothfac - reduce);
}
reduce += 0.25f; // reduce the factor
}
@@ -1122,7 +1182,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
if ((tgpf->lock_axis > GP_LOCKAXIS_VIEW) &&
((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0)) {
float origin[3];
- ED_gp_get_drawing_reference(tgpf->scene, tgpf->ob, tgpf->gpl, ts->gpencil_v3d_align, origin);
+ ED_gpencil_drawing_reference_get(tgpf->scene, tgpf->ob, ts->gpencil_v3d_align, origin);
ED_gp_project_stroke_to_plane(
tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin, tgpf->lock_axis - 1);
}
@@ -1130,7 +1190,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
/* if parented change position relative to parent object */
for (int a = 0; a < tgpf->sbuffer_used; a++) {
pt = &gps->points[a];
- gp_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpd, tgpf->gpl, pt);
+ gp_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpl, pt);
}
/* if camera view, reproject flat to view to avoid perspective effect */
@@ -1140,14 +1200,17 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
/* simplify stroke */
for (int b = 0; b < tgpf->fill_simplylvl; b++) {
- BKE_gpencil_simplify_fixed(gps);
+ BKE_gpencil_stroke_simplify_fixed(gps);
}
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* ----------------------- */
/* Drawing */
/* Helper: Draw status message while the user is running the operator */
-static void gpencil_fill_status_indicators(bContext *C, tGPDfill *UNUSED(tgpf))
+static void gpencil_fill_status_indicators(bContext *C)
{
const char *status_str = TIP_("Fill: ESC/RMB cancel, LMB Fill, Shift Draw on Back");
ED_workspace_status_text(C, status_str);
@@ -1164,12 +1227,12 @@ static void gpencil_draw_boundary_lines(const bContext *UNUSED(C), tGPDfill *tgp
}
/* Drawing callback for modal operator in 3d mode */
-static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(ar), void *arg)
+static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(region), void *arg)
{
tGPDfill *tgpf = (tGPDfill *)arg;
/* draw only in the region that originated operator. This is required for multiwindow */
- ARegion *ar = CTX_wm_region(C);
- if (ar != tgpf->ar) {
+ ARegion *region = CTX_wm_region(C);
+ if (region != tgpf->region) {
return;
}
@@ -1182,8 +1245,8 @@ static bool gpencil_fill_poll(bContext *C)
Object *obact = CTX_data_active_object(C);
if (ED_operator_regionactive(C)) {
- ScrArea *sa = CTX_wm_area(C);
- if (sa->spacetype == SPACE_VIEW3D) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area->spacetype == SPACE_VIEW3D) {
if ((obact == NULL) || (obact->type != OB_GPENCIL) ||
(obact->mode != OB_MODE_PAINT_GPENCIL)) {
return false;
@@ -1217,19 +1280,20 @@ static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op))
tgpf->bmain = CTX_data_main(C);
tgpf->scene = CTX_data_scene(C);
tgpf->ob = CTX_data_active_object(C);
- tgpf->sa = CTX_wm_area(C);
- tgpf->ar = CTX_wm_region(C);
- tgpf->rv3d = tgpf->ar->regiondata;
- tgpf->v3d = tgpf->sa->spacedata.first;
+ tgpf->area = CTX_wm_area(C);
+ tgpf->region = CTX_wm_region(C);
+ tgpf->rv3d = tgpf->region->regiondata;
+ tgpf->v3d = tgpf->area->spacedata.first;
tgpf->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
tgpf->win = CTX_wm_window(C);
/* set GP datablock */
tgpf->gpd = gpd;
- tgpf->gpl = BKE_gpencil_layer_getactive(gpd);
+ tgpf->gpl = BKE_gpencil_layer_active_get(gpd);
if (tgpf->gpl == NULL) {
tgpf->gpl = BKE_gpencil_layer_addnew(tgpf->gpd, DATA_("GP_Layer"), true);
}
+
tgpf->lock_axis = ts->gp_sculpt.lock_axis;
tgpf->oldkey = -1;
@@ -1290,19 +1354,12 @@ static void gpencil_fill_exit(bContext *C, wmOperator *op)
/* remove drawing handler */
if (tgpf->draw_handle_3d) {
- ED_region_draw_cb_exit(tgpf->ar->type, tgpf->draw_handle_3d);
+ ED_region_draw_cb_exit(tgpf->region->type, tgpf->draw_handle_3d);
}
- /* delete temp image */
+ /* Delete temp image. */
if (tgpf->ima) {
- for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
- if (ima == tgpf->ima) {
- BLI_remlink(&bmain->images, ima);
- BKE_image_free(tgpf->ima);
- MEM_SAFE_FREE(tgpf->ima);
- break;
- }
- }
+ BKE_id_free(bmain, tgpf->ima);
}
/* finally, free memory used by temp data */
@@ -1334,7 +1391,7 @@ static int gpencil_fill_init(bContext *C, wmOperator *op)
tGPDfill *tgpf;
/* cannot paint in locked layer */
bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if ((gpl) && (gpl->flag & GP_LAYER_LOCKED)) {
return 0;
}
@@ -1367,12 +1424,12 @@ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
}
}
else {
- if (give_current_material(ob, ob->actcol) == NULL) {
+ if (BKE_object_material_get(ob, ob->actcol) == NULL) {
valid = false;
}
}
if (!valid) {
- BKE_report(op->reports, RPT_ERROR, "Fill tool needs active material.");
+ BKE_report(op->reports, RPT_ERROR, "Fill tool needs active material");
return OPERATOR_CANCELLED;
}
@@ -1391,12 +1448,12 @@ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
/* Enable custom drawing handlers to show help lines */
if (tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) {
tgpf->draw_handle_3d = ED_region_draw_cb_activate(
- tgpf->ar->type, gpencil_fill_draw_3d, tgpf, REGION_DRAW_POST_VIEW);
+ tgpf->region->type, gpencil_fill_draw_3d, tgpf, REGION_DRAW_POST_VIEW);
}
WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_PAINT_BRUSH);
- gpencil_fill_status_indicators(C, tgpf);
+ gpencil_fill_status_indicators(C);
DEG_id_tag_update(&tgpf->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
@@ -1411,38 +1468,45 @@ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tGPDfill *tgpf = op->customdata;
+ Scene *scene = tgpf->scene;
int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through */
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
case RIGHTMOUSE:
estate = OPERATOR_CANCELLED;
break;
case LEFTMOUSE:
tgpf->on_back = RNA_boolean_get(op->ptr, "on_back");
- /* first time the event is not enabled to show help lines */
+ /* first time the event is not enabled to show help lines. */
if ((tgpf->oldkey != -1) || ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) == 0)) {
- ARegion *ar = BKE_area_find_region_xy(CTX_wm_area(C), RGN_TYPE_ANY, event->x, event->y);
- if (ar) {
+ ARegion *region = BKE_area_find_region_xy(
+ CTX_wm_area(C), RGN_TYPE_ANY, event->x, event->y);
+ if (region) {
bool in_bounds = false;
/* Perform bounds check */
- in_bounds = BLI_rcti_isect_pt(&ar->winrct, event->x, event->y);
+ in_bounds = BLI_rcti_isect_pt(&region->winrct, event->x, event->y);
- if ((in_bounds) && (ar->regiontype == RGN_TYPE_WINDOW)) {
- /* TODO GPXX: Verify the mouse click is right for any window size */
+ if ((in_bounds) && (region->regiontype == RGN_TYPE_WINDOW)) {
tgpf->center[0] = event->mval[0];
tgpf->center[1] = event->mval[1];
+ /* Set active frame as current for filling. */
+ tgpf->active_cfra = CFRA;
+
/* render screen to temp image */
if (gp_render_offscreen(tgpf)) {
+ /* Set red borders to create a external limit. */
+ gpencil_set_borders(tgpf, true);
+
/* apply boundary fill */
gpencil_boundaryfill_area(tgpf);
- /* clean borders to avoid infinite loops */
- gpencil_clean_borders(tgpf);
+ /* Clean borders to avoid infinite loops. */
+ gpencil_set_borders(tgpf, false);
/* analyze outline */
gpencil_get_outline_points(tgpf);
@@ -1457,16 +1521,20 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
gpencil_stroke_from_buffer(tgpf);
}
- /* restore size */
- tgpf->ar->winx = (short)tgpf->bwinx;
- tgpf->ar->winy = (short)tgpf->bwiny;
- tgpf->ar->winrct = tgpf->brect;
-
/* free temp stack data */
if (tgpf->stack) {
BLI_stack_free(tgpf->stack);
}
+ /* Free memory. */
+ MEM_SAFE_FREE(tgpf->sbuffer);
+ MEM_SAFE_FREE(tgpf->depth_arr);
+
+ /* restore size */
+ tgpf->region->winx = (short)tgpf->bwinx;
+ tgpf->region->winy = (short)tgpf->bwiny;
+ tgpf->region->winrct = tgpf->brect;
+
/* push undo data */
gpencil_undo_push(tgpf->gpd);
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 69ec11685fb..a98ccb1cba6 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -68,6 +68,17 @@ struct PropertyRNA;
/* Internal Operator-State Data ------------------------ */
+/** Random settings by stroke */
+typedef struct GpRandomSettings {
+ /** Pressure used for evaluated curves. */
+ float pen_press;
+
+ float hsv[3];
+ float pressure;
+ float strength;
+ float uv;
+} GpRandomSettings;
+
/* Temporary draw data (no draw manager mode) */
typedef struct tGPDdraw {
struct RegionView3D *rv3d; /* region to draw */
@@ -111,12 +122,14 @@ typedef struct tGPDinterpolate_layer {
} tGPDinterpolate_layer;
typedef struct tGPDinterpolate {
+ /** Current depsgraph from context */
+ struct Depsgraph *depsgraph;
/** current scene from context */
struct Scene *scene;
/** area where painting originated */
- struct ScrArea *sa;
+ struct ScrArea *area;
/** region where painting originated */
- struct ARegion *ar;
+ struct ARegion *region;
/** current GP datablock */
struct bGPdata *gpd;
/** current material */
@@ -138,10 +151,6 @@ typedef struct tGPDinterpolate {
int flag;
NumInput num; /* numeric input */
- /** handle for drawing strokes while operator is running 3d stuff */
- void *draw_handle_3d;
- /** handle for drawing strokes while operator is running screen stuff */
- void *draw_handle_screen;
} tGPDinterpolate;
/* Temporary primitive operation data */
@@ -155,18 +164,20 @@ typedef struct tGPDprimitive {
struct Scene *scene;
/** current active gp object */
struct Object *ob;
+ /** current evaluated gp object */
+ struct Object *ob_eval;
/** area where painting originated */
- struct ScrArea *sa;
+ struct ScrArea *area;
/** region where painting originated */
struct RegionView3D *rv3d;
/** view3d where painting originated */
struct View3D *v3d;
/** region where painting originated */
- struct ARegion *ar;
+ struct ARegion *region;
/** current GP datablock */
struct bGPdata *gpd;
/** current material */
- struct Material *mat;
+ struct Material *material;
/** current brush */
struct Brush *brush;
@@ -230,13 +241,13 @@ typedef struct tGPDprimitive {
/** size in pixels for uv calculation */
float totpixlen;
+
+ /** Random settings by stroke */
+ GpRandomSettings random_settings;
+
} tGPDprimitive;
/* Modal Operator Drawing Callbacks ------------------------ */
-
-void ED_gp_draw_interpolation(const struct bContext *C,
- struct tGPDinterpolate *tgpi,
- const int type);
void ED_gp_draw_fill(struct tGPDdraw *tgpw);
/* ***************************************************** */
@@ -251,8 +262,8 @@ typedef struct GP_SpaceConversion {
struct bGPdata *gpd;
struct bGPDlayer *gpl;
- struct ScrArea *sa;
- struct ARegion *ar;
+ struct ScrArea *area;
+ struct ARegion *region;
struct View2D *v2d;
rctf *subrect; /* for using the camera rect within the 3d view */
@@ -261,8 +272,7 @@ typedef struct GP_SpaceConversion {
float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */
} GP_SpaceConversion;
-bool gp_stroke_inside_circle(
- const float mval[2], const float UNUSED(mvalo[2]), int rad, int x0, int y0, int x1, int y1);
+bool gp_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1);
void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc);
@@ -284,7 +294,6 @@ void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4],
*/
void gp_apply_parent(struct Depsgraph *depsgraph,
struct Object *obact,
- bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps);
/**
@@ -292,7 +301,6 @@ void gp_apply_parent(struct Depsgraph *depsgraph,
*/
void gp_apply_parent_point(struct Depsgraph *depsgraph,
struct Object *obact,
- bGPdata *gpd,
bGPDlayer *gpl,
bGPDspoint *pt);
@@ -308,9 +316,8 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc,
/* helper to convert 2d to 3d */
void gp_stroke_convertcoords_tpoint(struct Scene *scene,
- struct ARegion *ar,
+ struct ARegion *region,
struct Object *ob,
- bGPDlayer *gpl,
const struct tGPspoint *point2D,
float *depth,
float out[3]);
@@ -342,7 +349,6 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf,
int gp_delete_selected_point_wrap(bContext *C);
void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide);
-void gp_randomize_stroke(bGPDstroke *gps, Brush *brush, struct RNG *rng);
/* Layers Enums -------------------------------------- */
@@ -354,6 +360,10 @@ const struct EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(struct bCon
struct PointerRNA *ptr,
struct PropertyRNA *prop,
bool *r_free);
+const struct EnumPropertyItem *ED_gpencil_material_enum_itemf(struct bContext *C,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ bool *r_free);
/* ***************************************************** */
/* Operator Defines */
@@ -367,6 +377,14 @@ void GPENCIL_OT_annotate(struct wmOperatorType *ot);
void GPENCIL_OT_draw(struct wmOperatorType *ot);
void GPENCIL_OT_fill(struct wmOperatorType *ot);
+/* Vertex Paint. */
+void GPENCIL_OT_vertex_paint(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_color_brightness_contrast(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_color_hsv(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_color_invert(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_color_levels(struct wmOperatorType *ot);
+void GPENCIL_OT_vertex_color_set(struct wmOperatorType *ot);
+
/* Guides ----------------------- */
void GPENCIL_OT_guide_rotate(struct wmOperatorType *ot);
@@ -390,6 +408,7 @@ void GPENCIL_OT_selectmode_toggle(struct wmOperatorType *ot);
void GPENCIL_OT_paintmode_toggle(struct wmOperatorType *ot);
void GPENCIL_OT_sculptmode_toggle(struct wmOperatorType *ot);
void GPENCIL_OT_weightmode_toggle(struct wmOperatorType *ot);
+void GPENCIL_OT_vertexmode_toggle(struct wmOperatorType *ot);
void GPENCIL_OT_selection_opacity_toggle(struct wmOperatorType *ot);
void GPENCIL_OT_select(struct wmOperatorType *ot);
@@ -405,6 +424,7 @@ void GPENCIL_OT_select_less(struct wmOperatorType *ot);
void GPENCIL_OT_select_first(struct wmOperatorType *ot);
void GPENCIL_OT_select_last(struct wmOperatorType *ot);
void GPENCIL_OT_select_alternate(struct wmOperatorType *ot);
+void GPENCIL_OT_select_vertex_color(struct wmOperatorType *ot);
void GPENCIL_OT_duplicate(struct wmOperatorType *ot);
void GPENCIL_OT_delete(struct wmOperatorType *ot);
@@ -415,16 +435,19 @@ void GPENCIL_OT_extrude(struct wmOperatorType *ot);
void GPENCIL_OT_move_to_layer(struct wmOperatorType *ot);
void GPENCIL_OT_layer_change(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_active(struct wmOperatorType *ot);
void GPENCIL_OT_snap_to_grid(struct wmOperatorType *ot);
void GPENCIL_OT_snap_to_cursor(struct wmOperatorType *ot);
void GPENCIL_OT_snap_cursor_to_selected(struct wmOperatorType *ot);
void GPENCIL_OT_reproject(struct wmOperatorType *ot);
+void GPENCIL_OT_recalc_geometry(struct wmOperatorType *ot);
/* stroke sculpting -- */
void GPENCIL_OT_sculpt_paint(struct wmOperatorType *ot);
+void GPENCIL_OT_weight_paint(struct wmOperatorType *ot);
/* buttons editing --- */
@@ -440,6 +463,9 @@ void GPENCIL_OT_layer_annotation_move(struct wmOperatorType *ot);
void GPENCIL_OT_layer_duplicate(struct wmOperatorType *ot);
void GPENCIL_OT_layer_duplicate_object(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_mask_add(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_mask_remove(struct wmOperatorType *ot);
+
void GPENCIL_OT_hide(struct wmOperatorType *ot);
void GPENCIL_OT_reveal(struct wmOperatorType *ot);
@@ -459,6 +485,7 @@ void GPENCIL_OT_frame_clean_fill(struct wmOperatorType *ot);
void GPENCIL_OT_frame_clean_loose(struct wmOperatorType *ot);
void GPENCIL_OT_convert(struct wmOperatorType *ot);
+void GPENCIL_OT_image_to_grease_pencil(struct wmOperatorType *ot);
enum {
GP_STROKE_JOIN = -1,
@@ -481,7 +508,6 @@ enum {
void GPENCIL_OT_stroke_arrange(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_change_color(struct wmOperatorType *ot);
-void GPENCIL_OT_stroke_lock_color(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_apply_thickness(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_cyclical_set(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_caps_set(struct wmOperatorType *ot);
@@ -498,8 +524,16 @@ void GPENCIL_OT_stroke_merge(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_cutter(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_trim(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_merge_by_distance(struct wmOperatorType *ot);
+void GPENCIL_OT_stroke_merge_material(struct wmOperatorType *ot);
+
+void GPENCIL_OT_material_to_vertex_color(struct wmOperatorType *ot);
+void GPENCIL_OT_extract_palette_vertex(struct wmOperatorType *ot);
-void GPENCIL_OT_brush_presets_create(struct wmOperatorType *ot);
+void GPENCIL_OT_transform_fill(struct wmOperatorType *ot);
+void GPENCIL_OT_reset_transform_fill(struct wmOperatorType *ot);
+
+void GPENCIL_OT_brush_reset(struct wmOperatorType *ot);
+void GPENCIL_OT_brush_reset_all(struct wmOperatorType *ot);
/* undo stack ---------- */
@@ -529,12 +563,14 @@ void GPENCIL_OT_vertex_group_normalize_all(struct wmOperatorType *ot);
/* color handle */
void GPENCIL_OT_lock_layer(struct wmOperatorType *ot);
-void GPENCIL_OT_color_isolate(struct wmOperatorType *ot);
-void GPENCIL_OT_color_hide(struct wmOperatorType *ot);
-void GPENCIL_OT_color_reveal(struct wmOperatorType *ot);
-void GPENCIL_OT_color_lock_all(struct wmOperatorType *ot);
-void GPENCIL_OT_color_unlock_all(struct wmOperatorType *ot);
-void GPENCIL_OT_color_select(struct wmOperatorType *ot);
+void GPENCIL_OT_material_isolate(struct wmOperatorType *ot);
+void GPENCIL_OT_material_hide(struct wmOperatorType *ot);
+void GPENCIL_OT_material_reveal(struct wmOperatorType *ot);
+void GPENCIL_OT_material_lock_all(struct wmOperatorType *ot);
+void GPENCIL_OT_material_unlock_all(struct wmOperatorType *ot);
+void GPENCIL_OT_material_lock_unused(struct wmOperatorType *ot);
+void GPENCIL_OT_material_select(struct wmOperatorType *ot);
+void GPENCIL_OT_material_set(struct wmOperatorType *ot);
void GPENCIL_OT_set_active_material(struct wmOperatorType *ot);
/* convert old 2.7 files to 2.8 */
@@ -544,7 +580,7 @@ void GPENCIL_OT_convert_old_files(struct wmOperatorType *ot);
void GPENCIL_OT_generate_weights(struct wmOperatorType *ot);
/* ****************************************************** */
-/* FILTERED ACTION DATA - TYPES ---> XXX DEPRECEATED OLD ANIM SYSTEM CODE! */
+/* FILTERED ACTION DATA - TYPES ---> XXX DEPRECATED OLD ANIM SYSTEM CODE! */
/* XXX - TODO: replace this with the modern bAnimListElem... */
/* This struct defines a structure used for quick access */
@@ -617,7 +653,7 @@ struct GP_EditableStrokes_Iter {
bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \
for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \
if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \
- ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, gpstroke_iter.diff_mat); \
+ BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \
invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \
/* loop over strokes */ \
bGPDstroke *gpsn_; \
@@ -643,10 +679,6 @@ struct GP_EditableStrokes_Iter {
} \
(void)0
-#define GPENCIL_ANY_SCULPT_MASK(flag) \
- ((flag & (GP_SCULPT_MASK_SELECTMODE_POINT | GP_SCULPT_MASK_SELECTMODE_STROKE | \
- GP_SCULPT_MASK_SELECTMODE_SEGMENT)))
-
/**
* Iterate over all editable strokes using evaluated data in the current context,
* stopping on each usable layer + stroke pair (i.e. gpl and gps)
@@ -662,26 +694,21 @@ struct GP_EditableStrokes_Iter {
struct GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
Depsgraph *depsgraph_ = CTX_data_ensure_evaluated_depsgraph(C); \
Object *obact_ = CTX_data_active_object(C); \
- Object *obeval_ = DEG_get_evaluated_object(depsgraph_, obact_); \
- bGPdata *gpd_ = CTX_data_gpencil_data(C); \
+ Object *ob_eval_ = (Object *)DEG_get_evaluated_id(depsgraph_, &obact_->id); \
+ bGPdata *gpd_ = (bGPdata *)ob_eval_->data; \
const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
- int idx_eval = 0; \
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { \
- if (gpencil_layer_is_editable(gpl)) { \
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_->layers) { \
+ if (BKE_gpencil_layer_is_editable(gpl)) { \
bGPDframe *init_gpf_ = gpl->actframe; \
if (is_multiedit_) { \
init_gpf_ = gpl->frames.first; \
} \
for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \
if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \
- ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, gpstroke_iter.diff_mat); \
+ BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \
invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \
- /* get evaluated frame with modifiers applied */ \
- bGPDframe *gpf_eval_ = (!is_multiedit_) ? \
- &obeval_->runtime.gpencil_evaluated_frames[idx_eval] : \
- gpf_; \
/* loop over strokes */ \
- for (bGPDstroke *gps = gpf_eval_->strokes.first; gps; gps = gps->next) { \
+ for (bGPDstroke *gps = gpf_->strokes.first; gps; gps = gps->next) { \
/* skip strokes that are invalid for current view */ \
if (ED_gpencil_stroke_can_use(C, gps) == false) \
continue; \
@@ -698,7 +725,6 @@ struct GP_EditableStrokes_Iter {
} \
} \
} \
- idx_eval++; \
} \
} \
(void)0
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index ec26006eb06..5cb49600d05 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -22,18 +22,18 @@
* \ingroup edgpencil
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_easing.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -50,6 +50,7 @@
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
#include "BKE_report.h"
#include "UI_interface.h"
@@ -67,8 +68,8 @@
#include "ED_gpencil.h"
#include "ED_object.h"
#include "ED_screen.h"
-#include "ED_view3d.h"
#include "ED_space_api.h"
+#include "ED_view3d.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -85,8 +86,8 @@ static bool gpencil_view3d_poll(bContext *C)
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
/* only 3D view */
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacetype != SPACE_VIEW3D) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area && area->spacetype != SPACE_VIEW3D) {
return 0;
}
@@ -115,31 +116,51 @@ static void gp_interpolate_update_points(const bGPDstroke *gps_from,
pt->pressure = interpf(prev->pressure, next->pressure, 1.0f - factor);
pt->strength = interpf(prev->strength, next->strength, 1.0f - factor);
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
-
- /* GPXX interpolate dverts */
-#if 0
- MDeformVert *dvert = &new_stroke->dvert[i];
- dvert->totweight = 0;
- dvert->dw = NULL;
-#endif
}
}
/* ****************** Interpolate Interactive *********************** */
+/* Helper: free all temp strokes for display. */
+static void gp_interpolate_free_temp_strokes(bGPDframe *gpf)
+{
+ if (gpf == NULL) {
+ return;
+ }
+
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->flag & GP_STROKE_TAG) {
+ BLI_remlink(&gpf->strokes, gps);
+ BKE_gpencil_free_stroke(gps);
+ }
+ }
+}
+
+/* Helper: Untag all strokes. */
+static void gp_interpolate_untag_strokes(bGPDframe *gpf)
+{
+ BLI_assert(gpf != NULL);
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->flag & GP_STROKE_TAG) {
+ gps->flag &= ~GP_STROKE_TAG;
+ }
+ }
+}
/* Helper: Update all strokes interpolated */
static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
{
bGPdata *gpd = tgpi->gpd;
- tGPDinterpolate_layer *tgpil;
const float shift = tgpi->shift;
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- bGPDstroke *new_stroke;
+ LISTBASE_FOREACH (tGPDinterpolate_layer *, tgpil, &tgpi->ilayers) {
const float factor = tgpil->factor + shift;
- for (new_stroke = tgpil->interFrame->strokes.first; new_stroke;
- new_stroke = new_stroke->next) {
+ bGPDframe *gpf = tgpil->gpl->actframe;
+ /* Free temp strokes. */
+ gp_interpolate_free_temp_strokes(gpf);
+
+ LISTBASE_FOREACH (bGPDstroke *, new_stroke, &tgpil->interFrame->strokes) {
bGPDstroke *gps_from, *gps_to;
int stroke_idx;
@@ -156,6 +177,13 @@ static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
/* update points position */
if ((gps_from) && (gps_to)) {
gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
+
+ /* Add temp strokes. */
+ if (gpf) {
+ bGPDstroke *gps_eval = BKE_gpencil_stroke_duplicate(new_stroke, true);
+ gps_eval->flag |= GP_STROKE_TAG;
+ BLI_addtail(&gpf->strokes, gps_eval);
+ }
}
}
}
@@ -172,19 +200,18 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag;
/* get layers */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* all layers or only active */
if (!(flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && !(gpl->flag & GP_LAYER_ACTIVE)) {
continue;
}
/* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ if (!BKE_gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
continue;
}
/* read strokes */
- for (bGPDstroke *gps_from = gpl->actframe->strokes.first; gps_from;
- gps_from = gps_from->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps_from, &gpl->actframe->strokes) {
bGPDstroke *gps_to;
int fFrame;
@@ -232,7 +259,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
tgpi->high_limit = 2.0f - tgpi->init_factor;
/* set layers */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
tGPDinterpolate_layer *tgpil;
/* all layers or only active */
@@ -240,7 +267,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
continue;
}
/* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ if (!BKE_gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
continue;
}
@@ -251,6 +278,10 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
tgpil->prevFrame = gpl->actframe;
tgpil->nextFrame = gpl->actframe->next;
+ /* Untag interpolated strokes to be sure nothing is pending. */
+ gp_interpolate_untag_strokes(tgpil->prevFrame);
+ gp_interpolate_untag_strokes(tgpil->nextFrame);
+
BLI_addtail(&tgpi->ilayers, tgpil);
/* create a new temporary frame */
@@ -262,8 +293,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
(tgpil->nextFrame->framenum - tgpil->prevFrame->framenum + 1);
/* create new strokes data with interpolated points reading original stroke */
- for (bGPDstroke *gps_from = tgpil->prevFrame->strokes.first; gps_from;
- gps_from = gps_from->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps_from, &tgpil->prevFrame->strokes) {
bGPDstroke *gps_to;
int fFrame;
@@ -293,7 +323,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
}
/* create new stroke */
- new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
+ new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true);
if (valid) {
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
@@ -305,8 +335,6 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
sizeof(*new_stroke->dvert) * gps_to->totpoints);
}
new_stroke->totpoints = gps_to->totpoints;
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
}
/* update points position */
gp_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor);
@@ -318,12 +346,10 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
if (new_stroke->dvert != NULL) {
new_stroke->dvert = MEM_recallocN(new_stroke->dvert, sizeof(*new_stroke->dvert));
}
- new_stroke->tot_triangles = 0;
- new_stroke->triangles = MEM_recallocN(new_stroke->triangles,
- sizeof(*new_stroke->triangles));
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
/* add to strokes */
BLI_addtail(&tgpil->interFrame->strokes, new_stroke);
}
@@ -331,33 +357,14 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
}
/* ----------------------- */
-/* Drawing Callbacks */
-
-/* Drawing callback for modal operator in screen mode */
-static void gpencil_interpolate_draw_screen(const struct bContext *C,
- ARegion *UNUSED(ar),
- void *arg)
-{
- tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
- ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_PIXEL);
-}
-
-/* Drawing callback for modal operator in 3d mode */
-static void gpencil_interpolate_draw_3d(const bContext *C, ARegion *UNUSED(ar), void *arg)
-{
- tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
- ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_VIEW);
-}
-
-/* ----------------------- */
/* Helper: calculate shift based on position of mouse (we only use x-axis for now.
* since this is more convenient for users to do), and store new shift value
*/
static void gpencil_mouse_update_shift(tGPDinterpolate *tgpi, wmOperator *op, const wmEvent *event)
{
- float mid = (float)(tgpi->ar->winx - tgpi->ar->winrct.xmin) / 2.0f;
- float mpos = event->x - tgpi->ar->winrct.xmin;
+ float mid = (float)(tgpi->region->winx - tgpi->region->winrct.xmin) / 2.0f;
+ float mpos = event->x - tgpi->region->winrct.xmin;
if (mpos >= mid) {
tgpi->shift = ((mpos - mid) * tgpi->high_limit) / mid;
@@ -393,7 +400,7 @@ static void gpencil_interpolate_status_indicators(bContext *C, tGPDinterpolate *
(int)((p->init_factor + p->shift) * 100.0f));
}
- ED_area_status_text(p->sa, status_str);
+ ED_area_status_text(p->area, status_str);
ED_workspace_status_text(
C, TIP_("ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/MOVE to adjust factor"));
}
@@ -415,25 +422,23 @@ static void gpencil_interpolate_update(bContext *C, wmOperator *op, tGPDinterpol
static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
{
tGPDinterpolate *tgpi = op->customdata;
- tGPDinterpolate_layer *tgpil;
bGPdata *gpd = tgpi->gpd;
/* don't assume that operator data exists at all */
if (tgpi) {
- /* remove drawing handler */
- if (tgpi->draw_handle_screen) {
- ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_screen);
- }
- if (tgpi->draw_handle_3d) {
- ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d);
- }
-
/* clear status message area */
- ED_area_status_text(tgpi->sa, NULL);
+ ED_area_status_text(tgpi->area, NULL);
ED_workspace_status_text(C, NULL);
+ /* Clear any temp stroke. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ gp_interpolate_free_temp_strokes(gpf);
+ }
+ }
+
/* finally, free memory used by temp data */
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+ LISTBASE_FOREACH (tGPDinterpolate_layer *, tgpil, &tgpi->ilayers) {
BKE_gpencil_free_strokes(tgpil->interFrame);
MEM_freeN(tgpil->interFrame);
}
@@ -455,9 +460,10 @@ static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinte
bGPdata *gpd = CTX_data_gpencil_data(C);
/* set current scene and window */
+ tgpi->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
tgpi->scene = CTX_data_scene(C);
- tgpi->sa = CTX_wm_area(C);
- tgpi->ar = CTX_wm_region(C);
+ tgpi->area = CTX_wm_area(C);
+ tgpi->region = CTX_wm_region(C);
tgpi->flag = ts->gp_interpolate.flag;
/* set current frame number */
@@ -550,15 +556,6 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent
tgpi = op->customdata;
}
- /* Enable custom drawing handlers
- * It needs 2 handlers because strokes can in 3d space and screen space
- * and each handler use different coord system
- */
- tgpi->draw_handle_screen = ED_region_draw_cb_activate(
- tgpi->ar->type, gpencil_interpolate_draw_screen, tgpi, REGION_DRAW_POST_PIXEL);
- tgpi->draw_handle_3d = ED_region_draw_cb_activate(
- tgpi->ar->type, gpencil_interpolate_draw_3d, tgpi, REGION_DRAW_POST_VIEW);
-
/* set cursor to indicate modal */
WM_cursor_modal_set(win, WM_CURSOR_EW_SCROLL);
@@ -579,40 +576,35 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
tGPDinterpolate *tgpi = op->customdata;
wmWindow *win = CTX_wm_window(C);
bGPDframe *gpf_dst;
- bGPDstroke *gps_src, *gps_dst;
- tGPDinterpolate_layer *tgpil;
+ bGPDstroke *gps_dst;
const bool has_numinput = hasNumInput(&tgpi->num);
switch (event->type) {
case LEFTMOUSE: /* confirm */
- case PADENTER:
- case RETKEY: {
+ case EVT_PADENTER:
+ case EVT_RETKEY: {
/* return to normal cursor and header status */
- ED_area_status_text(tgpi->sa, NULL);
+ ED_area_status_text(tgpi->area, NULL);
ED_workspace_status_text(C, NULL);
WM_cursor_modal_restore(win);
/* insert keyframes as required... */
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- gpf_dst = BKE_gpencil_layer_getframe(tgpil->gpl, tgpi->cframe, GP_GETFRAME_ADD_NEW);
+ LISTBASE_FOREACH (tGPDinterpolate_layer *, tgpil, &tgpi->ilayers) {
+ gpf_dst = BKE_gpencil_layer_frame_get(tgpil->gpl, tgpi->cframe, GP_GETFRAME_ADD_NEW);
gpf_dst->key_type = BEZT_KEYTYPE_BREAKDOWN;
/* copy strokes */
BLI_listbase_clear(&gpf_dst->strokes);
- for (gps_src = tgpil->interFrame->strokes.first; gps_src; gps_src = gps_src->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps_src, &tgpil->interFrame->strokes) {
if (gps_src->totpoints == 0) {
continue;
}
/* make copy of source stroke, then adjust pointer to points too */
- gps_dst = MEM_dupallocN(gps_src);
- gps_dst->points = MEM_dupallocN(gps_src->points);
- if (gps_src->dvert != NULL) {
- gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
- }
- gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
- gps_dst->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps_dst);
+
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
}
@@ -624,10 +616,10 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_FINISHED;
}
- case ESCKEY: /* cancel */
+ case EVT_ESCKEY: /* cancel */
case RIGHTMOUSE: {
/* return to normal cursor and header status */
- ED_area_status_text(tgpi->sa, NULL);
+ ED_area_status_text(tgpi->area, NULL);
ED_workspace_status_text(C, NULL);
WM_cursor_modal_restore(win);
@@ -973,17 +965,21 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
}
/* loop all layer to check if need interpolation */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *prevFrame, *nextFrame;
bGPDstroke *gps_from, *gps_to;
int cframe, fFrame;
+ /* Need a set of frames to interpolate. */
+ if ((gpl->actframe == NULL) || (gpl->actframe->next == NULL)) {
+ continue;
+ }
/* all layers or only active */
if (((flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) == 0) && (gpl != active_gpl)) {
continue;
}
/* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ if (!BKE_gpencil_layer_is_editable(gpl)) {
continue;
}
@@ -1017,7 +1013,6 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
/* create new strokes data with interpolated points reading original stroke */
for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
- bGPDstroke *new_stroke = NULL;
/* only selected */
if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) &&
@@ -1042,12 +1037,12 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
/* create a new frame if needed */
if (interFrame == NULL) {
- interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW);
+ interFrame = BKE_gpencil_layer_frame_get(gpl, cframe, GP_GETFRAME_ADD_NEW);
interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN;
}
/* create new stroke */
- new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
+ bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true);
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
if (gps_from->totpoints > gps_to->totpoints) {
@@ -1064,14 +1059,16 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
new_stroke->dvert = MEM_recallocN(new_stroke->dvert,
sizeof(*new_stroke->dvert) * gps_to->totpoints);
}
+
new_stroke->totpoints = gps_to->totpoints;
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
}
/* update points position */
gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
+
/* add to strokes */
BLI_addtail(&interFrame->strokes, new_stroke);
}
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 36cef3ccdc0..e71bf2098dd 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -35,8 +35,10 @@
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_report.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -60,6 +62,7 @@ typedef struct tGPencilPointCache {
float x, y, z;
float pressure;
float strength;
+ float vert_color[4];
} tGPencilPointCache;
/* helper function to sort points */
@@ -93,6 +96,7 @@ static void gpencil_insert_points_to_stroke(bGPDstroke *gps,
pt_dst->uv_fac = 1.0f;
pt_dst->uv_rot = 0;
pt_dst->flag |= GP_SPOINT_SELECT;
+ copy_v4_v4(pt_dst->vert_color, point_elem->vert_color);
}
}
@@ -113,7 +117,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo
/* if not exist, create a new one */
if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
- BKE_brush_gpencil_presets(bmain, ts);
+ BKE_brush_gpencil_paint_presets(bmain, ts, false);
}
Brush *brush = paint->brush;
@@ -125,25 +129,11 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo
else {
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, add_frame_mode);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode);
/* stroke */
- bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
- gps->totpoints = totpoints;
- gps->inittime = 0.0f;
- gps->thickness = brush->size;
- gps->gradient_f = brush->gpencil_settings->gradient_f;
- copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s);
+ bGPDstroke *gps = BKE_gpencil_stroke_new(ob->actcol - 1, totpoints, brush->size);
gps->flag |= GP_STROKE_SELECT;
- gps->flag |= GP_STROKE_3DSPACE;
- gps->mat_nr = ob->actcol - 1;
-
- /* allocate memory for points */
- gps->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, "gp_stroke_points");
- /* initialize triangle memory to dummy data */
- gps->tot_triangles = 0;
- gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
if (cyclic) {
gps->flag |= GP_STROKE_CYCLIC;
@@ -181,17 +171,14 @@ static void gpencil_get_elements_len(bContext *C, int *totstrokes, int *totpoint
static void gpencil_dissolve_points(bContext *C)
{
- bGPDstroke *gps, *gpsn;
-
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *gpf = gpl->actframe;
if (gpf == NULL) {
continue;
}
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
- gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_TAG, false, 0);
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
}
}
CTX_DATA_END;
@@ -224,7 +211,7 @@ static void gpencil_calc_points_factor(bContext *C,
if (gpf == NULL) {
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (clear_stroke) {
@@ -239,6 +226,7 @@ static void gpencil_calc_points_factor(bContext *C,
copy_v3_v3(&pt2->x, &pt->x);
pt2->pressure = pt->pressure;
pt2->strength = pt->strength;
+ copy_v4_v4(pt2->vert_color, pt->vert_color);
pt->flag &= ~GP_SPOINT_SELECT;
if (clear_point) {
pt->flag |= GP_SPOINT_TAG;
@@ -288,6 +276,7 @@ static void gpencil_calc_points_factor(bContext *C,
copy_v3_v3(&sort_pt->x, &pt2->x);
sort_pt->pressure = pt2->pressure;
sort_pt->strength = pt2->strength;
+ copy_v4_v4(sort_pt->vert_color, pt2->vert_color);
sort_pt->gps = gps_array[i];
@@ -336,6 +325,7 @@ static int gpencil_insert_to_array(tGPencilPointCache *src_array,
dst_elem->pressure = src_elem->pressure;
dst_elem->strength = src_elem->strength;
dst_elem->factor = src_elem->factor;
+ copy_v4_v4(dst_elem->vert_color, src_elem->vert_color);
}
return last;
@@ -451,14 +441,14 @@ static bool gp_strokes_merge_poll(bContext *C)
/* check material */
Material *ma = NULL;
- ma = BKE_material_gpencil_get(ob, ob->actcol);
+ ma = BKE_gpencil_material(ob, ob->actcol);
if ((ma == NULL) || (ma->gp_style == NULL)) {
return false;
}
/* check hidden or locked materials */
MaterialGPencilStyle *gp_style = ma->gp_style;
- if ((gp_style->flag & GP_STYLE_COLOR_HIDE) || (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ if ((gp_style->flag & GP_MATERIAL_HIDE) || (gp_style->flag & GP_MATERIAL_LOCKED)) {
return false;
}
@@ -529,6 +519,8 @@ static int gp_stroke_merge_exec(bContext *C, wmOperator *op)
gpencil_dissolve_points(C);
}
+ BKE_gpencil_stroke_geometry_update(gps);
+
/* free memory */
MEM_SAFE_FREE(original_array);
MEM_SAFE_FREE(sorted_array);
@@ -569,3 +561,100 @@ void GPENCIL_OT_stroke_merge(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "clear_point", 0, "Dissolve Points", "Dissolve old selected points");
RNA_def_boolean(ot->srna, "clear_stroke", 0, "Delete Strokes", "Delete old selected strokes");
}
+
+/* Merge similar materials. */
+static bool gp_stroke_merge_material_poll(bContext *C)
+{
+ /* only supported with grease pencil objects */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ return true;
+}
+
+static int gp_stroke_merge_material_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const float hue_threshold = RNA_float_get(op->ptr, "hue_threshold");
+ const float sat_threshold = RNA_float_get(op->ptr, "sat_threshold");
+ const float val_threshold = RNA_float_get(op->ptr, "val_threshold");
+
+ /* Review materials. */
+ GHash *mat_table = BLI_ghash_int_new(__func__);
+
+ short *totcol = BKE_object_material_len_p(ob);
+ if (totcol == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bool changed = BKE_gpencil_merge_materials_table_get(
+ ob, hue_threshold, sat_threshold, val_threshold, mat_table);
+
+ int removed = BLI_ghash_len(mat_table);
+
+ /* Update stroke material index. */
+ if (changed) {
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+
+ if (BLI_ghash_haskey(mat_table, POINTER_FROM_INT(gps->mat_nr))) {
+ int *idx = BLI_ghash_lookup(mat_table, POINTER_FROM_INT(gps->mat_nr));
+ gps->mat_nr = POINTER_AS_INT(idx);
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* Free hash memory. */
+ BLI_ghash_free(mat_table, NULL, NULL);
+
+ /* notifiers */
+ if (changed) {
+ BKE_reportf(op->reports, RPT_INFO, "Merged %d materials of %d", removed, *totcol);
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+ else {
+ BKE_report(op->reports, RPT_INFO, "Nothing to merge");
+ }
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_merge_material(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Merge Grease Pencil Materials";
+ ot->idname = "GPENCIL_OT_stroke_merge_material";
+ ot->description = "Replace materials in strokes merging similar";
+
+ /* api callbacks */
+ ot->exec = gp_stroke_merge_material_exec;
+ ot->poll = gp_stroke_merge_material_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_float(
+ ot->srna, "hue_threshold", 0.001f, 0.0f, 1.0f, "Hue Threshold", "", 0.0f, 1.0f);
+ prop = RNA_def_float(
+ ot->srna, "sat_threshold", 0.001f, 0.0f, 1.0f, "Saturation Threshold", "", 0.0f, 1.0f);
+ prop = RNA_def_float(
+ ot->srna, "val_threshold", 0.001f, 0.0f, 1.0f, "Value Threshold", "", 0.0f, 1.0f);
+ /* avoid re-using last var */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 7a541cd8f03..94c86572fd3 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -21,14 +21,14 @@
* \ingroup edgpencil
*/
-#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
+#include <stdlib.h>
#include "BLI_sys_types.h"
-#include "BKE_context.h"
#include "BKE_brush.h"
+#include "BKE_context.h"
#include "BKE_gpencil.h"
#include "BKE_paint.h"
@@ -39,14 +39,14 @@
#include "DNA_space_types.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "ED_gpencil.h"
-#include "ED_select_utils.h"
#include "ED_object.h"
+#include "ED_select_utils.h"
#include "ED_transform.h"
#include "gpencil_intern.h"
@@ -95,6 +95,60 @@ static bool gp_stroke_paintmode_poll_with_tool(bContext *C, const char gpencil_t
WM_toolsystem_active_tool_is_brush(C) && (brush->gpencil_tool == gpencil_tool));
}
+static bool gp_stroke_vertexmode_poll_with_tool(bContext *C, const char gpencil_vertex_tool)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ if (!gpd) {
+ return false;
+ }
+
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ if (!ts || !ts->gp_vertexpaint) {
+ return false;
+ }
+
+ Brush *brush = BKE_paint_brush(&ts->gp_vertexpaint->paint);
+ return ((gpd->flag & GP_DATA_STROKE_VERTEXMODE) && (brush && brush->gpencil_settings) &&
+ WM_toolsystem_active_tool_is_brush(C) &&
+ (brush->gpencil_vertex_tool == gpencil_vertex_tool));
+}
+
+static bool gp_stroke_sculptmode_poll_with_tool(bContext *C, const char gpencil_sculpt_tool)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ if (!gpd) {
+ return false;
+ }
+
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ if (!ts || !ts->gp_sculptpaint) {
+ return false;
+ }
+
+ Brush *brush = BKE_paint_brush(&ts->gp_sculptpaint->paint);
+ return ((gpd->flag & GP_DATA_STROKE_SCULPTMODE) && (brush && brush->gpencil_settings) &&
+ WM_toolsystem_active_tool_is_brush(C) &&
+ (brush->gpencil_sculpt_tool == gpencil_sculpt_tool));
+}
+
+static bool gp_stroke_weightmode_poll_with_tool(bContext *C, const char gpencil_weight_tool)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ if (!gpd) {
+ return false;
+ }
+
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ if (!ts || !ts->gp_weightpaint) {
+ return false;
+ }
+
+ Brush *brush = BKE_paint_brush(&ts->gp_weightpaint->paint);
+ return ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) && (brush && brush->gpencil_settings) &&
+ WM_toolsystem_active_tool_is_brush(C) &&
+ (brush->gpencil_weight_tool == gpencil_weight_tool));
+}
+
/* Poll callback for stroke painting (draw brush) */
static bool gp_stroke_paintmode_draw_poll(bContext *C)
{
@@ -113,21 +167,26 @@ static bool gp_stroke_paintmode_fill_poll(bContext *C)
return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_FILL);
}
+/* Poll callback for stroke painting (tint) */
+static bool gp_stroke_paintmode_tint_poll(bContext *C)
+{
+ return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_TINT);
+}
+
/* Poll callback for stroke sculpting mode */
static bool gp_stroke_sculptmode_poll(bContext *C)
{
bGPdata *gpd = CTX_data_gpencil_data(C);
Object *ob = CTX_data_active_object(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* if not gpencil object and not view3d, need sculpt keys if edit mode */
- if (sa->spacetype != SPACE_VIEW3D) {
+ if (area->spacetype != SPACE_VIEW3D) {
return ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
}
else {
- /* weight paint is a submode of sculpt */
if ((ob) && (ob->type == OB_GPENCIL)) {
- return GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd);
+ return GPENCIL_SCULPT_MODE(gpd);
}
}
@@ -141,12 +200,113 @@ static bool gp_stroke_weightmode_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
if ((ob) && (ob->type == OB_GPENCIL)) {
- return (gpd && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE));
+ return GPENCIL_WEIGHT_MODE(gpd);
+ }
+
+ return 0;
+}
+
+/* Poll callback for stroke vertex paint mode */
+static bool gp_stroke_vertexmode_poll(bContext *C)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Object *ob = CTX_data_active_object(C);
+
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ return (gpd && (gpd->flag & GP_DATA_STROKE_VERTEXMODE));
}
return 0;
}
+/* Poll callback for vertex painting (draw) */
+static bool gp_stroke_vertexmode_draw_poll(bContext *C)
+{
+ return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_DRAW);
+}
+
+/* Poll callback for vertex painting (blur) */
+static bool gp_stroke_vertexmode_blur_poll(bContext *C)
+{
+ return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_BLUR);
+}
+
+/* Poll callback for vertex painting (average) */
+static bool gp_stroke_vertexmode_average_poll(bContext *C)
+{
+ return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_AVERAGE);
+}
+
+/* Poll callback for vertex painting (smear) */
+static bool gp_stroke_vertexmode_smear_poll(bContext *C)
+{
+ return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_SMEAR);
+}
+
+/* Poll callback for vertex painting (replace) */
+static bool gp_stroke_vertexmode_replace_poll(bContext *C)
+{
+ return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_REPLACE);
+}
+
+/* Poll callback for sculpt (Smooth) */
+static bool gp_stroke_sculptmode_smooth_poll(bContext *C)
+{
+ return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_SMOOTH);
+}
+/* Poll callback for sculpt (Thickness) */
+static bool gp_stroke_sculptmode_thickness_poll(bContext *C)
+{
+ return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_THICKNESS);
+}
+
+/* Poll callback for sculpt (Strength) */
+static bool gp_stroke_sculptmode_strength_poll(bContext *C)
+{
+ return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_STRENGTH);
+}
+
+/* Poll callback for sculpt (Grab) */
+static bool gp_stroke_sculptmode_grab_poll(bContext *C)
+{
+ return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_GRAB);
+}
+
+/* Poll callback for sculpt (Push) */
+static bool gp_stroke_sculptmode_push_poll(bContext *C)
+{
+ return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_PUSH);
+}
+
+/* Poll callback for sculpt (Twist) */
+static bool gp_stroke_sculptmode_twist_poll(bContext *C)
+{
+ return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_TWIST);
+}
+
+/* Poll callback for sculpt (Pinch) */
+static bool gp_stroke_sculptmode_pinch_poll(bContext *C)
+{
+ return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_PINCH);
+}
+/* Poll callback for sculpt (Randomize) */
+static bool gp_stroke_sculptmode_randomize_poll(bContext *C)
+{
+ return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_RANDOMIZE);
+}
+
+/* Poll callback for sculpt (Clone) */
+static bool gp_stroke_sculptmode_clone_poll(bContext *C)
+{
+ return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_CLONE);
+}
+
+/* Poll callback for weight paint (Draw) */
+static bool gp_stroke_weightmode_draw_poll(bContext *C)
+{
+ return gp_stroke_weightmode_poll_with_tool(C, GPWEIGHT_TOOL_DRAW);
+}
+
/* Stroke Editing Keymap - Only when editmode is enabled */
static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
{
@@ -177,6 +337,13 @@ static void ed_keymap_gpencil_painting_fill(wmKeyConfig *keyconf)
keymap->poll = gp_stroke_paintmode_fill_poll;
}
+/* keys for draw with a tint brush */
+static void ed_keymap_gpencil_painting_tint(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Tint)", 0, 0);
+ keymap->poll = gp_stroke_paintmode_tint_poll;
+}
+
/* Stroke Painting Keymap - Only when paintmode is enabled */
static void ed_keymap_gpencil_painting(wmKeyConfig *keyconf)
{
@@ -200,6 +367,106 @@ static void ed_keymap_gpencil_weightpainting(wmKeyConfig *keyconf)
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight Mode", 0, 0);
keymap->poll = gp_stroke_weightmode_poll;
}
+
+static void ed_keymap_gpencil_vertexpainting(wmKeyConfig *keyconf)
+{
+ /* set poll callback - so that this keymap only gets enabled when stroke vertex is enabled */
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex Mode", 0, 0);
+ keymap->poll = gp_stroke_vertexmode_poll;
+}
+
+/* keys for vertex with a draw brush */
+static void ed_keymap_gpencil_vertexpainting_draw(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Draw)", 0, 0);
+ keymap->poll = gp_stroke_vertexmode_draw_poll;
+}
+
+/* keys for vertex with a blur brush */
+static void ed_keymap_gpencil_vertexpainting_blur(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Blur)", 0, 0);
+ keymap->poll = gp_stroke_vertexmode_blur_poll;
+}
+/* keys for vertex with a average brush */
+static void ed_keymap_gpencil_vertexpainting_average(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Average)", 0, 0);
+ keymap->poll = gp_stroke_vertexmode_average_poll;
+}
+/* keys for vertex with a smear brush */
+static void ed_keymap_gpencil_vertexpainting_smear(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Smear)", 0, 0);
+ keymap->poll = gp_stroke_vertexmode_smear_poll;
+}
+/* keys for vertex with a replace brush */
+static void ed_keymap_gpencil_vertexpainting_replace(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Replace)", 0, 0);
+ keymap->poll = gp_stroke_vertexmode_replace_poll;
+}
+/* keys for sculpt with a smooth brush */
+static void ed_keymap_gpencil_sculptpainting_smooth(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Smooth)", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_smooth_poll;
+}
+/* keys for sculpt with a thickness brush */
+static void ed_keymap_gpencil_sculptpainting_thickness(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Thickness)", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_thickness_poll;
+}
+/* keys for sculpt with a strength brush */
+static void ed_keymap_gpencil_sculptpainting_strength(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Strength)", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_strength_poll;
+}
+/* keys for sculpt with a grab brush */
+static void ed_keymap_gpencil_sculptpainting_grab(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Grab)", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_grab_poll;
+}
+/* keys for sculpt with a push brush */
+static void ed_keymap_gpencil_sculptpainting_push(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Push)", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_push_poll;
+}
+/* keys for sculpt with a twist brush */
+static void ed_keymap_gpencil_sculptpainting_twist(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Twist)", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_twist_poll;
+}
+/* keys for sculpt with a pinch brush */
+static void ed_keymap_gpencil_sculptpainting_pinch(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Pinch)", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_pinch_poll;
+}
+/* keys for sculpt with a randomize brush */
+static void ed_keymap_gpencil_sculptpainting_randomize(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Randomize)", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_randomize_poll;
+}
+/* keys for sculpt with a clone brush */
+static void ed_keymap_gpencil_sculptpainting_clone(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Clone)", 0, 0);
+ keymap->poll = gp_stroke_sculptmode_clone_poll;
+}
+/* keys for weight with a draw brush */
+static void ed_keymap_gpencil_weightpainting_draw(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight (Draw)", 0, 0);
+ keymap->poll = gp_stroke_weightmode_draw_poll;
+}
+
/* ==================== */
void ED_keymap_gpencil(wmKeyConfig *keyconf)
@@ -210,8 +477,25 @@ void ED_keymap_gpencil(wmKeyConfig *keyconf)
ed_keymap_gpencil_painting_draw(keyconf);
ed_keymap_gpencil_painting_erase(keyconf);
ed_keymap_gpencil_painting_fill(keyconf);
+ ed_keymap_gpencil_painting_tint(keyconf);
ed_keymap_gpencil_sculpting(keyconf);
+ ed_keymap_gpencil_sculptpainting_smooth(keyconf);
+ ed_keymap_gpencil_sculptpainting_thickness(keyconf);
+ ed_keymap_gpencil_sculptpainting_strength(keyconf);
+ ed_keymap_gpencil_sculptpainting_grab(keyconf);
+ ed_keymap_gpencil_sculptpainting_push(keyconf);
+ ed_keymap_gpencil_sculptpainting_twist(keyconf);
+ ed_keymap_gpencil_sculptpainting_pinch(keyconf);
+ ed_keymap_gpencil_sculptpainting_randomize(keyconf);
+ ed_keymap_gpencil_sculptpainting_clone(keyconf);
ed_keymap_gpencil_weightpainting(keyconf);
+ ed_keymap_gpencil_weightpainting_draw(keyconf);
+ ed_keymap_gpencil_vertexpainting(keyconf);
+ ed_keymap_gpencil_vertexpainting_draw(keyconf);
+ ed_keymap_gpencil_vertexpainting_blur(keyconf);
+ ed_keymap_gpencil_vertexpainting_average(keyconf);
+ ed_keymap_gpencil_vertexpainting_smear(keyconf);
+ ed_keymap_gpencil_vertexpainting_replace(keyconf);
}
/* ****************************************** */
@@ -226,6 +510,12 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_draw);
WM_operatortype_append(GPENCIL_OT_fill);
+ WM_operatortype_append(GPENCIL_OT_vertex_paint);
+ WM_operatortype_append(GPENCIL_OT_vertex_color_brightness_contrast);
+ WM_operatortype_append(GPENCIL_OT_vertex_color_hsv);
+ WM_operatortype_append(GPENCIL_OT_vertex_color_invert);
+ WM_operatortype_append(GPENCIL_OT_vertex_color_levels);
+ WM_operatortype_append(GPENCIL_OT_vertex_color_set);
/* Guides ----------------------- */
@@ -238,6 +528,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_paintmode_toggle);
WM_operatortype_append(GPENCIL_OT_sculptmode_toggle);
WM_operatortype_append(GPENCIL_OT_weightmode_toggle);
+ WM_operatortype_append(GPENCIL_OT_vertexmode_toggle);
WM_operatortype_append(GPENCIL_OT_selection_opacity_toggle);
WM_operatortype_append(GPENCIL_OT_select);
@@ -253,6 +544,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_select_first);
WM_operatortype_append(GPENCIL_OT_select_last);
WM_operatortype_append(GPENCIL_OT_select_alternate);
+ WM_operatortype_append(GPENCIL_OT_select_vertex_color);
WM_operatortype_append(GPENCIL_OT_duplicate);
WM_operatortype_append(GPENCIL_OT_delete);
@@ -263,6 +555,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_move_to_layer);
WM_operatortype_append(GPENCIL_OT_layer_change);
+ WM_operatortype_append(GPENCIL_OT_layer_active);
WM_operatortype_append(GPENCIL_OT_set_active_material);
@@ -271,8 +564,10 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_snap_cursor_to_selected);
WM_operatortype_append(GPENCIL_OT_reproject);
+ WM_operatortype_append(GPENCIL_OT_recalc_geometry);
WM_operatortype_append(GPENCIL_OT_sculpt_paint);
+ WM_operatortype_append(GPENCIL_OT_weight_paint);
/* Editing (Buttons) ------------ */
@@ -288,6 +583,9 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_layer_duplicate);
WM_operatortype_append(GPENCIL_OT_layer_duplicate_object);
+ WM_operatortype_append(GPENCIL_OT_layer_mask_add);
+ WM_operatortype_append(GPENCIL_OT_layer_mask_remove);
+
WM_operatortype_append(GPENCIL_OT_hide);
WM_operatortype_append(GPENCIL_OT_reveal);
WM_operatortype_append(GPENCIL_OT_lock_all);
@@ -306,9 +604,11 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_convert);
+ WM_operatortype_append(GPENCIL_OT_image_to_grease_pencil);
+
WM_operatortype_append(GPENCIL_OT_stroke_arrange);
WM_operatortype_append(GPENCIL_OT_stroke_change_color);
- WM_operatortype_append(GPENCIL_OT_stroke_lock_color);
+ WM_operatortype_append(GPENCIL_OT_material_lock_unused);
WM_operatortype_append(GPENCIL_OT_stroke_apply_thickness);
WM_operatortype_append(GPENCIL_OT_stroke_cyclical_set);
WM_operatortype_append(GPENCIL_OT_stroke_caps_set);
@@ -325,8 +625,16 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_stroke_cutter);
WM_operatortype_append(GPENCIL_OT_stroke_trim);
WM_operatortype_append(GPENCIL_OT_stroke_merge_by_distance);
+ WM_operatortype_append(GPENCIL_OT_stroke_merge_material);
+
+ WM_operatortype_append(GPENCIL_OT_material_to_vertex_color);
+ WM_operatortype_append(GPENCIL_OT_extract_palette_vertex);
+
+ WM_operatortype_append(GPENCIL_OT_transform_fill);
+ WM_operatortype_append(GPENCIL_OT_reset_transform_fill);
- WM_operatortype_append(GPENCIL_OT_brush_presets_create);
+ WM_operatortype_append(GPENCIL_OT_brush_reset);
+ WM_operatortype_append(GPENCIL_OT_brush_reset_all);
/* vertex groups */
WM_operatortype_append(GPENCIL_OT_vertex_group_assign);
@@ -340,12 +648,13 @@ void ED_operatortypes_gpencil(void)
/* color handle */
WM_operatortype_append(GPENCIL_OT_lock_layer);
- WM_operatortype_append(GPENCIL_OT_color_isolate);
- WM_operatortype_append(GPENCIL_OT_color_hide);
- WM_operatortype_append(GPENCIL_OT_color_reveal);
- WM_operatortype_append(GPENCIL_OT_color_lock_all);
- WM_operatortype_append(GPENCIL_OT_color_unlock_all);
- WM_operatortype_append(GPENCIL_OT_color_select);
+ WM_operatortype_append(GPENCIL_OT_material_isolate);
+ WM_operatortype_append(GPENCIL_OT_material_hide);
+ WM_operatortype_append(GPENCIL_OT_material_reveal);
+ WM_operatortype_append(GPENCIL_OT_material_lock_all);
+ WM_operatortype_append(GPENCIL_OT_material_unlock_all);
+ WM_operatortype_append(GPENCIL_OT_material_select);
+ WM_operatortype_append(GPENCIL_OT_material_set);
/* Editing (Time) --------------- */
diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c
index 3d56cb0fcb1..2dd98bb8df1 100644
--- a/source/blender/editors/gpencil/gpencil_ops_versioning.c
+++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c
@@ -37,13 +37,13 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BKE_main.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
-#include "BKE_object.h"
+#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_object.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -51,8 +51,8 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "ED_object.h"
#include "ED_gpencil.h"
+#include "ED_object.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -117,9 +117,8 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain); /* added object */
/* convert grease pencil palettes (version >= 2.78) to materials and weights */
- for (const bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
- for (bGPDpalettecolor *palcolor = palette->colors.first; palcolor;
- palcolor = palcolor->next) {
+ LISTBASE_FOREACH (const bGPDpalette *, palette, &gpd->palettes) {
+ LISTBASE_FOREACH (bGPDpalettecolor *, palcolor, &palette->colors) {
/* create material slot */
Material *ma = BKE_gpencil_object_material_new(bmain, ob, palcolor->info, NULL);
@@ -130,21 +129,19 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
copy_v4_v4(gp_style->fill_rgba, palcolor->fill);
/* set basic settings */
- gp_style->pattern_gridsize = 0.1f;
gp_style->gradient_radius = 0.5f;
ARRAY_SET_ITEMS(gp_style->mix_rgba, 1.0f, 1.0f, 1.0f, 0.2f);
ARRAY_SET_ITEMS(gp_style->gradient_scale, 1.0f, 1.0f);
ARRAY_SET_ITEMS(gp_style->texture_scale, 1.0f, 1.0f);
- gp_style->texture_opacity = 1.0f;
gp_style->texture_pixsize = 100.0f;
- gp_style->flag |= GP_STYLE_STROKE_SHOW;
- gp_style->flag |= GP_STYLE_FILL_SHOW;
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ gp_style->flag |= GP_MATERIAL_FILL_SHOW;
/* fix strokes */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if ((gps->colorname[0] != '\0') && (STREQ(gps->colorname, palcolor->info))) {
gps->mat_nr = ob->totcol - 1;
gps->colorname[0] = '\0';
@@ -170,11 +167,10 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
}
if (is_annotation) {
- for (const bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
- for (bGPDpalettecolor *palcolor = palette->colors.first; palcolor;
- palcolor = palcolor->next) {
+ LISTBASE_FOREACH (const bGPDpalette *, palette, &gpd->palettes) {
+ LISTBASE_FOREACH (bGPDpalettecolor *, palcolor, &palette->colors) {
/* fix layers */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* unlock/unhide layer */
gpl->flag &= ~GP_LAYER_LOCKED;
gpl->flag &= ~GP_LAYER_HIDE;
@@ -182,8 +178,8 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
gpl->opacity = 1.0f;
/* disable tint */
gpl->tintcolor[3] = 0.0f;
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if ((gps->colorname[0] != '\0') && (STREQ(gps->colorname, palcolor->info))) {
/* copy color settings */
copy_v4_v4(gpl->color, palcolor->color);
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 09ff24f05fc..309329e4649 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -21,53 +21,55 @@
* \ingroup edgpencil
*/
-#include <stdio.h>
+#include <math.h>
#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_hash.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_rand.h"
#include "BLI_math_geom.h"
+#include "BLI_rand.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "PIL_time.h"
+#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_material_types.h"
-#include "DNA_brush_types.h"
#include "DNA_windowmanager_types.h"
-#include "BKE_colortools.h"
-#include "BKE_main.h"
#include "BKE_brush.h"
-#include "BKE_paint.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_report.h"
+#include "BKE_gpencil_geom.h"
#include "BKE_layer.h"
+#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_paint.h"
+#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_tracking.h"
#include "UI_view2d.h"
+#include "ED_clip.h"
#include "ED_gpencil.h"
-#include "ED_screen.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_clip.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
@@ -149,12 +151,14 @@ typedef struct tGPsdata {
/** current object. */
Object *ob;
+ /** Obeject eval. */
+ Object *ob_eval;
/** window where painting originated. */
wmWindow *win;
/** area where painting originated. */
- ScrArea *sa;
+ ScrArea *area;
/** region where painting originated. */
- ARegion *ar;
+ ARegion *region;
/** needed for GP_STROKE_2DSPACE. */
View2D *v2d;
/** for using the camera rect within the 3d view. */
@@ -215,6 +219,8 @@ typedef struct tGPsdata {
float imat[4][4];
float mat[4][4];
+ float diff_mat[4][4];
+
/** custom color - hack for enforcing a particular color for track/mask editing. */
float custom_color[4];
@@ -249,6 +255,10 @@ typedef struct tGPsdata {
tGPguide guide;
ReportList *reports;
+
+ /** Random settings by stroke */
+ GpRandomSettings random_settings;
+
} tGPsdata;
/* ------ */
@@ -270,11 +280,6 @@ static void gp_update_cache(bGPdata *gpd)
}
}
-static bool gp_stroke_added_check(tGPsdata *p)
-{
- return (p->gpf && p->gpf->strokes.last && p->flags & GP_PAINTFLAG_STROKEADDED);
-}
-
static void gp_stroke_added_enable(tGPsdata *p)
{
BLI_assert(p->gpf->strokes.last != NULL);
@@ -296,9 +301,9 @@ static void gp_session_validatebuffer(tGPsdata *p);
static bool gpencil_draw_poll(bContext *C)
{
if (ED_operator_regionactive(C)) {
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* 3D Viewport */
- if (sa->spacetype != SPACE_VIEW3D) {
+ if (area->spacetype != SPACE_VIEW3D) {
return false;
}
@@ -353,7 +358,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3])
if (p->ownerPtr.type == &RNA_Object) {
ob = (Object *)p->ownerPtr.data;
}
- ED_gp_get_drawing_reference(p->scene, ob, p->gpl, *p->align_flag, vec);
+ ED_gpencil_drawing_reference_get(p->scene, ob, *p->align_flag, vec);
}
/* Stroke Editing ---------------------------- */
@@ -411,7 +416,7 @@ static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps)
Object *obact = (Object *)p->ownerPtr.data;
float origin[3];
- RegionView3D *rv3d = p->ar->regiondata;
+ RegionView3D *rv3d = p->region->regiondata;
/* verify the stroke mode is CURSOR 3d space mode */
if ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) == 0) {
@@ -444,9 +449,13 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
}
int mval_i[2];
- round_v2i_v2fl(mval_i, mval);
+ float rmval[2];
+ rmval[0] = mval[0] - 0.5f;
+ rmval[1] = mval[1] - 0.5f;
+ round_v2i_v2fl(mval_i, rmval);
- if (gpencil_project_check(p) && (ED_view3d_autodist_simple(p->ar, mval_i, out, 0, depth))) {
+ if (gpencil_project_check(p) &&
+ (ED_view3d_autodist_simple(p->region, mval_i, out, 0, depth))) {
/* projecting onto 3D-Geometry
* - nothing more needs to be done here, since view_autodist_simple() has already done it
*/
@@ -468,12 +477,12 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
* works OK, but it could of course be improved. */
gp_get_3d_reference(p, rvec);
- zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL);
+ zfac = ED_view3d_calc_zfac(p->region->regiondata, rvec, NULL);
- if (ED_view3d_project_float_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
+ if (ED_view3d_project_float_global(p->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK) {
sub_v2_v2v2(mval_f, mval_prj, mval);
- ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac);
+ ED_view3d_win_to_delta(p->region, mval_f, dvec, zfac);
sub_v3_v3v3(out, rvec, dvec);
}
else {
@@ -482,49 +491,26 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
}
}
-/* apply jitter to stroke */
-static void gp_brush_jitter(bGPdata *gpd,
- Brush *brush,
- tGPspoint *pt,
- const float mval[2],
- const float pressure,
- float r_mval[2],
- RNG *rng)
+/* Apply jitter to stroke point. */
+static void gp_brush_jitter(bGPdata *gpd, tGPspoint *pt, const float amplitude)
{
- float tmp_pressure = pressure;
- if (brush->gpencil_settings->draw_jitter > 0.0f) {
- float curvef = BKE_curvemapping_evaluateF(brush->gpencil_settings->curve_jitter, 0, pressure);
- tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity;
- }
- /* exponential value */
- const float exfactor = (brush->gpencil_settings->draw_jitter + 2.0f) *
- (brush->gpencil_settings->draw_jitter + 2.0f);
- const float fac = BLI_rng_get_float(rng) * exfactor * tmp_pressure;
- /* Jitter is applied perpendicular to the mouse movement vector (2D space) */
- float mvec[2], svec[2];
- /* mouse movement in ints -> floats */
+ const float axis[2] = {0.0f, 1.0f};
+ /* Jitter is applied perpendicular to the mouse movement vector (2D space). */
+ float mvec[2];
+ /* Mouse movement in ints -> floats. */
if (gpd->runtime.sbuffer_used > 1) {
- mvec[0] = (mval[0] - (pt - 1)->x);
- mvec[1] = (mval[1] - (pt - 1)->y);
+ tGPspoint *pt_prev = pt - 1;
+ sub_v2_v2v2(mvec, &pt->x, &pt_prev->x);
normalize_v2(mvec);
- }
- else {
- mvec[0] = 0.0f;
- mvec[1] = 0.0f;
- }
- /* rotate mvec by 90 degrees... */
- svec[0] = -mvec[1];
- svec[1] = mvec[0];
- /* scale the displacement by the random, and apply */
- if (BLI_rng_get_float(rng) > 0.5f) {
- mul_v2_fl(svec, -fac);
- }
- else {
- mul_v2_fl(svec, fac);
- }
+ /* Rotate mvec by 90 degrees... */
+ float angle = angle_v2v2(mvec, axis);
+ /* Reduce noise in the direction of the stroke. */
+ mvec[0] *= cos(angle);
+ mvec[1] *= sin(angle);
- r_mval[0] = mval[0] + svec[0];
- r_mval[1] = mval[1] + svec[1];
+ /* Scale by displacement amount, and apply. */
+ madd_v2_v2fl(&pt->x, mvec, amplitude * 10.0f);
+ }
}
/* apply pressure change depending of the angle of the stroke to simulate a pen with shape */
@@ -533,7 +519,6 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa
float mvec[2];
float sen = brush->gpencil_settings->draw_angle_factor; /* sensitivity */
float fac;
- float mpressure;
/* default angle of brush in radians */
float angle = brush->gpencil_settings->draw_angle;
@@ -561,9 +546,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa
fac = 1.0f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */
/* interpolate with previous point for smoother transitions */
- mpressure = interpf(pt->pressure - (sen * fac), (pt - 1)->pressure, 0.3f);
- pt->pressure = mpressure;
-
+ pt->pressure = interpf(pt->pressure - (sen * fac), (pt - 1)->pressure, 0.3f);
CLAMP(pt->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f);
}
}
@@ -580,6 +563,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa
static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
{
bGPdata *gpd = p->gpd;
+ GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
const short num_points = gpd->runtime.sbuffer_used;
/* Do nothing if not enough points to smooth out */
@@ -627,9 +611,12 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
strength += ptd->strength * average_fac;
}
- /* Based on influence factor, blend between original and optimal smoothed coordinate. */
- interp_v2_v2v2(c, c, sco, inf);
- copy_v2_v2(&ptc->x, c);
+ /* Based on influence factor, blend between original and optimal smoothed coordinate but not
+ * for Guide mode. */
+ if (!guide->use_guide) {
+ interp_v2_v2v2(c, c, sco, inf);
+ copy_v2_v2(&ptc->x, c);
+ }
/* Interpolate pressure. */
ptc->pressure = interpf(ptc->pressure, pressure, inf);
/* Interpolate strength. */
@@ -660,140 +647,131 @@ static void gp_smooth_segment(bGPdata *gpd, const float inf, int from_idx, int t
tGPspoint *ptd = &points[i];
float sco[2] = {0.0f};
+ float pressure = 0.0f;
+ float strength = 0.0f;
/* Compute smoothed coordinate by taking the ones nearby */
if (pta) {
madd_v2_v2fl(sco, &pta->x, average_fac);
+ pressure += pta->pressure * average_fac;
+ strength += pta->strength * average_fac;
}
else {
madd_v2_v2fl(sco, &ptc->x, average_fac);
+ pressure += ptc->pressure * average_fac;
+ strength += ptc->strength * average_fac;
}
if (ptb) {
madd_v2_v2fl(sco, &ptb->x, average_fac);
+ pressure += ptb->pressure * average_fac;
+ strength += ptb->strength * average_fac;
}
else {
madd_v2_v2fl(sco, &ptc->x, average_fac);
+ pressure += ptc->pressure * average_fac;
+ strength += ptc->strength * average_fac;
}
madd_v2_v2fl(sco, &ptc->x, average_fac);
+ pressure += ptc->pressure * average_fac;
+ strength += ptc->strength * average_fac;
madd_v2_v2fl(sco, &ptd->x, average_fac);
+ pressure += ptd->pressure * average_fac;
+ strength += ptd->strength * average_fac;
/* Based on influence factor, blend between original and optimal smoothed coordinate. */
interp_v2_v2v2(&ptc->x, &ptc->x, sco, inf);
+
+ /* Interpolate pressure. */
+ ptc->pressure = interpf(ptc->pressure, pressure, inf);
+ /* Interpolate strength. */
+ ptc->strength = interpf(ptc->strength, strength, inf);
}
}
-/* Smooth all the sections created with fake events to avoid abrupt transitions.
- *
- * As the fake events add points between two real events, this produces a straight line, but if
- * there is 3 or more real points that used fakes, the stroke is not smooth and produces abrupt
- * angles.
- * This function reads these segments and finds the real points and smooth with the surrounding
- * points. */
-static void gp_smooth_fake_segments(tGPsdata *p)
+static void gp_apply_randomness(tGPsdata *p,
+ BrushGpencilSettings *brush_settings,
+ tGPspoint *pt,
+ const bool press,
+ const bool strength,
+ const bool uv)
{
bGPdata *gpd = p->gpd;
- Brush *brush = p->brush;
+ GpRandomSettings random_settings = p->random_settings;
+ float value = 0.0f;
+ /* Apply randomness to pressure. */
+ if ((brush_settings->draw_random_press > 0.0f) && (press)) {
+ if ((brush_settings->flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) {
+ float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f;
+ value = 1.0 + rand * 2.0 * brush_settings->draw_random_press;
+ }
+ else {
+ value = 1.0 + random_settings.pressure * brush_settings->draw_random_press;
+ }
- if (brush->gpencil_settings->input_samples < 2) {
- return;
+ /* Apply random curve. */
+ if (brush_settings->flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) {
+ value *= BKE_curvemapping_evaluateF(
+ brush_settings->curve_rand_pressure, 0, random_settings.pen_press);
+ }
+
+ pt->pressure *= value;
+ CLAMP(pt->pressure, 0.1f, 1.0f);
}
- tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
- tGPspoint *pt = NULL;
- /* Index where segment starts. */
- int from_idx = 0;
- /* Index where segment ends. */
- int to_idx = 0;
-
- bool doit = false;
- /* Loop all points except the extremes. */
- for (int i = 1; i < gpd->runtime.sbuffer_used - 1; i++) {
- pt = &points[i];
- bool is_fake = (bool)(pt->tflag & GP_TPOINT_FAKE);
- to_idx = i;
-
- /* Detect fake points in the stroke. */
- if ((!doit) && (is_fake)) {
- from_idx = i;
- doit = true;
- }
- /* If detect control point after fake points, select a segment with same length in both sides,
- * except if it is more than stroke length. */
- if ((doit) && (!is_fake)) {
- if (i + (i - from_idx) < gpd->runtime.sbuffer_used - 1) {
- to_idx = i + (i - from_idx);
- /* Smooth this segments (need loop to get cumulative smooth). */
- for (int r = 0; r < 5; r++) {
- gp_smooth_segment(gpd, 0.1f, from_idx, to_idx);
- }
- }
- else {
- break;
- }
- /* Reset to new segments. */
- from_idx = i;
- doit = false;
+ /* Apply randomness to color strength. */
+ if ((brush_settings->draw_random_strength) && (strength)) {
+ if ((brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) {
+ float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f;
+ value = 1.0 + rand * brush_settings->draw_random_strength;
+ }
+ else {
+ value = 1.0 + random_settings.strength * brush_settings->draw_random_strength;
}
- }
-}
-/* Smooth the section added with fake events when pen moves very fast. */
-static void gp_smooth_fake_events(tGPsdata *p, int size_before, int size_after)
-{
- bGPdata *gpd = p->gpd;
- const short totpoints = size_after - size_before - 1;
- /* Do nothing if not enough data to smooth out. */
- if (totpoints < 1) {
- return;
+ /* Apply random curve. */
+ if (brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) {
+ value *= BKE_curvemapping_evaluateF(
+ brush_settings->curve_rand_pressure, 0, random_settings.pen_press);
+ }
+
+ pt->strength *= value;
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
- /* Back two points to get smoother effect. */
- size_before -= 2;
- CLAMP_MIN(size_before, 1);
+ /* Apply randomness to uv texture rotation. */
+ if ((brush_settings->uv_random > 0.0f) && (uv)) {
+ if ((brush_settings->flag2 & GP_BRUSH_USE_UV_AT_STROKE) == 0) {
+ float rand = BLI_hash_int_01(BLI_hash_int_2d((int)pt->x, gpd->runtime.sbuffer_used)) * 2.0f -
+ 1.0f;
+ value = rand * M_PI_2 * brush_settings->uv_random;
+ }
+ else {
+ value = random_settings.uv * M_PI_2 * brush_settings->uv_random;
+ }
- tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
- /* Extreme points. */
- const tGPspoint *pta = &points[size_before - 1];
- const tGPspoint *ptb = &points[size_after - 1];
- tGPspoint *pt1, *pt2;
- int i;
+ /* Apply random curve. */
+ if (brush_settings->flag2 & GP_BRUSH_USE_UV_RAND_PRESS) {
+ value *= BKE_curvemapping_evaluateF(
+ brush_settings->curve_rand_uv, 0, random_settings.pen_press);
+ }
- /* Get total length of the segment to smooth. */
- float totlen = 0.0f;
- for (i = size_before; i < size_after; i++) {
- pt1 = &points[i - 1];
- pt2 = &points[i];
- totlen += len_v2v2(&pt1->x, &pt2->x);
- }
- /* Smooth interpolating the position of the points. */
- float pointlen = 0.0f;
- for (i = size_before; i < size_after - 1; i++) {
- pt1 = &points[i - 1];
- pt2 = &points[i];
- pointlen += len_v2v2(&pt1->x, &pt2->x);
- pt2->pressure = interpf(ptb->pressure, pta->pressure, pointlen / totlen);
- pt2->strength = interpf(ptb->strength, pta->strength, pointlen / totlen);
+ pt->uv_rot += value;
+ CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
}
}
/* add current stroke-point to buffer (returns whether point was successfully added) */
-static short gp_stroke_addpoint(
- tGPsdata *p, const float mval[2], float pressure, double curtime, bool is_fake)
+static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime)
{
bGPdata *gpd = p->gpd;
Brush *brush = p->brush;
+ BrushGpencilSettings *brush_settings = p->brush->gpencil_settings;
tGPspoint *pt;
- ToolSettings *ts = p->scene->toolsettings;
Object *obact = (Object *)p->ownerPtr.data;
- Depsgraph *depsgraph = p->depsgraph;
- RegionView3D *rv3d = p->ar->regiondata;
- View3D *v3d = p->sa->spacedata.first;
- MaterialGPencilStyle *gp_style = p->material->gp_style;
- const int def_nr = obact->actdef - 1;
- const bool have_weight = (bool)BLI_findlink(&obact->defbase, def_nr);
+ RegionView3D *rv3d = p->region->regiondata;
/* check painting mode */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
@@ -845,108 +823,60 @@ static short gp_stroke_addpoint(
/* get pointer to destination point */
pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used);
- /* Set if point was created by fake events. */
- if (is_fake) {
- pt->tflag |= GP_TPOINT_FAKE;
- }
- else {
- pt->tflag &= ~GP_TPOINT_FAKE;
- }
-
/* store settings */
+ pt->strength = brush_settings->draw_strength;
+ pt->pressure = 1.0f;
+ pt->uv_rot = 0.0f;
+ copy_v2_v2(&pt->x, mval);
+
/* pressure */
- if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
- float curvef = BKE_curvemapping_evaluateF(
- brush->gpencil_settings->curve_sensitivity, 0, pressure);
- pt->pressure = curvef * brush->gpencil_settings->draw_sensitivity;
- }
- else {
- pt->pressure = 1.0f;
+ if (brush_settings->flag & GP_BRUSH_USE_PRESSURE) {
+ pt->pressure *= BKE_curvemapping_evaluateF(brush_settings->curve_sensitivity, 0, pressure);
}
- /* Apply jitter to position */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_jitter > 0.0f)) {
- float r_mval[2];
- const float jitpress = (brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) ?
- pressure :
- 1.0f;
- gp_brush_jitter(gpd, brush, pt, mval, jitpress, r_mval, p->rng);
- copy_v2_v2(&pt->x, r_mval);
- }
- else {
- copy_v2_v2(&pt->x, mval);
- }
- /* apply randomness to pressure */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_random_press > 0.0f)) {
- float curvef = BKE_curvemapping_evaluateF(
- brush->gpencil_settings->curve_sensitivity, 0, pressure);
- float tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity;
- if (BLI_rng_get_float(p->rng) > 0.5f) {
- pt->pressure -= tmp_pressure * brush->gpencil_settings->draw_random_press *
- BLI_rng_get_float(p->rng);
- }
- else {
- pt->pressure += tmp_pressure * brush->gpencil_settings->draw_random_press *
- BLI_rng_get_float(p->rng);
- }
- CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f);
+ /* color strength */
+ if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
+ pt->strength *= BKE_curvemapping_evaluateF(brush_settings->curve_strength, 0, pressure);
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
- /* apply randomness to uv texture rotation */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->uv_random > 0.0f)) {
- if (BLI_rng_get_float(p->rng) > 0.5f) {
- pt->uv_rot = (BLI_rng_get_float(p->rng) * M_PI * -1) * brush->gpencil_settings->uv_random;
- }
- else {
- pt->uv_rot = (BLI_rng_get_float(p->rng) * M_PI) * brush->gpencil_settings->uv_random;
+ /* Set vertex colors for buffer. */
+ ED_gpencil_sbuffer_vertex_color_set(p->depsgraph,
+ p->ob,
+ p->scene->toolsettings,
+ p->brush,
+ p->material,
+ p->random_settings.hsv,
+ p->random_settings.pen_press);
+
+ if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) {
+ /* Apply jitter to position */
+ if (brush_settings->draw_jitter > 0.0f) {
+ float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f;
+ float jitpress = 1.0f;
+ if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
+ jitpress = BKE_curvemapping_evaluateF(brush_settings->curve_jitter, 0, pressure);
+ }
+ /* FIXME the +2 means minimum jitter is 4 which is a bit strange for UX. */
+ const float exp_factor = brush_settings->draw_jitter + 2.0f;
+ const float fac = rand * square_f(exp_factor) * jitpress;
+ gp_brush_jitter(gpd, pt, fac);
}
- CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
- }
- else {
- pt->uv_rot = 0.0f;
+
+ /* Apply other randomness. */
+ gp_apply_randomness(p, brush_settings, pt, true, true, true);
}
/* apply angle of stroke to brush size */
- if (brush->gpencil_settings->draw_angle_factor != 0.0f) {
+ if (brush_settings->draw_angle_factor != 0.0f) {
gp_brush_angle(gpd, brush, pt, mval);
}
- /* color strength */
- if (brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
- float curvef = BKE_curvemapping_evaluateF(
- brush->gpencil_settings->curve_strength, 0, pressure);
- float tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity;
-
- pt->strength = tmp_pressure * brush->gpencil_settings->draw_strength;
- }
- else {
- pt->strength = brush->gpencil_settings->draw_strength;
- }
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
-
- /* apply randomness to color strength */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_random_strength > 0.0f)) {
- if (BLI_rng_get_float(p->rng) > 0.5f) {
- pt->strength -= pt->strength * brush->gpencil_settings->draw_random_strength *
- BLI_rng_get_float(p->rng);
- }
- else {
- pt->strength += pt->strength * brush->gpencil_settings->draw_random_strength *
- BLI_rng_get_float(p->rng);
- }
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- }
-
/* point time */
pt->time = (float)(curtime - p->inittime);
/* point uv (only 3d view) */
- if ((p->sa->spacetype == SPACE_VIEW3D) && (gpd->runtime.sbuffer_used > 0)) {
- float pixsize = gp_style->texture_pixsize / 1000000.0f;
+ if ((p->area->spacetype == SPACE_VIEW3D) && (gpd->runtime.sbuffer_used > 0)) {
tGPspoint *ptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
bGPDspoint spt, spt2;
@@ -954,17 +884,14 @@ static short gp_stroke_addpoint(
float origin[3];
gp_get_3d_reference(p, origin);
/* reproject current */
- ED_gpencil_tpoint_to_point(p->ar, origin, pt, &spt);
+ ED_gpencil_tpoint_to_point(p->region, origin, pt, &spt);
ED_gp_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt);
/* reproject previous */
- ED_gpencil_tpoint_to_point(p->ar, origin, ptb, &spt2);
+ ED_gpencil_tpoint_to_point(p->region, origin, ptb, &spt2);
ED_gp_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2);
- p->totpixlen += len_v3v3(&spt.x, &spt2.x) / pixsize;
+ p->totpixlen += len_v3v3(&spt.x, &spt2.x);
pt->uv_fac = p->totpixlen;
- if ((gp_style) && (gp_style->sima)) {
- pt->uv_fac /= gp_style->sima->gen_x;
- }
}
else {
p->totpixlen = 0.0f;
@@ -974,7 +901,7 @@ static short gp_stroke_addpoint(
/* increment counters */
gpd->runtime.sbuffer_used++;
- /* smooth while drawing previous points with a reduction factor for previous */
+ /* Smooth while drawing previous points with a reduction factor for previous. */
if (brush->gpencil_settings->active_smooth > 0.0f) {
for (int s = 0; s < 3; s++) {
gp_smooth_buffer(p,
@@ -983,98 +910,11 @@ static short gp_stroke_addpoint(
}
}
- return GP_STROKEADD_NORMAL;
- }
- else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
-
- /* enable special flag for drawing engine */
- gpd->flag |= GP_DATA_STROKE_POLYGON;
-
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- /* get pointer to destination point */
- pt = (tGPspoint *)(gpd->runtime.sbuffer);
-
- /* store settings */
- copy_v2_v2(&pt->x, mval);
- /* T44932 - Pressure vals are unreliable, so ignore for now */
- pt->pressure = 1.0f;
- pt->strength = 1.0f;
- pt->time = (float)(curtime - p->inittime);
-
- /* if there's stroke for this poly line session add (or replace last) point
- * to stroke. This allows to draw lines more interactively (see new segment
- * during mouse slide, e.g.)
- */
- if (gp_stroke_added_check(p)) {
- bGPDstroke *gps = p->gpf->strokes.last;
- bGPDspoint *pts;
- MDeformVert *dvert = NULL;
-
- /* First time point is adding to temporary buffer (need to allocate new point in stroke) */
- if (gpd->runtime.sbuffer_used == 0) {
- gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
- if (gps->dvert != NULL) {
- gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1));
- }
- gps->totpoints++;
- }
-
- pts = &gps->points[gps->totpoints - 1];
- if (gps->dvert != NULL) {
- dvert = &gps->dvert[gps->totpoints - 1];
- }
- /* special case for poly lines: normally,
- * depth is needed only when creating new stroke from buffer,
- * but poly lines are converting to stroke instantly,
- * so initialize depth buffer before converting coordinates
- */
- if (gpencil_project_check(p)) {
- view3d_region_operator_needs_opengl(p->win, p->ar);
- ED_view3d_autodist_init(
- p->depsgraph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
- }
-
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL);
- /* reproject to plane (only in 3d space) */
- gp_reproject_toplane(p, gps);
- /* if parented change position relative to parent object */
- gp_apply_parent_point(depsgraph, obact, gpd, gpl, pts);
- /* copy pressure and time */
- pts->pressure = pt->pressure;
- pts->strength = pt->strength;
- pts->time = pt->time;
- pts->uv_fac = pt->uv_fac;
- pts->uv_rot = pt->uv_rot;
-
- if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
- BKE_gpencil_dvert_ensure(gps);
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
- if (dw) {
- dw->weight = ts->vgroup_weight;
- }
- }
- else {
- if (dvert != NULL) {
- dvert->totweight = 0;
- dvert->dw = NULL;
- }
- }
-
- /* force fill recalc */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- /* drawing batch cache is dirty now */
- gp_update_cache(p->gpd);
- }
-
- /* increment counters */
- if (gpd->runtime.sbuffer_used == 0) {
- gpd->runtime.sbuffer_used++;
- }
+ /* Update evaluated data. */
+ ED_gpencil_sbuffer_update_eval(gpd, p->ob_eval);
return GP_STROKEADD_NORMAL;
}
-
/* return invalid state for now... */
return GP_STROKEADD_INVALID;
}
@@ -1092,7 +932,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
ToolSettings *ts = p->scene->toolsettings;
Depsgraph *depsgraph = p->depsgraph;
Object *obact = (Object *)p->ownerPtr.data;
- RegionView3D *rv3d = p->ar->regiondata;
+ RegionView3D *rv3d = p->region->regiondata;
const int def_nr = obact->actdef - 1;
const bool have_weight = (bool)BLI_findlink(&obact->defbase, def_nr);
const char *align_flag = &ts->gpencil_v3d_align;
@@ -1140,42 +980,25 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
return;
}
- /* special case for poly line -- for already added stroke during session
- * coordinates are getting added to stroke immediately to allow more
- * interactive behavior
- */
- if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
- /* be sure to hide any lazy cursor */
- ED_gpencil_toggle_brush_cursor(p->C, true, NULL);
-
- if (gp_stroke_added_check(p)) {
- return;
- }
- }
-
/* allocate memory for a new stroke */
gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
/* copy appropriate settings for stroke */
gps->totpoints = totelem;
gps->thickness = brush->size;
- gps->gradient_f = brush->gpencil_settings->gradient_f;
- copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s);
+ gps->fill_opacity_fac = 1.0f;
+ gps->hardeness = brush->gpencil_settings->hardeness;
+ copy_v2_v2(gps->aspect_ratio, brush->gpencil_settings->aspect_ratio);
gps->flag = gpd->runtime.sbuffer_sflag;
gps->inittime = p->inittime;
-
- /* enable recalculation flag by default (only used if hq fill) */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->uv_scale = 1.0f;
/* allocate enough memory for a continuous array for storage points */
const int subdivide = brush->gpencil_settings->draw_subdivide;
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->dvert = NULL;
- /* initialize triangle memory to dummy data */
- gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
/* drawing batch cache is dirty now */
gp_update_cache(p->gpd);
/* set pointer to first non-initialized point */
@@ -1184,6 +1007,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
dvert = gps->dvert + (gps->totpoints - totelem);
}
+ /* Apply the vertex color to fill. */
+ ED_gpencil_fill_vertex_color_set(ts, brush, gps);
+
/* copy points from the buffer to the stroke */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
/* straight lines only -> only endpoints */
@@ -1197,12 +1023,16 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt->pressure = ptc->pressure;
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ copy_v4_v4(pt->vert_color, ptc->vert_color);
pt->time = ptc->time;
+ /* Apply the vertex color to point. */
+ ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc);
+
pt++;
if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
BKE_gpencil_dvert_ensure(gps);
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr);
if (dw) {
dw->weight = ts->vgroup_weight;
}
@@ -1228,10 +1058,12 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt->time = ptc->time;
+ /* Apply the vertex color to point. */
+ ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc);
if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
BKE_gpencil_dvert_ensure(gps);
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr);
if (dw) {
dw->weight = ts->vgroup_weight;
}
@@ -1249,7 +1081,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt = gps->points;
for (i = 0; i < gps->totpoints; i++, pt++) {
/* if parented change position relative to parent object */
- gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
+ gp_apply_parent_point(depsgraph, obact, gpl, pt);
}
/* if camera view, reproject flat to view to avoid perspective effect */
@@ -1257,40 +1089,6 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
ED_gpencil_project_stroke_to_view(p->C, p->gpl, gps);
}
}
- else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
- /* first point */
- ptc = gpd->runtime.sbuffer;
-
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* reproject to plane (only in 3d space) */
- gp_reproject_toplane(p, gps);
- /* if parented change position relative to parent object */
- gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
- /* if camera view, reproject flat to view to avoid perspective effect */
- if (is_camera) {
- ED_gpencil_project_stroke_to_view(p->C, p->gpl, gps);
- }
- /* copy pressure and time */
- pt->pressure = ptc->pressure;
- pt->strength = ptc->strength;
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- pt->time = ptc->time;
-
- if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
- BKE_gpencil_dvert_ensure(gps);
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
- if (dw) {
- dw->weight = ts->vgroup_weight;
- }
- }
- else {
- if (dvert != NULL) {
- dvert->totweight = 0;
- dvert->dw = NULL;
- }
- }
- }
else {
float *depth_arr = NULL;
@@ -1306,9 +1104,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
round_v2i_v2fl(mval_i, &ptc->x);
- if ((ED_view3d_autodist_depth(p->ar, mval_i, depth_margin, depth_arr + i) == 0) &&
+ if ((ED_view3d_autodist_depth(p->region, mval_i, depth_margin, depth_arr + i) == 0) &&
(i && (ED_view3d_autodist_depth_seg(
- p->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
+ p->region, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
interp_depth = true;
}
else {
@@ -1367,9 +1165,6 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
}
- /* Smooth any point created with fake events when the mouse/pen move very fast. */
- gp_smooth_fake_segments(p);
-
pt = gps->points;
dvert = gps->dvert;
@@ -1383,9 +1178,12 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt->pressure = ptc->pressure;
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ copy_v4_v4(pt->vert_color, ptc->vert_color);
pt->time = ptc->time;
pt->uv_fac = ptc->uv_fac;
pt->uv_rot = ptc->uv_rot;
+ /* Apply the vertex color to point. */
+ ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc);
if (dvert != NULL) {
dvert->totweight = 0;
@@ -1398,11 +1196,6 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) && (subdivide > 0)) {
gp_subdivide_stroke(gps, subdivide);
}
- /* apply randomness to stroke */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_random_sub > 0.0f)) {
- gp_randomize_stroke(gps, brush, p->rng);
- }
/* Smooth stroke after subdiv - only if there's something to do for each iteration,
* the factor is reduced to get a better smoothing
@@ -1412,33 +1205,33 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
float reduce = 0.0f;
for (int r = 0; r < brush->gpencil_settings->draw_smoothlvl; r++) {
for (i = 0; i < gps->totpoints - 1; i++) {
- BKE_gpencil_smooth_stroke(gps, i, brush->gpencil_settings->draw_smoothfac - reduce);
- BKE_gpencil_smooth_stroke_strength(gps, i, brush->gpencil_settings->draw_smoothfac);
+ BKE_gpencil_stroke_smooth(gps, i, brush->gpencil_settings->draw_smoothfac - reduce);
+ BKE_gpencil_stroke_smooth_strength(gps, i, brush->gpencil_settings->draw_smoothfac);
}
reduce += 0.25f; /* reduce the factor */
}
}
+ /* If reproject the stroke using Stroke mode, need to apply a smooth because
+ * the reprojection creates small jitter. */
+ if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) {
+ float ifac = (float)brush->gpencil_settings->input_samples / 10.0f;
+ float sfac = interpf(1.0f, 0.2f, ifac);
+ for (i = 0; i < gps->totpoints - 1; i++) {
+ BKE_gpencil_stroke_smooth(gps, i, sfac);
+ BKE_gpencil_stroke_smooth_strength(gps, i, sfac);
+ }
+ }
/* Simplify adaptive */
if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
(brush->gpencil_settings->simplify_f > 0.0f)) {
- BKE_gpencil_simplify_stroke(gps, brush->gpencil_settings->simplify_f);
- }
-
- /* smooth thickness */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
- (brush->gpencil_settings->thick_smoothfac > 0.0f)) {
- for (int r = 0; r < brush->gpencil_settings->thick_smoothlvl * 2; r++) {
- for (i = 0; i < gps->totpoints - 1; i++) {
- BKE_gpencil_smooth_stroke_thickness(gps, i, brush->gpencil_settings->thick_smoothfac);
- }
- }
+ BKE_gpencil_stroke_simplify_adaptive(gps, brush->gpencil_settings->simplify_f);
}
/* reproject to plane (only in 3d space) */
gp_reproject_toplane(p, gps);
/* change position relative to parent object */
- gp_apply_parent(depsgraph, obact, gpd, gpl, gps);
+ gp_apply_parent(depsgraph, obact, gpl, gps);
/* if camera view, reproject flat to view to avoid perspective effect */
if (is_camera) {
ED_gpencil_project_stroke_to_view(p->C, p->gpl, gps);
@@ -1460,15 +1253,11 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
}
- /* calculate UVs along the stroke */
- ED_gpencil_calc_stroke_uv(obact, gps);
-
/* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke
* is added on listbase head because the drawing order is inverse and the head stroke is the
* first to draw. This is very useful for artist when drawing the background.
*/
- if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) &&
- (p->paintmode != GP_PAINTMODE_DRAW_POLY)) {
+ if (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) {
BLI_addhead(&p->gpf->strokes, gps);
}
else {
@@ -1479,7 +1268,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
BKE_gpencil_dvert_ensure(gps);
for (i = 0; i < gps->totpoints; i++) {
MDeformVert *ve = &gps->dvert[i];
- MDeformWeight *dw = defvert_verify_index(ve, def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(ve, def_nr);
if (dw) {
dw->weight = ts->vgroup_weight;
}
@@ -1489,9 +1278,12 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* post process stroke */
if ((p->brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
p->brush->gpencil_settings->flag & GP_BRUSH_TRIM_STROKE) {
- BKE_gpencil_trim_stroke(gps);
+ BKE_gpencil_stroke_trim(gps);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+
gp_stroke_added_enable(p);
}
@@ -1526,9 +1318,9 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
gp_settings = eraser->gpencil_settings;
}
- if ((gp_settings != NULL) && (p->sa->spacetype == SPACE_VIEW3D) &&
+ if ((gp_settings != NULL) && (p->area->spacetype == SPACE_VIEW3D) &&
(gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER)) {
- RegionView3D *rv3d = p->ar->regiondata;
+ RegionView3D *rv3d = p->region->regiondata;
bGPDlayer *gpl = p->gpl;
const int mval_i[2] = {x, y};
@@ -1537,9 +1329,9 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
float diff_mat[4][4];
/* calculate difference matrix if parent object */
- ED_gpencil_parent_location(p->depsgraph, obact, p->gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(p->depsgraph, obact, gpl, diff_mat);
- if (ED_view3d_autodist_simple(p->ar, mval_i, mval_3d, 0, NULL)) {
+ if (ED_view3d_autodist_simple(p->region, mval_i, mval_3d, 0, NULL)) {
const float depth_mval = view3d_point_depth(rv3d, mval_3d);
mul_v3_m4v3(fpt, diff_mat, &pt->x);
@@ -1639,31 +1431,22 @@ static void gp_stroke_soft_refine(bGPDstroke *gps)
}
/* eraser tool - evaluation per stroke */
-/* TODO: this could really do with some optimization (KD-Tree/BVH?) */
static void gp_stroke_eraser_dostroke(tGPsdata *p,
- bGPDlayer *gpl,
bGPDframe *gpf,
bGPDstroke *gps,
const float mval[2],
- const float mvalo[2],
const int radius,
const rcti *rect)
{
- Depsgraph *depsgraph = p->depsgraph;
- Object *obact = (Object *)p->ownerPtr.data;
Brush *eraser = p->eraser;
bGPDspoint *pt0, *pt1, *pt2;
int pc0[2] = {0};
int pc1[2] = {0};
int pc2[2] = {0};
int i;
- float diff_mat[4][4];
int mval_i[2];
round_v2i_v2fl(mval_i, mval);
- /* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, p->gpd, gpl, diff_mat);
-
if (gps->totpoints == 0) {
/* just free stroke */
gp_free_stroke(p->gpd, gpf, gps);
@@ -1672,7 +1455,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
/* only process if it hasn't been masked out... */
if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) {
bGPDspoint pt_temp;
- gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
+ gp_point_to_parent_space(gps->points, p->diff_mat, &pt_temp);
gp_point_to_xy(&p->gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
@@ -1696,7 +1479,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
/* get points to work with */
pt1 = gps->points + i;
bGPDspoint npt;
- gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_parent_space(pt1, p->diff_mat, &npt);
gp_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]);
/* do boundbox check first */
@@ -1748,7 +1531,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
bGPDspoint npt;
if (pt0) {
- gp_point_to_parent_space(pt0, diff_mat, &npt);
+ gp_point_to_parent_space(pt0, p->diff_mat, &npt);
gp_point_to_xy(&p->gsc, gps, &npt, &pc0[0], &pc0[1]);
}
else {
@@ -1756,10 +1539,10 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
copy_v2_v2_int(pc0, pc1);
}
- gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_parent_space(pt1, p->diff_mat, &npt);
gp_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]);
- gp_point_to_parent_space(pt2, diff_mat, &npt);
+ gp_point_to_parent_space(pt2, p->diff_mat, &npt);
gp_point_to_xy(&p->gsc, gps, &npt, &pc2[0], &pc2[1]);
/* Check that point segment of the boundbox of the eraser stroke */
@@ -1770,7 +1553,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
* eraser region (either within stroke painted, or on its lines)
* - this assumes that linewidth is irrelevant
*/
- if (gp_stroke_inside_circle(mval, mvalo, radius, pc0[0], pc0[1], pc2[0], pc2[1])) {
+ if (gp_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) {
if ((gp_stroke_eraser_is_occluded(p, pt0, pc0[0], pc0[1]) == false) ||
(gp_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) ||
(gp_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) {
@@ -1859,8 +1642,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
/* erase strokes which fall under the eraser strokes */
static void gp_stroke_doeraser(tGPsdata *p)
{
- bGPDlayer *gpl;
- bGPDstroke *gps, *gpn;
rcti rect;
Brush *brush = p->brush;
Brush *eraser = p->eraser;
@@ -1888,11 +1669,11 @@ static void gp_stroke_doeraser(tGPsdata *p)
rect.xmax = p->mval[0] + calc_radius;
rect.ymax = p->mval[1] + calc_radius;
- if (p->sa->spacetype == SPACE_VIEW3D) {
+ if (p->area->spacetype == SPACE_VIEW3D) {
if ((gp_settings != NULL) && (gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER)) {
- View3D *v3d = p->sa->spacedata.first;
- view3d_region_operator_needs_opengl(p->win, p->ar);
- ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, 0);
+ View3D *v3d = p->area->spacedata.first;
+ view3d_region_operator_needs_opengl(p->win, p->region);
+ ED_view3d_autodist_init(p->depsgraph, p->region, v3d, 0);
}
}
@@ -1900,29 +1681,36 @@ static void gp_stroke_doeraser(tGPsdata *p)
* only a subset of layers, it is harder to perform the same erase operation
* on multiple layers...
*/
- for (gpl = p->gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &p->gpd->layers) {
bGPDframe *gpf = gpl->actframe;
/* only affect layer if it's editable (and visible) */
- if (gpencil_layer_is_editable(gpl) == false) {
+ if (BKE_gpencil_layer_is_editable(gpl) == false) {
continue;
}
else if (gpf == NULL) {
continue;
}
+ /* calculate difference matrix */
+ BKE_gpencil_parent_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat);
/* loop over strokes, checking segments for intersections */
- for (gps = gpf->strokes.first; gps; gps = gpn) {
- gpn = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* check if the color is editable */
if (ED_gpencil_stroke_color_use(p->ob, gpl, gps) == false) {
continue;
}
+
+ /* Check if the stroke collide with mouse. */
+ if (!ED_gpencil_stroke_check_collision(&p->gsc, gps, p->mval, calc_radius, p->diff_mat)) {
+ continue;
+ }
+
/* Not all strokes in the datablock may be valid in the current editor/context
* (e.g. 2D space strokes in the 3D view, if the same datablock is shared)
*/
- if (ED_gpencil_stroke_can_use_direct(p->sa, gps)) {
- gp_stroke_eraser_dostroke(p, gpl, gpf, gps, p->mval, p->mvalo, calc_radius, &rect);
+ if (ED_gpencil_stroke_can_use_direct(p->area, gps)) {
+ gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, calc_radius, &rect);
}
}
}
@@ -1944,9 +1732,6 @@ static void gp_session_validatebuffer(tGPsdata *p)
/* reset flags */
gpd->runtime.sbuffer_sflag = 0;
- /* reset region */
- gpd->runtime.ar = NULL;
-
/* reset inittime */
p->inittime = 0.0;
@@ -1961,8 +1746,11 @@ static Brush *gp_get_default_eraser(Main *bmain, ToolSettings *ts)
{
Brush *brush_dft = NULL;
Paint *paint = &ts->gp_paint->paint;
- Brush *brush_old = paint->brush;
+ Brush *brush_prev = paint->brush;
for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
+ if (brush->gpencil_settings == NULL) {
+ continue;
+ }
if ((brush->ob_mode == OB_MODE_PAINT_GPENCIL) && (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
/* save first eraser to use later if no default */
if (brush_dft == NULL) {
@@ -1981,15 +1769,15 @@ static Brush *gp_get_default_eraser(Main *bmain, ToolSettings *ts)
}
/* create a new soft eraser brush */
else {
- brush_dft = BKE_brush_add_gpencil(bmain, ts, "Soft Eraser");
+ brush_dft = BKE_brush_add_gpencil(bmain, ts, "Soft Eraser", OB_MODE_PAINT_GPENCIL);
brush_dft->size = 30.0f;
- brush_dft->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
+ brush_dft->gpencil_settings->flag |= GP_BRUSH_DEFAULT_ERASER;
brush_dft->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
brush_dft->gpencil_tool = GPAINT_TOOL_ERASE;
brush_dft->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
/* reset current brush */
- BKE_paint_brush_set(paint, brush_old);
+ BKE_paint_brush_set(paint, brush_prev);
return brush_dft;
}
@@ -2026,13 +1814,19 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p)
/* if not exist, create a new one */
if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
- BKE_brush_gpencil_presets(bmain, ts);
+ BKE_brush_gpencil_paint_presets(bmain, ts, true);
changed = true;
}
- /* be sure curves are initializated */
+ /* Be sure curves are initializated. */
BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_sensitivity);
BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_strength);
BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_jitter);
+ BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_pressure);
+ BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_strength);
+ BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_uv);
+ BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_hue);
+ BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_saturation);
+ BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_value);
/* assign to temp tGPsdata */
p->brush = paint->brush;
@@ -2048,10 +1842,7 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p)
/* use radius of eraser */
p->radius = (short)p->eraser->size;
- /* GPXX: Need this update to synchronize brush with draw manager.
- * Maybe this update can be removed when the new tool system
- * will be in place, but while, we need this to keep drawing working.
- */
+ /* Need this update to synchronize brush with draw manager. */
if (changed) {
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
}
@@ -2063,33 +1854,11 @@ static void gp_init_colors(tGPsdata *p)
bGPdata *gpd = p->gpd;
Brush *brush = p->brush;
- MaterialGPencilStyle *gp_style = NULL;
-
/* use brush material */
p->material = BKE_gpencil_object_material_ensure_from_active_input_brush(p->bmain, p->ob, brush);
- /* assign color information to temp tGPsdata */
- gp_style = p->material->gp_style;
- if (gp_style) {
-
- /* set colors */
- if (gp_style->flag & GP_STYLE_STROKE_SHOW) {
- copy_v4_v4(gpd->runtime.scolor, gp_style->stroke_rgba);
- }
- else {
- /* if no stroke, use fill */
- copy_v4_v4(gpd->runtime.scolor, gp_style->fill_rgba);
- }
- copy_v4_v4(gpd->runtime.sfill, gp_style->fill_rgba);
- /* add some alpha to make easy the filling without hide strokes */
- if (gpd->runtime.sfill[3] > 0.8f) {
- gpd->runtime.sfill[3] = 0.8f;
- }
-
- gpd->runtime.mode = (short)gp_style->mode;
- gpd->runtime.bstroke_style = gp_style->stroke_style;
- gpd->runtime.bfill_style = gp_style->fill_style;
- }
+ gpd->runtime.matid = BKE_object_material_slot_find_index(p->ob, p->material);
+ gpd->runtime.sbuffer_brush = brush;
}
/* (re)init new painting data */
@@ -2098,7 +1867,7 @@ static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p)
Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = NULL;
ScrArea *curarea = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ToolSettings *ts = CTX_data_tool_settings(C);
Object *obact = CTX_data_active_object(C);
@@ -2125,18 +1894,15 @@ static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p)
switch (curarea->spacetype) {
/* supported views first */
case SPACE_VIEW3D: {
- /* View3D *v3d = curarea->spacedata.first; */
- /* RegionView3D *rv3d = ar->regiondata; */
-
/* set current area
* - must verify that region data is 3D-view (and not something else)
*/
/* CAUTION: If this is the "toolbar", then this will change on the first stroke */
- p->sa = curarea;
- p->ar = ar;
+ p->area = curarea;
+ p->region = region;
p->align_flag = &ts->gpencil_v3d_align;
- if (ar->regiondata == NULL) {
+ if (region->regiondata == NULL) {
p->status = GP_STATUS_ERROR;
if (G.debug & G_DEBUG) {
printf(
@@ -2147,7 +1913,7 @@ static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p)
}
if ((!obact) || (obact->type != OB_GPENCIL)) {
- View3D *v3d = p->sa->spacedata.first;
+ View3D *v3d = p->area->spacedata.first;
/* if active object doesn't exist or isn't a GP Object, create one */
const float *cur = p->scene->cursor.location;
@@ -2156,10 +1922,11 @@ static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p)
local_view_bits = v3d->local_view_uuid;
}
/* create new default object */
- obact = ED_gpencil_add_object(C, p->scene, cur, local_view_bits);
+ obact = ED_gpencil_add_object(C, cur, local_view_bits);
}
/* assign object after all checks to be sure we have one active */
p->ob = obact;
+ p->ob_eval = (Object *)DEG_get_evaluated_object(p->depsgraph, p->ob);
break;
}
@@ -2198,21 +1965,13 @@ static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p)
gp_init_drawing_brush(C, p);
/* setup active color */
- if (curarea->spacetype == SPACE_VIEW3D) {
- /* region where paint was originated */
- p->gpd->runtime.ar = CTX_wm_region(C);
+ /* region where paint was originated */
+ int totcol = p->ob->totcol;
+ gp_init_colors(p);
- /* NOTE: This is only done for 3D view, as Materials aren't used for
- * annotations in 2D editors
- */
- int totcol = p->ob->totcol;
-
- gp_init_colors(p);
-
- /* check whether the material was newly added */
- if (totcol != p->ob->totcol) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_PROPERTIES, NULL);
- }
+ /* check whether the material was newly added */
+ if (totcol != p->ob->totcol) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_PROPERTIES, NULL);
}
/* lock axis (in some modes, disable) */
@@ -2268,7 +2027,6 @@ static void gp_session_cleanup(tGPsdata *p)
/* free stroke buffer */
if (gpd->runtime.sbuffer) {
- /* printf("\t\tGP - free sbuffer\n"); */
MEM_SAFE_FREE(gpd->runtime.sbuffer);
gpd->runtime.sbuffer = NULL;
}
@@ -2294,12 +2052,13 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
{
Scene *scene = p->scene;
ToolSettings *ts = scene->toolsettings;
+ bool changed = false;
/* get active layer (or add a new one if non-existent) */
- p->gpl = BKE_gpencil_layer_getactive(p->gpd);
+ p->gpl = BKE_gpencil_layer_active_get(p->gpd);
if (p->gpl == NULL) {
p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("GP_Layer"), true);
-
+ changed = true;
if (p->custom_color[3]) {
copy_v3_v3(p->gpl->color, p->custom_color);
}
@@ -2312,46 +2071,28 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
return;
}
- /* get active frame (add a new one if not matching frame) */
+ /* Eraser mode: If no active strokes, just return. */
if (paintmode == GP_PAINTMODE_ERASER) {
- /* Eraser mode:
- * 1) Add new frames to all frames that we might touch,
- * 2) Ensure that p->gpf refers to the frame used for the active layer
- * (to avoid problems with other tools which expect it to exist)
- */
bool has_layer_to_erase = false;
- for (bGPDlayer *gpl = p->gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &p->gpd->layers) {
/* Skip if layer not editable */
- if (gpencil_layer_is_editable(gpl) == false) {
+ if (BKE_gpencil_layer_is_editable(gpl) == false) {
continue;
}
- /* Add a new frame if needed (and based off the active frame,
- * as we need some existing strokes to erase)
- *
- * Note: We don't add a new frame if there's nothing there now, so
- * -> If there are no frames at all, don't add one
- * -> If there are no strokes in that frame, don't add a new empty frame
- */
if (gpl->actframe && gpl->actframe->strokes.first) {
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
has_layer_to_erase = true;
+ break;
}
-
- /* XXX: we omit GP_FRAME_PAINT here for now,
- * as it is only really useful for doing
- * paintbuffer drawing
- */
}
- /* Ensure this gets set... */
- p->gpf = p->gpl->actframe;
-
if (has_layer_to_erase == false) {
p->status = GP_STATUS_ERROR;
return;
}
+ /* Ensure this gets set... */
+ p->gpf = p->gpl->actframe;
}
else {
/* Drawing Modes - Add a new frame if needed on the active layer */
@@ -2364,7 +2105,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode);
+ p->gpf = BKE_gpencil_layer_frame_get(p->gpl, CFRA, add_frame_mode);
if (p->gpf == NULL) {
p->status = GP_STATUS_ERROR;
@@ -2391,8 +2132,6 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* set special fill stroke mode */
if (p->disable_fill == true) {
p->gpd->runtime.sbuffer_sflag |= GP_STROKE_NOFILL;
- /* replace stroke color with fill color */
- copy_v4_v4(p->gpd->runtime.scolor, p->gpd->runtime.sfill);
}
/* set 'initial run' flag, which is only used to denote when a new stroke is starting */
@@ -2401,15 +2140,15 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* when drawing in the camera view, in 2D space, set the subrect */
p->subrect = NULL;
if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) {
- if (p->sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = p->sa->spacedata.first;
- RegionView3D *rv3d = p->ar->regiondata;
+ if (p->area->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = p->area->spacedata.first;
+ RegionView3D *rv3d = p->region->regiondata;
/* for camera view set the subrect */
if (rv3d->persp == RV3D_CAMOB) {
/* no shift */
ED_view3d_calc_camera_border(
- p->scene, depsgraph, p->ar, v3d, rv3d, &p->subrect_data, true);
+ p->scene, depsgraph, p->region, v3d, rv3d, &p->subrect_data, true);
p->subrect = &p->subrect_data;
}
}
@@ -2419,8 +2158,8 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
p->gsc.gpd = p->gpd;
p->gsc.gpl = p->gpl;
- p->gsc.sa = p->sa;
- p->gsc.ar = p->ar;
+ p->gsc.area = p->area;
+ p->gsc.region = p->region;
p->gsc.v2d = p->v2d;
p->gsc.subrect_data = p->subrect_data;
@@ -2430,13 +2169,21 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* check if points will need to be made in view-aligned space */
if (*p->align_flag & GP_PROJECT_VIEWSPACE) {
- switch (p->sa->spacetype) {
+ switch (p->area->spacetype) {
case SPACE_VIEW3D: {
p->gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
break;
}
}
}
+ if (!changed) {
+ /* Copy the brush to avoid a full tag (very slow). */
+ bGPdata *gpd_eval = (bGPdata *)p->ob_eval->data;
+ gpd_eval->runtime.sbuffer_brush = p->gpd->runtime.sbuffer_brush;
+ }
+ else {
+ gp_update_cache(p->gpd);
+ }
}
/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
@@ -2447,12 +2194,12 @@ static void gp_paint_strokeend(tGPsdata *p)
* the conversions will project the values correctly...
*/
if (gpencil_project_check(p)) {
- View3D *v3d = p->sa->spacedata.first;
+ View3D *v3d = p->area->spacedata.first;
/* need to restore the original projection settings before packing up */
- view3d_region_operator_needs_opengl(p->win, p->ar);
+ view3d_region_operator_needs_opengl(p->win, p->region);
ED_view3d_autodist_init(
- p->depsgraph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ p->depsgraph, p->region, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
}
/* check if doing eraser or not */
@@ -2481,7 +2228,6 @@ static void gp_paint_cleanup(tGPsdata *p)
p->gpf->flag &= ~GP_FRAME_PAINT;
}
}
-
/* ------------------------------- */
/* Helper callback for drawing the cursor itself */
@@ -2579,16 +2325,13 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
}
/* restore cursor to indicate end of drawing */
- if (p->sa->spacetype != SPACE_VIEW3D) {
+ if (p->area->spacetype != SPACE_VIEW3D) {
WM_cursor_modal_restore(CTX_wm_window(C));
}
else {
/* drawing batch cache is dirty now */
bGPdata *gpd = CTX_data_gpencil_data(C);
- if (gpd) {
- gpd->flag &= ~GP_DATA_STROKE_POLYGON;
- gp_update_cache(gpd);
- }
+ gp_update_cache(gpd);
}
/* clear undo stack */
@@ -2659,23 +2402,6 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
/* ------------------------------- */
-/* ensure that the correct cursor icon is set */
-static void gpencil_draw_cursor_set(tGPsdata *p)
-{
- UNUSED_VARS(p);
- return;
- /* Disable while we get a better cursor handling for direct input devices (Cintiq/Ipad)*/
-#if 0
- Brush *brush = p->brush;
- if ((p->paintmode == GP_PAINTMODE_ERASER) || (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
- WM_cursor_modal_set(p->win, WM_CURSOR_CROSS); /* XXX need a better cursor */
- }
- else {
- WM_cursor_modal_set(p->win, WM_CURSOR_NONE);
- }
-#endif
-}
-
/* update UI indicators of status, including cursor and header prints */
static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
{
@@ -2718,13 +2444,6 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
}
break;
}
- case GP_PAINTMODE_DRAW_POLY: {
- ED_workspace_status_text(
- C,
- TIP_("Grease Pencil Poly Session: LMB click to place next stroke vertex | "
- "Release Shift/ESC/Enter to end (or click outside this area)"));
- break;
- }
default: /* unhandled future cases */
{
ED_workspace_status_text(
@@ -2747,88 +2466,6 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
/* ------------------------------- */
-/* create a new stroke point at the point indicated by the painting context */
-static void gpencil_draw_apply(
- bContext *C, wmOperator *op, tGPsdata *p, Depsgraph *depsgraph, bool is_fake)
-{
- bGPdata *gpd = p->gpd;
- tGPspoint *pt = NULL;
-
- /* handle drawing/erasing -> test for erasing first */
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- /* do 'live' erasing now */
- gp_stroke_doeraser(p);
-
- /* store used values */
- copy_v2_v2(p->mvalo, p->mval);
- p->opressure = p->pressure;
- }
- /* Only add current point to buffer if mouse moved
- * (even though we got an event, it might be just noise). */
- else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) {
-
- /* if lazy mouse, interpolate the last and current mouse positions */
- if (GPENCIL_LAZY_MODE(p->brush, p->shift)) {
- float now_mouse[2];
- float last_mouse[2];
- copy_v2_v2(now_mouse, p->mval);
- copy_v2_v2(last_mouse, p->mvalo);
- interp_v2_v2v2(now_mouse, now_mouse, last_mouse, p->brush->smooth_stroke_factor);
- copy_v2_v2(p->mval, now_mouse);
- }
-
- /* try to add point */
- short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime, is_fake);
-
- /* handle errors while adding point */
- if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) {
- /* finish off old stroke */
- gp_paint_strokeend(p);
- /* And start a new one!!! Else, projection errors! */
- gp_paint_initstroke(p, p->paintmode, depsgraph);
-
- /* start a new stroke, starting from previous point */
- /* XXX Must manually reset inittime... */
- /* XXX We only need to reuse previous point if overflow! */
- if (ok == GP_STROKEADD_OVERFLOW) {
- p->inittime = p->ocurtime;
- gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime, is_fake);
- }
- else {
- p->inittime = p->curtime;
- }
- gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime, is_fake);
- }
- else if (ok == GP_STROKEADD_INVALID) {
- /* the painting operation cannot continue... */
- BKE_report(op->reports, RPT_ERROR, "Cannot paint stroke");
- p->status = GP_STATUS_ERROR;
-
- if (G.debug & G_DEBUG) {
- printf("Error: Grease-Pencil Paint - Add Point Invalid\n");
- }
- return;
- }
-
- /* store used values */
- copy_v2_v2(p->mvalo, p->mval);
- p->opressure = p->pressure;
- p->ocurtime = p->curtime;
-
- pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
- if (p->paintmode != GP_PAINTMODE_ERASER) {
- ED_gpencil_toggle_brush_cursor(C, true, &pt->x);
- }
- }
- else if ((p->brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) &&
- (gpd->runtime.sbuffer_used > 0)) {
- pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
- if (p->paintmode != GP_PAINTMODE_ERASER) {
- ED_gpencil_toggle_brush_cursor(C, true, &pt->x);
- }
- }
-}
-
/* Helper to rotate point around origin */
static void gp_rotate_v2_v2v2fl(float v[2],
const float p[2],
@@ -2907,7 +2544,7 @@ static void gp_origin_get(tGPsdata *p, float origin[2])
static void gpencil_speed_guide_init(tGPsdata *p, GP_Sculpt_Guide *guide)
{
/* calculate initial guide values */
- RegionView3D *rv3d = p->ar->regiondata;
+ RegionView3D *rv3d = p->region->regiondata;
float scale = 1.0f;
if (rv3d->is_persp) {
float vec[3];
@@ -2950,66 +2587,151 @@ static void gpencil_speed_guide_init(tGPsdata *p, GP_Sculpt_Guide *guide)
}
/* apply speed guide */
-static void gpencil_speed_guide(tGPsdata *p, GP_Sculpt_Guide *guide)
+static void gpencil_snap_to_guide(const tGPsdata *p, const GP_Sculpt_Guide *guide, float point[2])
{
switch (guide->type) {
default:
case GP_GUIDE_CIRCULAR: {
- dist_ensure_v2_v2fl(p->mval, p->guide.origin, p->guide.origin_distance);
+ dist_ensure_v2_v2fl(point, p->guide.origin, p->guide.origin_distance);
break;
}
case GP_GUIDE_RADIAL: {
if (guide->use_snapping && (guide->angle_snap > 0.0f)) {
- closest_to_line_v2(p->mval, p->mval, p->guide.rot_point, p->guide.origin);
+ closest_to_line_v2(point, point, p->guide.rot_point, p->guide.origin);
}
else {
- closest_to_line_v2(p->mval, p->mval, p->mvali, p->guide.origin);
+ closest_to_line_v2(point, point, p->mvali, p->guide.origin);
}
break;
}
case GP_GUIDE_PARALLEL: {
- closest_to_line_v2(p->mval, p->mval, p->mvali, p->guide.rot_point);
+ closest_to_line_v2(point, point, p->mvali, p->guide.rot_point);
if (guide->use_snapping && (guide->spacing > 0.0f)) {
- gp_snap_to_rotated_grid_fl(p->mval, p->guide.origin, p->guide.spacing, guide->angle);
+ gp_snap_to_rotated_grid_fl(point, p->guide.origin, p->guide.spacing, guide->angle);
}
break;
}
case GP_GUIDE_ISO: {
- closest_to_line_v2(p->mval, p->mval, p->mvali, p->guide.rot_point);
+ closest_to_line_v2(point, point, p->mvali, p->guide.rot_point);
if (guide->use_snapping && (guide->spacing > 0.0f)) {
- gp_snap_to_rotated_grid_fl(p->mval, p->guide.origin, p->guide.spacing, p->guide.rot_angle);
+ gp_snap_to_rotated_grid_fl(point, p->guide.origin, p->guide.spacing, p->guide.rot_angle);
}
break;
}
case GP_GUIDE_GRID: {
if (guide->use_snapping && (guide->spacing > 0.0f)) {
- closest_to_line_v2(p->mval, p->mval, p->mvali, p->guide.rot_point);
+ closest_to_line_v2(point, point, p->mvali, p->guide.rot_point);
if (p->straight == STROKE_HORIZONTAL) {
- p->mval[1] = gp_snap_to_grid_fl(p->mval[1], p->guide.origin[1], p->guide.spacing);
+ point[1] = gp_snap_to_grid_fl(point[1], p->guide.origin[1], p->guide.spacing);
}
else {
- p->mval[0] = gp_snap_to_grid_fl(p->mval[0], p->guide.origin[0], p->guide.spacing);
+ point[0] = gp_snap_to_grid_fl(point[0], p->guide.origin[0], p->guide.spacing);
}
}
else if (p->straight == STROKE_HORIZONTAL) {
- p->mval[1] = p->mvali[1]; /* replace y */
+ point[1] = p->mvali[1]; /* replace y */
}
else {
- p->mval[0] = p->mvali[0]; /* replace x */
+ point[0] = p->mvali[0]; /* replace x */
}
break;
}
}
}
+/* create a new stroke point at the point indicated by the painting context */
+static void gpencil_draw_apply(bContext *C, wmOperator *op, tGPsdata *p, Depsgraph *depsgraph)
+{
+ bGPdata *gpd = p->gpd;
+ tGPspoint *pt = NULL;
+
+ /* handle drawing/erasing -> test for erasing first */
+ if (p->paintmode == GP_PAINTMODE_ERASER) {
+ /* do 'live' erasing now */
+ gp_stroke_doeraser(p);
+
+ /* store used values */
+ copy_v2_v2(p->mvalo, p->mval);
+ p->opressure = p->pressure;
+ }
+ /* Only add current point to buffer if mouse moved
+ * (even though we got an event, it might be just noise). */
+ else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) {
+
+ /* if lazy mouse, interpolate the last and current mouse positions */
+ if (GPENCIL_LAZY_MODE(p->brush, p->shift)) {
+ float now_mouse[2];
+ float last_mouse[2];
+ copy_v2_v2(now_mouse, p->mval);
+ copy_v2_v2(last_mouse, p->mvalo);
+ interp_v2_v2v2(now_mouse, now_mouse, last_mouse, p->brush->smooth_stroke_factor);
+ copy_v2_v2(p->mval, now_mouse);
+
+ GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
+ bool is_speed_guide = ((guide->use_guide) &&
+ (p->brush && (p->brush->gpencil_tool == GPAINT_TOOL_DRAW)));
+ if (is_speed_guide) {
+ gpencil_snap_to_guide(p, guide, p->mval);
+ }
+ }
+
+ /* try to add point */
+ short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
+
+ /* handle errors while adding point */
+ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) {
+ /* finish off old stroke */
+ gp_paint_strokeend(p);
+ /* And start a new one!!! Else, projection errors! */
+ gp_paint_initstroke(p, p->paintmode, depsgraph);
+
+ /* start a new stroke, starting from previous point */
+ /* XXX Must manually reset inittime... */
+ /* XXX We only need to reuse previous point if overflow! */
+ if (ok == GP_STROKEADD_OVERFLOW) {
+ p->inittime = p->ocurtime;
+ gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime);
+ }
+ else {
+ p->inittime = p->curtime;
+ }
+ gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
+ }
+ else if (ok == GP_STROKEADD_INVALID) {
+ /* the painting operation cannot continue... */
+ BKE_report(op->reports, RPT_ERROR, "Cannot paint stroke");
+ p->status = GP_STATUS_ERROR;
+
+ if (G.debug & G_DEBUG) {
+ printf("Error: Grease-Pencil Paint - Add Point Invalid\n");
+ }
+ return;
+ }
+
+ /* store used values */
+ copy_v2_v2(p->mvalo, p->mval);
+ p->opressure = p->pressure;
+ p->ocurtime = p->curtime;
+
+ pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
+ if (p->paintmode != GP_PAINTMODE_ERASER) {
+ ED_gpencil_toggle_brush_cursor(C, true, &pt->x);
+ }
+ }
+ else if ((p->brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) &&
+ (gpd->runtime.sbuffer_used > 0)) {
+ pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
+ if (p->paintmode != GP_PAINTMODE_ERASER) {
+ ED_gpencil_toggle_brush_cursor(C, true, &pt->x);
+ }
+ }
+}
+
/* handle draw event */
static void gpencil_draw_apply_event(bContext *C,
wmOperator *op,
const wmEvent *event,
- Depsgraph *depsgraph,
- float x,
- float y,
- const bool is_fake)
+ Depsgraph *depsgraph)
{
tGPsdata *p = op->customdata;
GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
@@ -3019,13 +2741,12 @@ static void gpencil_draw_apply_event(bContext *C,
(p->brush && (p->brush->gpencil_tool == GPAINT_TOOL_DRAW)));
/* convert from window-space to area-space mouse coordinates
- * add any x,y override position for fake events
+ * add any x,y override position
*/
- p->mval[0] = (float)event->mval[0] - x;
- p->mval[1] = (float)event->mval[1] - y;
+ copy_v2fl_v2i(p->mval, event->mval);
p->shift = event->shift;
- /* verify direction for straight lines */
+ /* verify direction for straight lines and guides */
if ((is_speed_guide) ||
((event->alt > 0) && (RNA_boolean_get(op->ptr, "disable_straight") == false))) {
if (p->straight == 0) {
@@ -3051,6 +2772,8 @@ static void gpencil_draw_apply_event(bContext *C,
/* handle pressure sensitivity (which is supplied by tablets or otherwise 1.0) */
p->pressure = event->tablet.pressure;
+ /* By default use pen pressure for random curves but attenuated. */
+ p->random_settings.pen_press = pow(p->pressure, 3.0f);
/* Hack for pressure sensitive eraser on D+RMB when using a tablet:
* The pen has to float over the tablet surface, resulting in
@@ -3093,12 +2816,12 @@ static void gpencil_draw_apply_event(bContext *C,
p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
/* set values */
- copy_v2_v2(p->mvalo, p->mval);
p->opressure = p->pressure;
p->inittime = p->ocurtime = p->curtime;
p->straight = 0;
/* save initial mouse */
+ copy_v2_v2(p->mvalo, p->mval);
copy_v2_v2(p->mvali, p->mval);
if (is_speed_guide && !ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP) &&
@@ -3114,7 +2837,7 @@ static void gpencil_draw_apply_event(bContext *C,
}
/* wait for vector then add initial point */
- if (is_speed_guide && p->flags & GP_PAINTFLAG_REQ_VECTOR) {
+ if (is_speed_guide && (p->flags & GP_PAINTFLAG_REQ_VECTOR)) {
if (p->straight == 0) {
return;
}
@@ -3148,23 +2871,13 @@ static void gpencil_draw_apply_event(bContext *C,
p->mvali,
(p->straight == STROKE_VERTICAL) ? M_PI_2 : 0.0f);
}
-
- /* create fake events */
- float tmp[2];
- copy_v2_v2(tmp, p->mval);
- gpencil_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1], false);
- if (len_v2v2(p->mval, p->mvalo)) {
- sub_v2_v2v2(pt, p->mval, p->mvalo);
- gpencil_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1], false);
- }
- copy_v2_v2(p->mval, tmp);
}
/* check if stroke is straight or guided */
if ((p->paintmode != GP_PAINTMODE_ERASER) && ((p->straight) || (is_speed_guide))) {
/* guided stroke */
if (is_speed_guide) {
- gpencil_speed_guide(p, guide);
+ gpencil_snap_to_guide(p, guide, p->mval);
}
else if (p->straight == STROKE_HORIZONTAL) {
p->mval[1] = p->mvali[1]; /* replace y */
@@ -3186,11 +2899,11 @@ static void gpencil_draw_apply_event(bContext *C,
RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
/* apply the current latest drawing point */
- gpencil_draw_apply(C, op, p, depsgraph, is_fake);
+ gpencil_draw_apply(C, op, p, depsgraph);
/* force refresh */
/* just active area for now, since doing whole screen is too slow */
- ED_region_tag_redraw(p->ar);
+ ED_region_tag_redraw(p->region);
}
/* ------------------------------- */
@@ -3201,28 +2914,21 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
tGPsdata *p = NULL;
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- /* printf("GPencil - Starting Re-Drawing\n"); */
-
/* try to initialize context data needed while drawing */
if (!gpencil_draw_init(C, op, NULL)) {
MEM_SAFE_FREE(op->customdata);
- /* printf("\tGP - no valid data\n"); */
return OPERATOR_CANCELLED;
}
else {
p = op->customdata;
}
- /* printf("\tGP - Start redrawing stroke\n"); */
-
/* loop over the stroke RNA elements recorded (i.e. progress of mouse movement),
* setting the relevant values in context at each step, then applying
*/
RNA_BEGIN (op->ptr, itemptr, "stroke") {
float mousef[2];
- /* printf("\t\tGP - stroke elem\n"); */
-
/* get relevant data for this point from stroke */
RNA_float_get_array(&itemptr, "mouse", mousef);
p->mval[0] = mousef[0];
@@ -3252,12 +2958,10 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
}
/* apply this data as necessary now (as per usual) */
- gpencil_draw_apply(C, op, p, depsgraph, false);
+ gpencil_draw_apply(C, op, p, depsgraph);
}
RNA_END;
- /* printf("\tGP - done\n"); */
-
/* cleanup */
gpencil_draw_exit(C, op);
@@ -3280,7 +2984,7 @@ static void gpencil_guide_event_handling(bContext *C,
GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
/* Enter or exit set center point mode */
- if ((event->type == OKEY) && (event->val == KM_RELEASE)) {
+ if ((event->type == EVT_OKEY) && (event->val == KM_RELEASE)) {
if ((p->paintmode == GP_PAINTMODE_DRAW) && guide->use_guide &&
(guide->reference_point != GP_GUIDE_REF_OBJECT)) {
add_notifier = true;
@@ -3289,12 +2993,12 @@ static void gpencil_guide_event_handling(bContext *C,
}
}
/* Freehand mode, turn off speed guide */
- else if ((event->type == VKEY) && (event->val == KM_RELEASE)) {
+ else if ((event->type == EVT_VKEY) && (event->val == KM_RELEASE)) {
guide->use_guide = false;
add_notifier = true;
}
/* Alternate or flip direction */
- else if ((event->type == MKEY) && (event->val == KM_RELEASE)) {
+ else if ((event->type == EVT_MKEY) && (event->val == KM_RELEASE)) {
if (guide->type == GP_GUIDE_CIRCULAR) {
add_notifier = true;
guide->type = GP_GUIDE_RADIAL;
@@ -3313,7 +3017,7 @@ static void gpencil_guide_event_handling(bContext *C,
}
}
/* Line guides */
- else if ((event->type == LKEY) && (event->val == KM_RELEASE)) {
+ else if ((event->type == EVT_LKEY) && (event->val == KM_RELEASE)) {
add_notifier = true;
guide->use_guide = true;
if (event->ctrl) {
@@ -3329,7 +3033,7 @@ static void gpencil_guide_event_handling(bContext *C,
}
}
/* Point guide */
- else if ((event->type == CKEY) && (event->val == KM_RELEASE)) {
+ else if ((event->type == EVT_CKEY) && (event->val == KM_RELEASE)) {
add_notifier = true;
if (!guide->use_guide) {
guide->use_guide = true;
@@ -3346,7 +3050,7 @@ static void gpencil_guide_event_handling(bContext *C,
}
}
/* Change line angle */
- else if (ELEM(event->type, JKEY, KKEY) && (event->val == KM_RELEASE)) {
+ else if (ELEM(event->type, EVT_JKEY, EVT_KKEY) && (event->val == KM_RELEASE)) {
add_notifier = true;
float angle = guide->angle;
float adjust = (float)M_PI / 180.0f;
@@ -3356,7 +3060,7 @@ static void gpencil_guide_event_handling(bContext *C,
else if (!event->shift) {
adjust *= 15.0f;
}
- angle += (event->type == JKEY) ? adjust : -adjust;
+ angle += (event->type == EVT_JKEY) ? adjust : -adjust;
angle = angle_compat_rad(angle, M_PI);
guide->angle = angle;
}
@@ -3394,9 +3098,9 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
else {
/* don't erase empty frames */
bool has_layer_to_erase = false;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Skip if layer not editable */
- if (gpencil_layer_is_editable(gpl)) {
+ if (BKE_gpencil_layer_is_editable(gpl)) {
if (gpl->actframe && gpl->actframe->strokes.first) {
has_layer_to_erase = true;
break;
@@ -3422,37 +3126,29 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
else {
p = op->customdata;
}
+ /* Init random settings. */
+ ED_gpencil_init_random_settings(p->brush, event->mval, &p->random_settings);
/* TODO: set any additional settings that we can take from the events?
- * TODO? if tablet is erasing, force eraser to be on? */
-
- /* if eraser is on, draw radial aid */
+ * if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
gpencil_draw_toggle_eraser_cursor(C, p, true);
}
else {
ED_gpencil_toggle_brush_cursor(C, true, NULL);
}
- /* set cursor
- * NOTE: This may change later (i.e. intentionally via brush toggle,
- * or unintentionally if the user scrolls outside the area)...
- */
- gpencil_draw_cursor_set(p);
/* only start drawing immediately if we're allowed to do so... */
if (RNA_boolean_get(op->ptr, "wait_for_input") == false) {
/* hotkey invoked - start drawing */
- /* printf("\tGP - set first spot\n"); */
p->status = GP_STATUS_PAINTING;
/* handle the initial drawing - i.e. for just doing a simple dot */
- gpencil_draw_apply_event(
- C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f, false);
+ gpencil_draw_apply_event(C, op, event, CTX_data_ensure_evaluated_depsgraph(C));
op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
else {
/* toolbar invoked - don't start drawing yet... */
- /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */
op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
@@ -3486,10 +3182,10 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
}
/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
-static bool gpencil_area_exists(bContext *C, ScrArea *sa_test)
+static bool gpencil_area_exists(bContext *C, ScrArea *area_test)
{
- bScreen *sc = CTX_wm_screen(C);
- return (BLI_findindex(&sc->areabase, sa_test) != -1);
+ bScreen *screen = CTX_wm_screen(C);
+ return (BLI_findindex(&screen->areabase, area_test) != -1);
}
static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
@@ -3499,17 +3195,12 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
/* we must check that we're still within the area that we're set up to work from
* otherwise we could crash (see bug #20586)
*/
- if (CTX_wm_area(C) != p->sa) {
+ if (CTX_wm_area(C) != p->area) {
printf("\t\t\tGP - wrong area execution abort!\n");
p->status = GP_STATUS_ERROR;
}
- /* printf("\t\tGP - start stroke\n"); */
-
/* we may need to set up paint env again if we're resuming */
- /* XXX: watch it with the paintmode! in future,
- * it'd be nice to allow changing paint-mode when in sketching-sessions */
-
if (gp_session_initdata(C, op, p)) {
gp_paint_initstroke(p, p->paintmode, CTX_data_depsgraph_pointer(C));
}
@@ -3522,134 +3213,273 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
return op->customdata;
}
-static void gpencil_stroke_end(wmOperator *op)
+/* Apply pressure change depending of the angle of the stroke for a segment. */
+static void gp_brush_angle_segment(tGPsdata *p, tGPspoint *pt_prev, tGPspoint *pt)
{
- tGPsdata *p = op->customdata;
+ Brush *brush = p->brush;
+ /* Sensitivity. */
+ const float sen = brush->gpencil_settings->draw_angle_factor;
+ /* Default angle of brush in radians */
+ const float angle = brush->gpencil_settings->draw_angle;
- gp_paint_cleanup(p);
+ float mvec[2];
+ float fac;
- gpencil_undo_push(p->gpd);
+ /* angle vector of the brush with full thickness */
+ float v0[2] = {cos(angle), sin(angle)};
- gp_session_cleanup(p);
+ mvec[0] = pt->x - pt_prev->x;
+ mvec[1] = pt->y - pt_prev->y;
+ normalize_v2(mvec);
+ fac = 1.0f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */
+ /* interpolate with previous point for smoother transitions */
+ pt->pressure = interpf(pt->pressure - (sen * fac), pt_prev->pressure, 0.3f);
+ CLAMP(pt->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f);
+}
+
+/* Add arc points between two mouse events using the previous segment to determine the vertice of
+ * the arc.
+ * /+ CTL
+ * / |
+ * / |
+ * PtA +...|...+ PtB
+ * /
+ * /
+ * + PtA - 1
+ * /
+ * CTL is the vertice of the triangle created between PtA and PtB */
+static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments)
+{
+ bGPdata *gpd = p->gpd;
+ BrushGpencilSettings *brush_settings = p->brush->gpencil_settings;
- p->status = GP_STATUS_IDLING;
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ if (gpd->runtime.sbuffer_used < 3) {
+ tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
+ /* Apply other randomness to first points. */
+ for (int i = 0; i < gpd->runtime.sbuffer_used; i++) {
+ tGPspoint *pt = &points[i];
+ gp_apply_randomness(p, brush_settings, pt, false, false, true);
+ }
+ return;
+ }
+ int idx_prev = gpd->runtime.sbuffer_used;
- p->gpd = NULL;
- p->gpl = NULL;
- p->gpf = NULL;
-}
+ /* Add space for new arc points. */
+ gpd->runtime.sbuffer_used += segments - 1;
-/* Move last stroke in the listbase to the head
- * to be drawn below all previous strokes in the layer. */
-static void gpencil_move_last_stroke_to_back(bContext *C)
-{
- /* Move last stroke (the polygon) to head of the listbase stroke
- * to draw on back of all previous strokes. */
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ /* Check if still room in buffer or add more. */
+ gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure(
+ gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false);
- /* sanity checks */
- if (ELEM(NULL, gpd, gpl, gpl->actframe)) {
+ tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
+ tGPspoint *pt = NULL;
+ tGPspoint *pt_before = &points[idx_prev - 1]; /* current - 2 */
+ tGPspoint *pt_prev = &points[idx_prev - 2]; /* previous */
+
+ /* Create two vectors, previous and half way of the actual to get the vertex of the triangle
+ * for arc curve.
+ */
+ float v_prev[2], v_cur[2], v_half[2];
+ sub_v2_v2v2(v_cur, mval, &pt_prev->x);
+
+ sub_v2_v2v2(v_prev, &pt_prev->x, &pt_before->x);
+ interp_v2_v2v2(v_half, &pt_prev->x, mval, 0.5f);
+ sub_v2_v2(v_half, &pt_prev->x);
+
+ /* If angle is too sharp undo all changes and return. */
+ const float min_angle = DEG2RADF(120.0f);
+ float angle = angle_v2v2(v_prev, v_half);
+ if (angle < min_angle) {
+ gpd->runtime.sbuffer_used -= segments - 1;
return;
}
- bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps = gpf->strokes.last;
- if (ELEM(NULL, gps)) {
+ /* Project the half vector to the previous vector and calculate the mid projected point. */
+ float dot = dot_v2v2(v_prev, v_half);
+ float l = len_squared_v2(v_prev);
+ if (l > 0.0f) {
+ mul_v2_fl(v_prev, dot / l);
+ }
+
+ /* Calc the position of the control point. */
+ float ctl[2];
+ add_v2_v2v2(ctl, &pt_prev->x, v_prev);
+
+ float step = M_PI_2 / (float)(segments + 1);
+ float a = step;
+
+ float midpoint[2], start[2], end[2], cp1[2], corner[2];
+ mid_v2_v2v2(midpoint, &pt_prev->x, mval);
+ copy_v2_v2(start, &pt_prev->x);
+ copy_v2_v2(end, mval);
+ copy_v2_v2(cp1, ctl);
+
+ corner[0] = midpoint[0] - (cp1[0] - midpoint[0]);
+ corner[1] = midpoint[1] - (cp1[1] - midpoint[1]);
+ float stepcolor = 1.0f / segments;
+
+ tGPspoint *pt_step = pt_prev;
+ for (int i = 0; i < segments; i++) {
+ pt = &points[idx_prev + i - 1];
+ pt->x = corner[0] + (end[0] - corner[0]) * sinf(a) + (start[0] - corner[0]) * cosf(a);
+ pt->y = corner[1] + (end[1] - corner[1]) * sinf(a) + (start[1] - corner[1]) * cosf(a);
+
+ /* Set pressure and strength equals to previous. It will be smoothed later. */
+ pt->pressure = pt_prev->pressure;
+ pt->strength = pt_prev->strength;
+ /* Interpolate vertex color. */
+ interp_v4_v4v4(
+ pt->vert_color, pt_before->vert_color, pt_prev->vert_color, stepcolor * (i + 1));
+
+ /* Apply angle of stroke to brush size to interpolated points but slightly attenuated.. */
+ if (brush_settings->draw_angle_factor != 0.0f) {
+ gp_brush_angle_segment(p, pt_step, pt);
+ CLAMP(pt->pressure, pt_prev->pressure * 0.5f, 1.0f);
+ /* Use the previous interpolated point for next segment. */
+ pt_step = pt;
+ }
+
+ /* Apply other randomness. */
+ gp_apply_randomness(p, brush_settings, pt, false, false, true);
+
+ a += step;
+ }
+}
+
+static void gpencil_add_guide_points(const tGPsdata *p,
+ const GP_Sculpt_Guide *guide,
+ const float start[2],
+ const float end[2],
+ int segments)
+{
+ bGPdata *gpd = p->gpd;
+ if (gpd->runtime.sbuffer_used == 0) {
return;
}
- BLI_remlink(&gpf->strokes, gps);
- BLI_insertlinkbefore(&gpf->strokes, gpf->strokes.first, gps);
+ int idx_prev = gpd->runtime.sbuffer_used;
+
+ /* Add space for new points. */
+ gpd->runtime.sbuffer_used += segments - 1;
+
+ /* Check if still room in buffer or add more. */
+ gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure(
+ gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false);
+
+ tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
+ tGPspoint *pt = NULL;
+ tGPspoint *pt_before = &points[idx_prev - 1];
+
+ /* Use arc sampling for circular guide */
+ if (guide->type == GP_GUIDE_CIRCULAR) {
+ float cw = cross_tri_v2(start, p->guide.origin, end);
+ float angle = angle_v2v2v2(start, p->guide.origin, end);
+
+ float step = angle / (float)(segments + 1);
+ if (cw < 0.0f) {
+ step = -step;
+ }
+
+ float a = step;
+
+ for (int i = 0; i < segments; i++) {
+ pt = &points[idx_prev + i - 1];
+
+ gp_rotate_v2_v2v2fl(&pt->x, start, p->guide.origin, -a);
+ gpencil_snap_to_guide(p, guide, &pt->x);
+ a += step;
+
+ /* Set pressure and strength equals to previous. It will be smoothed later. */
+ pt->pressure = pt_before->pressure;
+ pt->strength = pt_before->strength;
+ copy_v4_v4(pt->vert_color, pt_before->vert_color);
+ }
+ }
+ else {
+ float step = 1.0f / (float)(segments + 1);
+ float a = step;
+
+ for (int i = 0; i < segments; i++) {
+ pt = &points[idx_prev + i - 1];
+
+ interp_v2_v2v2(&pt->x, start, end, a);
+ gpencil_snap_to_guide(p, guide, &pt->x);
+ a += step;
+
+ /* Set pressure and strength equals to previous. It will be smoothed later. */
+ pt->pressure = pt_before->pressure;
+ pt->strength = pt_before->strength;
+ copy_v4_v4(pt->vert_color, pt_before->vert_color);
+ }
+ }
}
-/* Add fake events for missing mouse movements when the artist draw very fast */
-static bool gpencil_add_fake_events(bContext *C, wmOperator *op, const wmEvent *event, tGPsdata *p)
+/**
+ * Add fake points for missing mouse movements when the artist draw very fast creating an arc
+ * with the vertex in the middle of the segment and using the angle of the previous segment.
+ */
+static void gpencil_add_fake_points(const wmEvent *event, tGPsdata *p)
{
Brush *brush = p->brush;
+ /* Lazy mode do not use fake events. */
+ if (GPENCIL_LAZY_MODE(brush, p->shift)) {
+ return;
+ }
+
GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
int input_samples = brush->gpencil_settings->input_samples;
- bool added_events = false;
- /* ensure sampling when using circular guide */
- if (guide->use_guide && (guide->type == GP_GUIDE_CIRCULAR)) {
+ bool is_speed_guide = ((guide->use_guide) &&
+ (p->brush && (p->brush->gpencil_tool == GPAINT_TOOL_DRAW)));
+
+ /* TODO: ensure sampling enough points when using circular guide,
+ but the arc must be around the center. (see if above to check other guides only)
+ */
+ if (is_speed_guide && (guide->type == GP_GUIDE_CIRCULAR)) {
input_samples = GP_MAX_INPUT_SAMPLES;
}
if (input_samples == 0) {
- return added_events;
+ return;
}
- RegionView3D *rv3d = p->ar->regiondata;
- float defaultpixsize = rv3d->pixsize * 1000.0f;
- int samples = (GP_MAX_INPUT_SAMPLES - input_samples + 1);
- float thickness = (float)brush->size;
+ int samples = GP_MAX_INPUT_SAMPLES - input_samples + 1;
- float pt[2], a[2], b[2];
- float vec[3];
- float scale = 1.0f;
+ float mouse_prv[2], mouse_cur[2];
+ float min_dist = 4.0f * samples;
- /* get pixel scale */
- gp_get_3d_reference(p, vec);
- mul_m4_v3(rv3d->persmat, vec);
- if (rv3d->is_persp) {
- scale = vec[2] * defaultpixsize;
- }
- else {
- scale = defaultpixsize;
- }
+ copy_v2_v2(mouse_prv, p->mvalo);
+ copy_v2fl_v2i(mouse_cur, event->mval);
- /* The thickness of the brush is reduced of thickness to get overlap dots */
- float dot_factor = 0.50f;
- if (samples < 2) {
- dot_factor = 0.05f;
- }
- else if (samples < 4) {
- dot_factor = 0.10f;
- }
- else if (samples < 7) {
- dot_factor = 0.3f;
- }
- else if (samples < 10) {
- dot_factor = 0.4f;
+ /* get distance in pixels */
+ float dist = len_v2v2(mouse_prv, mouse_cur);
+
+ /* get distance for circular guide */
+ if (is_speed_guide && (guide->type == GP_GUIDE_CIRCULAR)) {
+ float middle[2];
+ gpencil_snap_to_guide(p, guide, mouse_prv);
+ gpencil_snap_to_guide(p, guide, mouse_cur);
+ mid_v2_v2v2(middle, mouse_cur, mouse_prv);
+ gpencil_snap_to_guide(p, guide, middle);
+ dist = len_v2v2(mouse_prv, middle) + len_v2v2(middle, mouse_cur);
}
- float factor = ((thickness * dot_factor) / scale) * samples;
- copy_v2_v2(a, p->mvalo);
- b[0] = (float)event->mval[0] + 1.0f;
- b[1] = (float)event->mval[1] + 1.0f;
+ if ((dist > 3.0f) && (dist > min_dist)) {
+ int slices = (dist / min_dist) + 1;
- /* get distance in pixels */
- float dist = len_v2v2(a, b);
-
- /* for very small distances, add a half way point */
- if (dist <= 2.0f) {
- interp_v2_v2v2(pt, a, b, 0.5f);
- sub_v2_v2v2(pt, b, pt);
- /* create fake event */
- gpencil_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1], true);
- added_events = true;
- }
- else if (dist >= factor) {
- int slices = 2 + (int)((dist - 1.0) / factor);
- float n = 1.0f / slices;
- for (int i = 1; i < slices; i++) {
- interp_v2_v2v2(pt, a, b, n * i);
- sub_v2_v2v2(pt, b, pt);
- /* create fake event */
- gpencil_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1], true);
- added_events = true;
- }
- }
- return added_events;
+ if (is_speed_guide) {
+ gpencil_add_guide_points(p, guide, mouse_prv, mouse_cur, slices);
+ }
+ else {
+ gpencil_add_arc_points(p, mouse_cur, slices);
+ }
+ }
}
/* events handling during interactive drawing part of operator */
static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tGPsdata *p = op->customdata;
- ToolSettings *ts = CTX_data_tool_settings(C);
+ // ToolSettings *ts = CTX_data_tool_settings(C);
GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide;
/* default exit state - pass through to support MMB view nav, etc. */
@@ -3669,8 +3499,8 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
*/
if (p->status == GP_STATUS_IDLING) {
- ARegion *ar = CTX_wm_region(C);
- p->ar = ar;
+ ARegion *region = CTX_wm_region(C);
+ p->region = region;
}
/* special mode for editing control points */
@@ -3681,7 +3511,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
/* cancel */
- case ESCKEY:
+ case EVT_ESCKEY:
case RIGHTMOUSE: {
if (ELEM(event->val, KM_RELEASE)) {
drawmode = true;
@@ -3712,26 +3542,36 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* We don't pass on key events, GP is used with key-modifiers -
* prevents Dkey to insert drivers. */
if (ISKEYBOARD(event->type)) {
- if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY)) {
+ if (ELEM(event->type, EVT_LEFTARROWKEY, EVT_DOWNARROWKEY, EVT_RIGHTARROWKEY, EVT_UPARROWKEY)) {
/* allow some keys:
* - for frame changing [#33412]
* - for undo (during sketching sessions)
*/
}
- else if (event->type == ZKEY) {
+ else if (event->type == EVT_ZKEY) {
if (event->ctrl) {
p->status = GP_STATUS_DONE;
estate = OPERATOR_FINISHED;
}
}
- else if (ELEM(event->type, PAD0, PAD1, PAD2, PAD3, PAD4, PAD5, PAD6, PAD7, PAD8, PAD9)) {
+ else if (ELEM(event->type,
+ EVT_PAD0,
+ EVT_PAD1,
+ EVT_PAD2,
+ EVT_PAD3,
+ EVT_PAD4,
+ EVT_PAD5,
+ EVT_PAD6,
+ EVT_PAD7,
+ EVT_PAD8,
+ EVT_PAD9)) {
/* allow numpad keys so that camera/view manipulations can still take place
* - PAD0 in particular is really important for Grease Pencil drawing,
* as animators may be working "to camera", so having this working
* is essential for ensuring that they can quickly return to that view
*/
}
- else if ((event->type == BKEY) && (event->val == KM_RELEASE)) {
+ else if ((event->type == EVT_BKEY) && (event->val == KM_RELEASE)) {
/* Add Blank Frame
* - Since this operator is non-modal, we can just call it here, and keep going...
* - This operator is especially useful when animating
@@ -3748,98 +3588,26 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
- // printf("\tGP - handle modal event...\n");
-
/* Exit painting mode (and/or end current stroke).
*
- * NOTE: cannot do RIGHTMOUSE (as is standard for canceling)
- * as that would break polyline T32647.
*/
- /* if polyline and release shift must cancel */
- if ((ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, EKEY)) ||
- ((p->paintmode == GP_PAINTMODE_DRAW_POLY) && (event->shift == 0))) {
- /* exit() ends the current stroke before cleaning up */
- /* printf("\t\tGP - end of paint op + end of stroke\n"); */
- /* if drawing polygon and enable on back, must move stroke */
- if (ts) {
- if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) &&
- (p->paintmode == GP_PAINTMODE_DRAW_POLY)) {
- if (p->flags & GP_PAINTFLAG_STROKEADDED) {
- gpencil_move_last_stroke_to_back(C);
- }
- }
- }
+ if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER, EVT_ESCKEY, EVT_SPACEKEY, EVT_EKEY)) {
p->status = GP_STATUS_DONE;
estate = OPERATOR_FINISHED;
}
/* toggle painting mode upon mouse-button movement
- * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox
- * only)
- * - RIGHTMOUSE = polyline (hotkey) / eraser (all)
+ * - LEFTMOUSE = standard drawing (all) / straight line drawing (all)
+ * - RIGHTMOUSE = eraser (all)
* (Disabling RIGHTMOUSE case here results in bugs like [#32647])
* also making sure we have a valid event value, to not exit too early
*/
if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE) && (ELEM(event->val, KM_PRESS, KM_RELEASE))) {
/* if painting, end stroke */
if (p->status == GP_STATUS_PAINTING) {
- int sketch = 0;
-
- /* basically, this should be mouse-button up = end stroke
- * BUT, polyline drawing is an exception -- all knots should be added during one session
- */
- sketch |= (p->paintmode == GP_PAINTMODE_DRAW_POLY);
-
- if (sketch) {
- /* end stroke only, and then wait to resume painting soon */
- /* printf("\t\tGP - end stroke only\n"); */
- gpencil_stroke_end(op);
-
- /* If eraser mode is on, turn it off after the stroke finishes
- * NOTE: This just makes it nicer to work with drawing sessions
- */
- if (p->paintmode == GP_PAINTMODE_ERASER) {
- p->paintmode = RNA_enum_get(op->ptr, "mode");
-
- /* if the original mode was *still* eraser,
- * we'll let it say for now, since this gives
- * users an opportunity to have visual feedback
- * when adjusting eraser size
- */
- if (p->paintmode != GP_PAINTMODE_ERASER) {
- /* turn off cursor...
- * NOTE: this should be enough for now
- * Just hiding this makes it seem like
- * you can paint again...
- */
- gpencil_draw_toggle_eraser_cursor(C, p, false);
- }
- }
-
- /* we've just entered idling state, so this event was processed (but no others yet) */
- estate = OPERATOR_RUNNING_MODAL;
-
- /* stroke could be smoothed, send notifier to refresh screen */
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
- }
- else {
- /* printf("\t\tGP - end of stroke + op\n"); */
- /* if drawing polygon and enable on back, must move stroke */
- if (ts) {
- if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) &&
- (p->paintmode == GP_PAINTMODE_DRAW_POLY)) {
- if (p->flags & GP_PAINTFLAG_STROKEADDED) {
- gpencil_move_last_stroke_to_back(C);
- }
- }
- }
- /* drawing batch cache is dirty now */
- gp_update_cache(p->gpd);
-
- p->status = GP_STATUS_DONE;
- estate = OPERATOR_FINISHED;
- }
+ p->status = GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
}
else if (event->val == KM_PRESS) {
bool in_bounds = false;
@@ -3848,27 +3616,28 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* NOTE: An exception here is that if launched from the toolbar,
* whatever region we're now in should become the new region
*/
- if ((p->ar) && (p->ar->regiontype == RGN_TYPE_TOOLS)) {
+ if ((p->region) && (p->region->regiontype == RGN_TYPE_TOOLS)) {
/* Change to whatever region is now under the mouse */
- ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y);
+ ARegion *current_region = BKE_area_find_region_xy(
+ p->area, RGN_TYPE_ANY, event->x, event->y);
if (G.debug & G_DEBUG) {
- printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
+ printf("found alternative region %p (old was %p) - at %d %d (area: %d %d -> %d %d)\n",
current_region,
- p->ar,
+ p->region,
event->x,
event->y,
- p->sa->totrct.xmin,
- p->sa->totrct.ymin,
- p->sa->totrct.xmax,
- p->sa->totrct.ymax);
+ p->area->totrct.xmin,
+ p->area->totrct.ymin,
+ p->area->totrct.xmax,
+ p->area->totrct.ymax);
}
if (current_region) {
/* Assume that since we found the cursor in here, it is in bounds
* and that this should be the region that we begin drawing in
*/
- p->ar = current_region;
+ p->region = current_region;
in_bounds = true;
}
else {
@@ -3881,9 +3650,9 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
}
- else if (p->ar) {
+ else if (p->region) {
/* Perform bounds check using */
- const rcti *region_rect = ED_region_visible_rect(p->ar);
+ const rcti *region_rect = ED_region_visible_rect(p->region);
in_bounds = BLI_rcti_isect_pt_v(region_rect, event->mval);
}
else {
@@ -3923,15 +3692,6 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* NOTE: Don't enter this case if an error occurred while finding the
* region (as above)
*/
- /* if drawing polygon and enable on back, must move stroke */
- if (ts) {
- if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) &&
- (p->paintmode == GP_PAINTMODE_DRAW_POLY)) {
- if (p->flags & GP_PAINTFLAG_STROKEADDED) {
- gpencil_move_last_stroke_to_back(C);
- }
- }
- }
p->status = GP_STATUS_DONE;
estate = OPERATOR_FINISHED;
}
@@ -3939,7 +3699,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
else if (event->val == KM_RELEASE) {
p->status = GP_STATUS_IDLING;
op->flag |= OP_IS_MODAL_CURSOR_REGION;
- ED_region_tag_redraw(p->ar);
+ ED_region_tag_redraw(p->region);
}
}
@@ -3948,25 +3708,24 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* handle painting mouse-movements? */
if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
/* handle drawing event */
- /* printf("\t\tGP - add point\n"); */
+ bool is_speed_guide = ((guide->use_guide) &&
+ (p->brush && (p->brush->gpencil_tool == GPAINT_TOOL_DRAW)));
int size_before = p->gpd->runtime.sbuffer_used;
- bool added_events = false;
- if (((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) && (p->paintmode != GP_PAINTMODE_ERASER)) {
- added_events = gpencil_add_fake_events(C, op, event, p);
+ if (((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) && (p->paintmode != GP_PAINTMODE_ERASER) &&
+ !(is_speed_guide && (p->flags & GP_PAINTFLAG_REQ_VECTOR))) {
+ gpencil_add_fake_points(event, p);
}
- gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph_pointer(C), 0.0f, 0.0f, false);
+ gpencil_draw_apply_event(C, op, event, CTX_data_depsgraph_pointer(C));
int size_after = p->gpd->runtime.sbuffer_used;
- /* Last point of the event is always real (not fake). */
- tGPspoint *points = (tGPspoint *)p->gpd->runtime.sbuffer;
- tGPspoint *pt = &points[size_after - 1];
- pt->tflag &= ~GP_TPOINT_FAKE;
-
- /* Smooth the fake events to get smoother strokes, specially at ends. */
- if (added_events) {
- gp_smooth_fake_events(p, size_before, size_after);
+ /* Smooth segments if some fake points were added (need loop to get cumulative smooth).
+ * the 0.15 value gets a good result in Windows and Linux. */
+ if (!is_speed_guide && (size_after - size_before > 1)) {
+ for (int r = 0; r < 5; r++) {
+ gp_smooth_segment(p->gpd, 0.15f, size_before - 1, size_after - 1);
+ }
}
/* finish painting operation if anything went wrong just now */
@@ -3976,25 +3735,21 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
/* event handled, so just tag as running modal */
- /* printf("\t\t\t\tGP - add point handled!\n"); */
estate = OPERATOR_RUNNING_MODAL;
}
}
/* eraser size */
else if ((p->paintmode == GP_PAINTMODE_ERASER) &&
- ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, PADPLUSKEY, PADMINUS)) {
- /* just resize the brush (local version)
- * TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys
- */
- /* printf("\t\tGP - resize eraser\n"); */
+ ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, EVT_PADPLUSKEY, EVT_PADMINUS)) {
+ /* Just resize the brush (local version). */
switch (event->type) {
case WHEELDOWNMOUSE: /* larger */
- case PADPLUSKEY:
+ case EVT_PADPLUSKEY:
p->radius += 5;
break;
case WHEELUPMOUSE: /* smaller */
- case PADMINUS:
+ case EVT_PADMINUS:
p->radius -= 5;
if (p->radius <= 0) {
@@ -4005,7 +3760,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* force refresh */
/* just active area for now, since doing whole screen is too slow */
- ED_region_tag_redraw(p->ar);
+ ED_region_tag_redraw(p->region);
/* event handled, so just tag as running modal */
estate = OPERATOR_RUNNING_MODAL;
@@ -4020,13 +3775,12 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
- if (0 == gpencil_area_exists(C, p->sa)) {
+ if (0 == gpencil_area_exists(C, p->area)) {
estate = OPERATOR_CANCELLED;
}
else {
/* update status indicators - cursor, header, etc. */
gpencil_draw_status_indicators(C, p);
- gpencil_draw_cursor_set(p); /* cursor may have changed outside our control - T44084 */
}
/* process last operations before exiting */
@@ -4050,12 +3804,6 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH:
/* event doesn't need to be handled */
-#if 0
- printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n",
- event->type,
- event->type == MIDDLEMOUSE,
- event->type == MOUSEMOVE);
-#endif
break;
}
@@ -4072,11 +3820,6 @@ static const EnumPropertyItem prop_gpencil_drawmodes[] = {
0,
"Draw Straight Lines",
"Draw straight line segment(s)"},
- {GP_PAINTMODE_DRAW_POLY,
- "DRAW_POLY",
- 0,
- "Draw Poly Line",
- "Click to place endpoints of straight line segments (connected)"},
{GP_PAINTMODE_ERASER, "ERASER", 0, "Eraser", "Erase Grease Pencil strokes"},
{0, NULL, 0, NULL, NULL},
};
@@ -4088,7 +3831,7 @@ void GPENCIL_OT_draw(wmOperatorType *ot)
/* identifiers */
ot->name = "Grease Pencil Draw";
ot->idname = "GPENCIL_OT_draw";
- ot->description = "Draw a new stroke in the active Grease Pencil Object";
+ ot->description = "Draw mouse_prv new stroke in the active Grease Pencil Object";
/* api callbacks */
ot->exec = gpencil_draw_exec;
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 6a0006ef04c..875a6265497 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -22,18 +22,18 @@
* \ingroup edgpencil
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rand.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -54,6 +54,7 @@
#include "BKE_deform.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_paint.h"
@@ -72,8 +73,8 @@
#include "ED_gpencil.h"
#include "ED_object.h"
#include "ED_screen.h"
-#include "ED_view3d.h"
#include "ED_space_api.h"
+#include "ED_view3d.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -122,6 +123,15 @@ static void gp_session_validatebuffer(tGPDprimitive *p)
gpd->runtime.sbuffer_sflag = 0;
gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
+ /* Set vertex colors for buffer. */
+ ED_gpencil_sbuffer_vertex_color_set(p->depsgraph,
+ p->ob,
+ p->scene->toolsettings,
+ p->brush,
+ p->material,
+ p->random_settings.hsv,
+ 1.0f);
+
if (ELEM(p->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) {
gpd->runtime.sbuffer_sflag |= GP_STROKE_CYCLIC;
}
@@ -132,34 +142,11 @@ static void gp_init_colors(tGPDprimitive *p)
bGPdata *gpd = p->gpd;
Brush *brush = p->brush;
- MaterialGPencilStyle *gp_style = NULL;
-
/* use brush material */
- p->mat = BKE_gpencil_object_material_ensure_from_active_input_brush(p->bmain, p->ob, brush);
+ p->material = BKE_gpencil_object_material_ensure_from_active_input_brush(p->bmain, p->ob, brush);
- /* assign color information to temp data */
- gp_style = p->mat->gp_style;
- if (gp_style) {
-
- /* set colors */
- if (gp_style->flag & GP_STYLE_STROKE_SHOW) {
- copy_v4_v4(gpd->runtime.scolor, gp_style->stroke_rgba);
- }
- else {
- /* if no stroke, use fill */
- copy_v4_v4(gpd->runtime.scolor, gp_style->fill_rgba);
- }
-
- copy_v4_v4(gpd->runtime.sfill, gp_style->fill_rgba);
- /* add some alpha to make easy the filling without hide strokes */
- if (gpd->runtime.sfill[3] > 0.8f) {
- gpd->runtime.sfill[3] = 0.8f;
- }
-
- gpd->runtime.mode = (short)gp_style->mode;
- gpd->runtime.bstroke_style = gp_style->stroke_style;
- gpd->runtime.bfill_style = gp_style->fill_style;
- }
+ gpd->runtime.matid = BKE_object_material_slot_find_index(p->ob, p->material);
+ gpd->runtime.sbuffer_brush = brush;
}
/* Helper to square a primitive */
@@ -221,7 +208,7 @@ static void gp_rotate_v2_v2v2fl(float v[2],
add_v2_v2v2(v, r, origin);
}
-/* Helper to rotate line around line centre */
+/* Helper to rotate line around line center. */
static void gp_primitive_rotate_line(
float va[2], float vb[2], const float a[2], const float b[2], const float angle)
{
@@ -254,24 +241,12 @@ static void gp_primitive_update_cps(tGPDprimitive *tgpi)
}
}
-/* Helper to reflect point */
-static void UNUSED_FUNCTION(gp_reflect_point_v2_v2v2v2)(float va[2],
- const float p[2],
- const float a[2],
- const float b[2])
-{
- float point[2];
- closest_to_line_v2(point, p, a, b);
- va[0] = point[0] - (p[0] - point[0]);
- va[1] = point[1] - (p[1] - point[1]);
-}
-
/* Poll callback for primitive operators */
static bool gpencil_primitive_add_poll(bContext *C)
{
/* only 3D view */
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacetype != SPACE_VIEW3D) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area && area->spacetype != SPACE_VIEW3D) {
return 0;
}
@@ -294,7 +269,7 @@ static bool gpencil_primitive_add_poll(bContext *C)
/* don't allow operator to function if the active layer is locked/hidden
* (BUT, if there isn't an active layer, we are free to add new layer when the time comes)
*/
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if ((gpl) && (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_HIDE))) {
CTX_wm_operator_poll_msg_set(C,
"Primitives cannot be added as active layer is locked or hidden");
@@ -322,6 +297,8 @@ static void gpencil_primitive_allocate_memory(tGPDprimitive *tgpi)
static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
{
Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ Brush *brush = tgpi->brush;
int cfra = CFRA;
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
@@ -339,13 +316,15 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
/* create new temp stroke */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "Temp bGPDstroke");
gps->thickness = 2.0f;
- gps->gradient_f = 1.0f;
- gps->gradient_s[0] = 1.0f;
- gps->gradient_s[1] = 1.0f;
+ gps->fill_opacity_fac = 1.0f;
+ gps->hardeness = 1.0f;
+ copy_v2_fl(gps->aspect_ratio, 1.0f);
+ gps->uv_scale = 1.0f;
gps->inittime = 0.0f;
- /* enable recalculation flag by default */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ /* Apply the vertex color to fill. */
+ ED_gpencil_fill_vertex_color_set(ts, brush, gps);
+
gps->flag &= ~GP_STROKE_SELECT;
/* the polygon must be closed, so enabled cyclic */
if (ELEM(tgpi->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) {
@@ -367,10 +346,11 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
/* allocate memory for storage points, but keep empty */
gps->totpoints = 0;
gps->points = MEM_callocN(sizeof(bGPDspoint), "gp_stroke_points");
+ gps->dvert = NULL;
+
/* initialize triangle memory to dummy data */
gps->tot_triangles = 0;
gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* add to strokes */
BLI_addtail(&tgpi->gpf->strokes, gps);
@@ -381,6 +361,8 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
/* Random generator, only init once. */
uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
tgpi->rng = BLI_rng_new(rng_seed);
+
+ DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);
}
/* add new segment to curve */
@@ -704,6 +686,8 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
ToolSettings *ts = tgpi->scene->toolsettings;
bGPdata *gpd = tgpi->gpd;
Brush *brush = tgpi->brush;
+ BrushGpencilSettings *brush_settings = brush->gpencil_settings;
+ GpRandomSettings random_settings = tgpi->random_settings;
bGPDstroke *gps = tgpi->gpf->strokes.first;
GP_Sculpt_Settings *gset = &ts->gp_sculpt;
int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
@@ -758,11 +742,11 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) {
BKE_curvemapping_initialize(ts->gp_sculpt.cur_primitive);
}
- if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
- BKE_curvemapping_initialize(tgpi->brush->gpencil_settings->curve_jitter);
+ if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
+ BKE_curvemapping_initialize(brush_settings->curve_jitter);
}
- if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
- BKE_curvemapping_initialize(tgpi->brush->gpencil_settings->curve_strength);
+ if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
+ BKE_curvemapping_initialize(brush_settings->curve_strength);
}
/* get an array of depths, far depths are blended */
@@ -774,9 +758,9 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
bool found_depth = false;
/* need to restore the original projection settings before packing up */
- view3d_region_operator_needs_opengl(tgpi->win, tgpi->ar);
+ view3d_region_operator_needs_opengl(tgpi->win, tgpi->region);
ED_view3d_autodist_init(tgpi->depsgraph,
- tgpi->ar,
+ tgpi->region,
tgpi->v3d,
(ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
@@ -784,9 +768,9 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
tGPspoint *ptc = &points2D[0];
for (i = 0; i < gps->totpoints; i++, ptc++) {
round_v2i_v2fl(mval_i, &ptc->x);
- if ((ED_view3d_autodist_depth(tgpi->ar, mval_i, depth_margin, depth_arr + i) == 0) &&
+ if ((ED_view3d_autodist_depth(tgpi->region, mval_i, depth_margin, depth_arr + i) == 0) &&
(i && (ED_view3d_autodist_depth_seg(
- tgpi->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
+ tgpi->region, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
interp_depth = true;
}
else {
@@ -864,10 +848,9 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
tGPspoint *p2d = &points2D[i];
/* set rnd value for reuse */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && (p2d->rnd_dirty != true)) {
+ if ((brush_settings->flag & GP_BRUSH_GROUP_RANDOM) && (p2d->rnd_dirty != true)) {
p2d->rnd[0] = BLI_rng_get_float(tgpi->rng);
p2d->rnd[1] = BLI_rng_get_float(tgpi->rng);
- p2d->rnd[2] = BLI_rng_get_float(tgpi->rng);
p2d->rnd_dirty = true;
}
@@ -881,7 +864,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
/* calc pressure */
float curve_pressure = 1.0;
float pressure = 1.0;
- float strength = brush->gpencil_settings->draw_strength;
+ float strength = brush_settings->draw_strength;
/* normalize value to evaluate curve */
if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) {
@@ -891,21 +874,18 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
}
/* apply jitter to position */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_jitter > 0.0f)) {
+ if ((brush_settings->flag & GP_BRUSH_GROUP_RANDOM) && (brush_settings->draw_jitter > 0.0f)) {
float jitter;
- if (brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
- jitter = BKE_curvemapping_evaluateF(
- brush->gpencil_settings->curve_jitter, 0, curve_pressure);
- jitter *= brush->gpencil_settings->draw_sensitivity;
+ if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
+ jitter = BKE_curvemapping_evaluateF(brush_settings->curve_jitter, 0, curve_pressure);
}
else {
- jitter = brush->gpencil_settings->draw_jitter;
+ jitter = brush_settings->draw_jitter;
}
/* exponential value */
- const float exfactor = SQUARE(brush->gpencil_settings->draw_jitter + 2.0f);
+ const float exfactor = square_f(brush_settings->draw_jitter + 2.0f);
const float fac = p2d->rnd[0] * exfactor * jitter;
/* vector */
@@ -930,71 +910,87 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
add_v2_v2(&p2d->x, svec);
}
- /* apply randomness to pressure */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_random_press > 0.0f)) {
- if (p2d->rnd[0] > 0.5f) {
- pressure -= brush->gpencil_settings->draw_random_press * p2d->rnd[1];
- }
- else {
- pressure += brush->gpencil_settings->draw_random_press * p2d->rnd[2];
- }
- }
-
/* color strength */
- if (brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
- float curvef = BKE_curvemapping_evaluateF(
- brush->gpencil_settings->curve_strength, 0, curve_pressure);
- strength *= curvef * brush->gpencil_settings->draw_sensitivity;
- strength *= brush->gpencil_settings->draw_strength;
+ if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
+ float curvef = BKE_curvemapping_evaluateF(brush_settings->curve_strength, 0, curve_pressure);
+ strength *= curvef;
+ strength *= brush_settings->draw_strength;
}
CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f);
- /* apply randomness to color strength */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_random_strength > 0.0f)) {
- if (p2d->rnd[2] > 0.5f) {
- strength -= strength * brush->gpencil_settings->draw_random_strength * p2d->rnd[0];
+ if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) {
+ /* Apply randomness to pressure. */
+ if (brush_settings->draw_random_press > 0.0f) {
+ if ((brush_settings->flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) {
+ float rand = BLI_rng_get_float(tgpi->rng) * 2.0f - 1.0f;
+ pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press;
+ }
+ else {
+ pressure *= 1.0 + random_settings.pressure * brush_settings->draw_random_press;
+ }
+
+ /* Apply random curve. */
+ if (brush_settings->flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) {
+ pressure *= BKE_curvemapping_evaluateF(brush_settings->curve_rand_pressure, 0, pressure);
+ }
+
+ CLAMP(pressure, 0.1f, 1.0f);
}
- else {
- strength += strength * brush->gpencil_settings->draw_random_strength * p2d->rnd[1];
+
+ /* Apply randomness to color strength. */
+ if (brush_settings->draw_random_strength) {
+ if ((brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) {
+ float rand = BLI_rng_get_float(tgpi->rng) * 2.0f - 1.0f;
+ strength *= 1.0 + rand * brush_settings->draw_random_strength;
+ }
+ else {
+ strength *= 1.0 + random_settings.strength * brush_settings->draw_random_strength;
+ }
+
+ /* Apply random curve. */
+ if (brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) {
+ strength *= BKE_curvemapping_evaluateF(brush_settings->curve_rand_strength, 0, pressure);
+ }
+
+ CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
- CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
copy_v2_v2(&tpt->x, &p2d->x);
- CLAMP_MIN(pressure, 0.1f);
-
tpt->pressure = pressure;
tpt->strength = strength;
tpt->time = p2d->time;
+ /* Set vertex colors for buffer. */
+ ED_gpencil_sbuffer_vertex_color_set(tgpi->depsgraph,
+ tgpi->ob,
+ tgpi->scene->toolsettings,
+ tgpi->brush,
+ tgpi->material,
+ tgpi->random_settings.hsv,
+ strength);
+
/* point uv */
if (gpd->runtime.sbuffer_used > 0) {
- MaterialGPencilStyle *gp_style = tgpi->mat->gp_style;
- const float pixsize = gp_style->texture_pixsize / 1000000.0f;
tGPspoint *tptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
bGPDspoint spt, spt2;
/* get origin to reproject point */
float origin[3];
- ED_gp_get_drawing_reference(tgpi->scene, tgpi->ob, tgpi->gpl, ts->gpencil_v3d_align, origin);
+ ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin);
/* reproject current */
- ED_gpencil_tpoint_to_point(tgpi->ar, origin, tpt, &spt);
+ ED_gpencil_tpoint_to_point(tgpi->region, origin, tpt, &spt);
ED_gp_project_point_to_plane(
tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt);
/* reproject previous */
- ED_gpencil_tpoint_to_point(tgpi->ar, origin, tptb, &spt2);
+ ED_gpencil_tpoint_to_point(tgpi->region, origin, tptb, &spt2);
ED_gp_project_point_to_plane(
tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2);
- tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x) / pixsize;
+ tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x);
tpt->uv_fac = tgpi->totpixlen;
- if ((gp_style) && (gp_style->sima)) {
- tpt->uv_fac /= gp_style->sima->gen_x;
- }
}
else {
tgpi->totpixlen = 0.0f;
@@ -1016,13 +1012,14 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
/* convert screen-coordinates to 3D coordinates */
gp_stroke_convertcoords_tpoint(
- tgpi->scene, tgpi->ar, tgpi->ob, tgpi->gpl, p2d, depth_arr ? depth_arr + i : NULL, &pt->x);
+ tgpi->scene, tgpi->region, tgpi->ob, p2d, depth_arr ? depth_arr + i : NULL, &pt->x);
pt->pressure = pressure;
pt->strength = strength;
pt->time = 0.0f;
pt->flag = 0;
pt->uv_fac = tpt->uv_fac;
+ copy_v4_v4(pt->vert_color, tpt->vert_color);
if (gps->dvert != NULL) {
MDeformVert *dvert = &gps->dvert[i];
@@ -1040,14 +1037,14 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
for (int i = 0; i < tgpi->gpd->runtime.tot_cp_points; i++) {
bGPDcontrolpoint *cp = &cps[i];
gp_stroke_convertcoords_tpoint(
- tgpi->scene, tgpi->ar, tgpi->ob, tgpi->gpl, (tGPspoint *)cp, NULL, &cp->x);
+ tgpi->scene, tgpi->region, tgpi->ob, (tGPspoint *)cp, NULL, &cp->x);
}
}
/* reproject to plane */
if (!is_depth) {
float origin[3];
- ED_gp_get_drawing_reference(tgpi->scene, tgpi->ob, tgpi->gpl, ts->gpencil_v3d_align, origin);
+ ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin);
ED_gp_project_stroke_to_plane(
tgpi->scene, tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1);
}
@@ -1055,7 +1052,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
/* if parented change position relative to parent object */
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
- gp_apply_parent_point(tgpi->depsgraph, tgpi->ob, tgpi->gpd, tgpi->gpl, pt);
+ gp_apply_parent_point(tgpi->depsgraph, tgpi->ob, tgpi->gpl, pt);
}
/* if camera view, reproject flat to view to avoid perspective effect */
@@ -1063,8 +1060,11 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
ED_gpencil_project_stroke_to_view(C, tgpi->gpl, gps);
}
- /* force fill recalc */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+
+ /* Update evaluated data. */
+ ED_gpencil_sbuffer_update_eval(tgpi->gpd, tgpi->ob_eval);
MEM_SAFE_FREE(depth_arr);
@@ -1157,13 +1157,14 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
/* set current scene and window info */
tgpi->bmain = CTX_data_main(C);
+ tgpi->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
tgpi->scene = scene;
tgpi->ob = CTX_data_active_object(C);
- tgpi->sa = CTX_wm_area(C);
- tgpi->ar = CTX_wm_region(C);
- tgpi->rv3d = tgpi->ar->regiondata;
- tgpi->v3d = tgpi->sa->spacedata.first;
- tgpi->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ tgpi->ob_eval = (Object *)DEG_get_evaluated_object(tgpi->depsgraph, tgpi->ob);
+ tgpi->area = CTX_wm_area(C);
+ tgpi->region = CTX_wm_region(C);
+ tgpi->rv3d = tgpi->region->regiondata;
+ tgpi->v3d = tgpi->area->spacedata.first;
tgpi->win = CTX_wm_window(C);
/* save original type */
@@ -1174,16 +1175,15 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
/* set GP datablock */
tgpi->gpd = gpd;
- /* region where paint was originated */
- tgpi->gpd->runtime.ar = tgpi->ar;
/* if brush doesn't exist, create a new set (fix damaged files from old versions) */
if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
- BKE_brush_gpencil_presets(bmain, ts);
+ BKE_brush_gpencil_paint_presets(bmain, ts, true);
}
/* Set Draw brush. */
Brush *brush = BKE_paint_toolslots_brush_get(paint, 0);
+
BKE_brush_tool_set(brush, paint, 0);
BKE_paint_brush_set(paint, brush);
tgpi->brush = brush;
@@ -1194,7 +1194,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
tgpi->gpd->runtime.tot_cp_points = 0;
/* getcolor info */
- tgpi->mat = BKE_gpencil_object_material_ensure_from_active_input_toolsettings(
+ tgpi->material = BKE_gpencil_object_material_ensure_from_active_input_toolsettings(
bmain, tgpi->ob, ts);
/* set parameters */
@@ -1251,6 +1251,9 @@ static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent *
gpencil_primitive_init(C, op);
tgpi = op->customdata;
+ /* Init random settings. */
+ ED_gpencil_init_random_settings(tgpi->brush, event->mval, &tgpi->random_settings);
+
const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
if (!is_modal) {
tgpi->flag = IN_PROGRESS;
@@ -1287,6 +1290,7 @@ static void gpencil_primitive_interaction_end(bContext *C,
ToolSettings *ts = tgpi->scene->toolsettings;
Brush *brush = tgpi->brush;
+ BrushGpencilSettings *brush_settings = brush->gpencil_settings;
const int def_nr = tgpi->ob->actdef - 1;
const bool have_weight = (bool)BLI_findlink(&tgpi->ob->defbase, def_nr);
@@ -1304,20 +1308,17 @@ static void gpencil_primitive_interaction_end(bContext *C,
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- gpf = BKE_gpencil_layer_getframe(tgpi->gpl, tgpi->cframe, add_frame_mode);
+ gpf = BKE_gpencil_layer_frame_get(tgpi->gpl, tgpi->cframe, add_frame_mode);
/* prepare stroke to get transferred */
gps = tgpi->gpf->strokes.first;
if (gps) {
gps->thickness = brush->size;
- gps->gradient_f = brush->gpencil_settings->gradient_f;
- copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s);
-
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ gps->hardeness = brush_settings->hardeness;
+ copy_v2_v2(gps->aspect_ratio, brush_settings->aspect_ratio);
- /* calculate UVs along the stroke */
- ED_gpencil_calc_stroke_uv(tgpi->ob, gps);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* transfer stroke from temporary buffer to the actual frame */
@@ -1334,7 +1335,7 @@ static void gpencil_primitive_interaction_end(bContext *C,
BKE_gpencil_dvert_ensure(gps);
for (int i = 0; i < gps->totpoints; i++) {
MDeformVert *ve = &gps->dvert[i];
- MDeformWeight *dw = defvert_verify_index(ve, def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(ve, def_nr);
if (dw) {
dw->weight = ts->vgroup_weight;
}
@@ -1343,7 +1344,7 @@ 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);
+ BKE_gpencil_stroke_close(gps);
}
DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);
@@ -1451,7 +1452,7 @@ static void gpencil_primitive_edit_event_handling(
}
break;
}
- case MKEY: {
+ case EVT_MKEY: {
if ((event->val == KM_PRESS) && (tgpi->curve) && (ELEM(tgpi->orign_type, GP_STROKE_ARC))) {
tgpi->flip ^= 1;
gp_primitive_update_cps(tgpi);
@@ -1459,7 +1460,7 @@ static void gpencil_primitive_edit_event_handling(
}
break;
}
- case EKEY: {
+ case EVT_EKEY: {
if (tgpi->flag == IN_CURVE_EDIT && !ELEM(tgpi->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) {
tgpi->flag = IN_PROGRESS;
WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL);
@@ -1477,23 +1478,25 @@ static void gpencil_primitive_edit_event_handling(
static void gpencil_primitive_strength(tGPDprimitive *tgpi, bool reset)
{
Brush *brush = tgpi->brush;
+ BrushGpencilSettings *brush_settings = brush->gpencil_settings;
+
if (brush) {
if (reset) {
- brush->gpencil_settings->draw_strength = tgpi->brush_strength;
+ brush_settings->draw_strength = tgpi->brush_strength;
tgpi->brush_strength = 0.0f;
}
else {
if (tgpi->brush_strength == 0.0f) {
- tgpi->brush_strength = brush->gpencil_settings->draw_strength;
+ tgpi->brush_strength = brush_settings->draw_strength;
}
float move[2];
sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo);
float adjust = (move[1] > 0.0f) ? 0.01f : -0.01f;
- brush->gpencil_settings->draw_strength += adjust * fabsf(len_manhattan_v2(move));
+ brush_settings->draw_strength += adjust * fabsf(len_manhattan_v2(move));
}
/* limit low limit because below 0.2f the stroke is invisible */
- CLAMP(brush->gpencil_settings->draw_strength, 0.2f, 1.0f);
+ CLAMP(brush_settings->draw_strength, 0.2f, 1.0f);
}
}
@@ -1566,7 +1569,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
gpencil_primitive_update(C, op, tgpi);
break;
}
- case ESCKEY:
+ case EVT_ESCKEY:
case LEFTMOUSE: {
zero_v2(tgpi->move);
tgpi->flag = IN_CURVE_EDIT;
@@ -1588,7 +1591,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
switch (event->type) {
- case ESCKEY: {
+ case EVT_ESCKEY: {
/* return to normal cursor and header status */
ED_workspace_status_text(C, NULL);
WM_cursor_modal_restore(win);
@@ -1610,9 +1613,9 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
- case SPACEKEY: /* confirm */
+ case EVT_SPACEKEY: /* confirm */
case MIDDLEMOUSE:
- case RETKEY:
+ case EVT_RETKEY:
case RIGHTMOUSE: {
if (event->val == KM_PRESS) {
tgpi->flag = IDLE;
@@ -1634,7 +1637,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
gpencil_primitive_update(C, op, tgpi);
break;
}
- case PADPLUSKEY:
+ case EVT_PADPLUSKEY:
case WHEELUPMOUSE: {
if ((event->val != KM_RELEASE)) {
tgpi->tot_edges = tgpi->tot_edges + 1;
@@ -1644,7 +1647,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
- case PADMINUS:
+ case EVT_PADMINUS:
case WHEELDOWNMOUSE: {
if ((event->val != KM_RELEASE)) {
tgpi->tot_edges = tgpi->tot_edges - 1;
@@ -1654,7 +1657,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
- case FKEY: /* brush thickness/ brush strength */
+ case EVT_FKEY: /* brush thickness/ brush strength */
{
if ((event->val == KM_PRESS)) {
if (event->shift) {
@@ -1680,7 +1683,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
gpencil_primitive_size(tgpi, false);
gpencil_primitive_update(C, op, tgpi);
break;
- case ESCKEY:
+ case EVT_ESCKEY:
case MIDDLEMOUSE:
case LEFTMOUSE:
tgpi->brush_size = 0;
@@ -1703,7 +1706,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
gpencil_primitive_strength(tgpi, false);
gpencil_primitive_update(C, op, tgpi);
break;
- case ESCKEY:
+ case EVT_ESCKEY:
case MIDDLEMOUSE:
case LEFTMOUSE:
tgpi->brush_strength = 0.0f;
@@ -1770,10 +1773,10 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
- case SPACEKEY: /* confirm */
+ case EVT_SPACEKEY: /* confirm */
case MIDDLEMOUSE:
- case PADENTER:
- case RETKEY: {
+ case EVT_PADENTER:
+ case EVT_RETKEY: {
tgpi->flag = IDLE;
gpencil_primitive_interaction_end(C, op, win, tgpi);
/* done! */
@@ -1791,7 +1794,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
ATTR_FALLTHROUGH;
}
- case ESCKEY: {
+ case EVT_ESCKEY: {
/* return to normal cursor and header status */
ED_workspace_status_text(C, NULL);
WM_cursor_modal_restore(win);
@@ -1802,7 +1805,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
/* canceled! */
return OPERATOR_CANCELLED;
}
- case PADPLUSKEY:
+ case EVT_PADPLUSKEY:
case WHEELUPMOUSE: {
if ((event->val != KM_RELEASE)) {
tgpi->tot_edges = tgpi->tot_edges + 1;
@@ -1814,7 +1817,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
- case PADMINUS:
+ case EVT_PADMINUS:
case WHEELDOWNMOUSE: {
if ((event->val != KM_RELEASE)) {
tgpi->tot_edges = tgpi->tot_edges - 1;
@@ -1826,7 +1829,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
- case GKEY: /* grab mode */
+ case EVT_GKEY: /* grab mode */
{
if ((event->val == KM_PRESS)) {
tgpi->flag = IN_MOVE;
@@ -1834,7 +1837,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
- case FKEY: /* brush thickness/ brush strength */
+ case EVT_FKEY: /* brush thickness/ brush strength */
{
if ((event->val == KM_PRESS)) {
if (event->shift) {
@@ -1849,7 +1852,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
- case CKEY: /* curve mode */
+ case EVT_CKEY: /* curve mode */
{
if ((event->val == KM_PRESS) && (tgpi->orign_type == GP_STROKE_CURVE)) {
switch (tgpi->type) {
@@ -1868,7 +1871,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
- case TABKEY: {
+ case EVT_TABKEY: {
if (tgpi->flag == IN_CURVE_EDIT) {
tgpi->flag = IN_PROGRESS;
WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL);
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index c2f1e9f091a..f7f3b128351 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -22,11 +22,11 @@
* \ingroup edgpencil
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -40,19 +40,22 @@
#include "BLT_translation.h"
+#include "DNA_gpencil_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_object_types.h"
+#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
#include "BKE_gpencil_modifier.h"
+#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object_deform.h"
#include "BKE_report.h"
@@ -83,24 +86,22 @@
/* Context for brush operators */
typedef struct tGP_BrushEditData {
/* Current editor/region/etc. */
- /* NOTE: This stuff is mainly needed to handle 3D view projection stuff... */
- struct Main *bmain;
+ Depsgraph *depsgraph;
+ Main *bmain;
Scene *scene;
Object *object;
- ScrArea *sa;
- ARegion *ar;
+ ScrArea *area;
+ ARegion *region;
/* Current GPencil datablock */
bGPdata *gpd;
/* Brush Settings */
GP_Sculpt_Settings *settings;
- GP_Sculpt_Data *gp_brush;
- GP_Sculpt_Data *gp_brush_old;
+ Brush *brush;
+ Brush *brush_prev;
- eGP_Sculpt_Types brush_type;
- eGP_Sculpt_Types brush_type_old;
eGP_Sculpt_Flag flag;
eGP_Sculpt_SelectMaskFlag mask;
@@ -109,7 +110,6 @@ typedef struct tGP_BrushEditData {
/* Is the brush currently painting? */
bool is_painting;
- bool is_weight_mode;
bool is_transformed;
/* Start of new sculpt stroke */
@@ -176,10 +176,6 @@ static void gpsculpt_compute_lock_axis(tGP_BrushEditData *gso,
bGPDspoint *pt,
const float save_pt[3])
{
- if (gso->sa->spacetype != SPACE_VIEW3D) {
- return;
- }
-
const ToolSettings *ts = gso->scene->toolsettings;
const View3DCursor *cursor = &gso->scene->cursor;
const int axis = ts->gp_sculpt.lock_axis;
@@ -230,29 +226,14 @@ static GP_Sculpt_Settings *gpsculpt_get_settings(Scene *scene)
return &scene->toolsettings->gp_sculpt;
}
-/* Get the active brush */
-static GP_Sculpt_Data *gpsculpt_get_brush(Scene *scene, bool is_weight_mode)
-{
- GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
- GP_Sculpt_Data *gp_brush = NULL;
- if (is_weight_mode) {
- gp_brush = &gset->brush[gset->weighttype];
- }
- else {
- gp_brush = &gset->brush[gset->brushtype];
- }
-
- return gp_brush;
-}
-
/* Brush Operations ------------------------------- */
/* Invert behavior of brush? */
static bool gp_brush_invert_check(tGP_BrushEditData *gso)
{
/* The basic setting is the brush's setting (from the panel) */
- bool invert = ((gso->gp_brush->flag & GP_SCULPT_FLAG_INVERT) != 0);
-
+ bool invert = ((gso->brush->gpencil_settings->sculpt_flag & GP_SCULPT_FLAG_INVERT) != 0) ||
+ (gso->brush->gpencil_settings->sculpt_flag & BRUSH_DIR_IN);
/* During runtime, the user can hold down the Ctrl key to invert the basic behavior */
if (gso->flag & GP_SCULPT_FLAG_INVERT) {
invert ^= true;
@@ -260,10 +241,10 @@ static bool gp_brush_invert_check(tGP_BrushEditData *gso)
/* set temporary status */
if (invert) {
- gso->gp_brush->flag |= GP_SCULPT_FLAG_TMP_INVERT;
+ gso->brush->gpencil_settings->sculpt_flag |= GP_SCULPT_FLAG_TMP_INVERT;
}
else {
- gso->gp_brush->flag &= ~GP_SCULPT_FLAG_TMP_INVERT;
+ gso->brush->gpencil_settings->sculpt_flag &= ~GP_SCULPT_FLAG_TMP_INVERT;
}
return invert;
@@ -272,28 +253,24 @@ static bool gp_brush_invert_check(tGP_BrushEditData *gso)
/* Compute strength of effect */
static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, const int co[2])
{
- GP_Sculpt_Data *gp_brush = gso->gp_brush;
+ Brush *brush = gso->brush;
/* basic strength factor from brush settings */
- float influence = gp_brush->strength;
+ float influence = brush->alpha;
/* use pressure? */
- if (gp_brush->flag & GP_SCULPT_FLAG_USE_PRESSURE) {
+ if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
influence *= gso->pressure;
}
/* distance fading */
- if (gp_brush->flag & GP_SCULPT_FLAG_USE_FALLOFF) {
- int mval_i[2];
- round_v2i_v2fl(mval_i, gso->mval);
- float distance = (float)len_v2v2_int(mval_i, co);
- float fac;
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, gso->mval);
+ float distance = (float)len_v2v2_int(mval_i, co);
- CLAMP(distance, 0.0f, (float)radius);
- fac = 1.0f - (distance / (float)radius);
-
- influence *= fac;
- }
+ /* Apply Brush curve. */
+ float brush_fallof = BKE_brush_curve_strength(brush, distance, (float)radius);
+ influence *= brush_fallof;
/* apply multiframe falloff */
influence *= gso->mf_falloff;
@@ -302,18 +279,36 @@ static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, c
return influence;
}
-/* Force recal filling data */
-static void gp_recalc_geometry(bGPDstroke *gps)
+/* Tag stroke to be recalculated. */
+static void gpencil_recalc_geometry_tag(bGPDstroke *gps)
{
- bGPDstroke *gps_orig = gps->runtime.gps_orig;
- if (gps_orig) {
- gps_orig->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps_orig->tot_triangles = 0;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ gps_active->flag |= GP_STROKE_TAG;
+}
+
+/* Recalc any stroke tagged. */
+static void gpencil_update_geometry(bGPdata *gpd)
+{
+ if (gpd == NULL) {
+ return;
}
- else {
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ if ((gpl->actframe != gpf) && ((gpf->flag & GP_FRAME_SELECT) == 0)) {
+ continue;
+ }
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->flag & GP_STROKE_TAG) {
+ BKE_gpencil_stroke_geometry_update(gps);
+ gps->flag &= ~GP_STROKE_TAG;
+ }
+ }
+ }
}
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
/* ************************************************ */
@@ -334,31 +329,22 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso,
const int radius,
const int co[2])
{
- // GP_Sculpt_Data *gp_brush = gso->brush;
float inf = gp_brush_influence_calc(gso, radius, co);
- /* need one flag enabled by default */
- if ((gso->settings->flag &
- (GP_SCULPT_SETT_FLAG_APPLY_POSITION | GP_SCULPT_SETT_FLAG_APPLY_STRENGTH |
- GP_SCULPT_SETT_FLAG_APPLY_THICKNESS | GP_SCULPT_SETT_FLAG_APPLY_UV)) == 0) {
- gso->settings->flag |= GP_SCULPT_SETT_FLAG_APPLY_POSITION;
- }
/* perform smoothing */
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_POSITION) {
- BKE_gpencil_smooth_stroke(gps, pt_index, inf);
+ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_POSITION) {
+ BKE_gpencil_stroke_smooth(gps, pt_index, inf);
}
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_STRENGTH) {
- BKE_gpencil_smooth_stroke_strength(gps, pt_index, inf);
+ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_STRENGTH) {
+ BKE_gpencil_stroke_smooth_strength(gps, pt_index, inf);
}
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_THICKNESS) {
- BKE_gpencil_smooth_stroke_thickness(gps, pt_index, inf);
+ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_THICKNESS) {
+ BKE_gpencil_stroke_smooth_thickness(gps, pt_index, inf);
}
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_UV) {
- BKE_gpencil_smooth_stroke_uv(gps, pt_index, inf);
+ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_UV) {
+ BKE_gpencil_stroke_smooth_uv(gps, pt_index, inf);
}
- gp_recalc_geometry(gps);
-
return true;
}
@@ -420,27 +406,15 @@ static bool gp_brush_strength_apply(tGP_BrushEditData *gso,
bGPDspoint *pt = gps->points + pt_index;
float inf;
- /* Compute strength of effect
- * - We divide the strength, so that users can set "sane" values.
- * Otherwise, good default values are in the range of 0.093
- */
- inf = gp_brush_influence_calc(gso, radius, co) / 2.0f;
- CLAMP_MIN(inf, 0.01f);
+ /* Compute strength of effect */
+ inf = gp_brush_influence_calc(gso, radius, co) * 0.125f;
- /* apply */
+ /* Invert effect. */
if (gp_brush_invert_check(gso)) {
- /* make line more transparent - reduce alpha factor */
- pt->strength -= inf;
+ inf *= -1.0f;
}
- else {
- /* make line more opaque - increase stroke strength */
- pt->strength += inf;
- }
- /* Strength should stay within [0.0, 1.0] */
- CLAMP(pt->strength, 0.0f, 1.0f);
- /* smooth the strength */
- BKE_gpencil_smooth_stroke_strength(gps, pt_index, inf);
+ pt->strength = clamp_f(pt->strength + inf, 0.0f, 1.0f);
return true;
}
@@ -534,38 +508,27 @@ static bool gp_brush_grab_store_points(tGP_BrushEditData *gso,
static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso)
{
/* Convert mouse-movements to movement vector */
- // TODO: incorporate pressure into this?
- // XXX: screen-space strokes in 3D space will suffer!
- if (gso->sa->spacetype == SPACE_VIEW3D) {
- RegionView3D *rv3d = gso->ar->regiondata;
- float *rvec = gso->object->loc;
- float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
-
- float mval_f[2];
-
- /* convert from 2D screenspace to 3D... */
- mval_f[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
- mval_f[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
-
- /* apply evaluated data transformation */
- if (gso->rot_eval != 0.0f) {
- const float cval = cos(gso->rot_eval);
- const float sval = sin(gso->rot_eval);
- float r[2];
- r[0] = (mval_f[0] * cval) - (mval_f[1] * sval);
- r[1] = (mval_f[0] * sval) + (mval_f[1] * cval);
- copy_v2_v2(mval_f, r);
- }
+ RegionView3D *rv3d = gso->region->regiondata;
+ float *rvec = gso->object->loc;
+ float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
- ED_view3d_win_to_delta(gso->ar, mval_f, gso->dvec, zfac);
- }
- else {
- /* 2D - just copy */
- // XXX: view2d?
- gso->dvec[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
- gso->dvec[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
- gso->dvec[2] = 0.0f; /* unused */
+ float mval_f[2];
+
+ /* convert from 2D screenspace to 3D... */
+ mval_f[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
+ mval_f[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
+
+ /* apply evaluated data transformation */
+ if (gso->rot_eval != 0.0f) {
+ const float cval = cos(gso->rot_eval);
+ const float sval = sin(gso->rot_eval);
+ float r[2];
+ r[0] = (mval_f[0] * cval) - (mval_f[1] * sval);
+ r[1] = (mval_f[0] * sval) + (mval_f[1] * cval);
+ copy_v2_v2(mval_f, r);
}
+
+ ED_view3d_win_to_delta(gso->region, mval_f, gso->dvec, zfac);
}
/* Apply grab transform to all relevant points of the affected strokes */
@@ -574,7 +537,14 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso,
const float diff_mat[4][4])
{
tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps);
+ /* If a new frame is created, could be impossible find the stroke. */
+ if (data == NULL) {
+ return;
+ }
+
int i;
+ float inverse_diff_mat[4][4];
+ invert_m4_m4(inverse_diff_mat, diff_mat);
/* Apply dvec to all of the stored points */
for (i = 0; i < data->size; i++) {
@@ -596,14 +566,11 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso,
/* apply */
add_v3_v3v3(&pt->x, fpt, delta);
/* undo transformation to the init parent position */
- float inverse_diff_mat[4][4];
- invert_m4_m4(inverse_diff_mat, diff_mat);
mul_m4_v3(inverse_diff_mat, &pt->x);
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
}
- gp_recalc_geometry(gps);
}
/* free customdata used for handling this stroke */
@@ -647,8 +614,6 @@ static bool gp_brush_push_apply(tGP_BrushEditData *gso,
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
/* done */
return true;
}
@@ -658,35 +623,26 @@ static bool gp_brush_push_apply(tGP_BrushEditData *gso,
/* Compute reference midpoint for the brush - this is what we'll be moving towards */
static void gp_brush_calc_midpoint(tGP_BrushEditData *gso)
{
- if (gso->sa->spacetype == SPACE_VIEW3D) {
- /* Convert mouse position to 3D space
- * See: gpencil_paint.c :: gp_stroke_convertcoords()
- */
- RegionView3D *rv3d = gso->ar->regiondata;
- const float *rvec = gso->object->loc;
- float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
-
- float mval_f[2];
- copy_v2_v2(mval_f, gso->mval);
- float mval_prj[2];
- float dvec[3];
-
- if (ED_view3d_project_float_global(gso->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
- V3D_PROJ_RET_OK) {
- sub_v2_v2v2(mval_f, mval_prj, mval_f);
- ED_view3d_win_to_delta(gso->ar, mval_f, dvec, zfac);
- sub_v3_v3v3(gso->dvec, rvec, dvec);
- }
- else {
- zero_v3(gso->dvec);
- }
+ /* Convert mouse position to 3D space
+ * See: gpencil_paint.c :: gp_stroke_convertcoords()
+ */
+ RegionView3D *rv3d = gso->region->regiondata;
+ const float *rvec = gso->object->loc;
+ float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
+
+ float mval_f[2];
+ copy_v2_v2(mval_f, gso->mval);
+ float mval_prj[2];
+ float dvec[3];
+
+ if (ED_view3d_project_float_global(gso->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK) {
+ sub_v2_v2v2(mval_f, mval_prj, mval_f);
+ ED_view3d_win_to_delta(gso->region, mval_f, dvec, zfac);
+ sub_v3_v3v3(gso->dvec, rvec, dvec);
}
else {
- /* Just 2D coordinates */
- // XXX: fix View2D offsets later
- gso->dvec[0] = (float)gso->mval[0];
- gso->dvec[1] = (float)gso->mval[1];
- gso->dvec[2] = 0.0f;
+ zero_v3(gso->dvec);
}
}
@@ -738,8 +694,6 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso,
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
- gp_recalc_geometry(gps);
-
/* done */
return true;
}
@@ -774,7 +728,7 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso,
/* Rotate in 2D or 3D space? */
if (gps->flag & GP_STROKE_3DSPACE) {
/* Perform rotation in 3D space... */
- RegionView3D *rv3d = gso->ar->regiondata;
+ RegionView3D *rv3d = gso->region->regiondata;
float rmat[3][3];
float axis[3];
float vec[3];
@@ -826,8 +780,6 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso,
}
}
- gp_recalc_geometry(gps);
-
/* done */
return true;
}
@@ -851,15 +803,9 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
*/
const float inf = gp_brush_influence_calc(gso, radius, co) / 2.0f;
const float fac = BLI_rng_get_float(gso->rng) * inf;
- /* need one flag enabled by default */
- if ((gso->settings->flag &
- (GP_SCULPT_SETT_FLAG_APPLY_POSITION | GP_SCULPT_SETT_FLAG_APPLY_STRENGTH |
- GP_SCULPT_SETT_FLAG_APPLY_THICKNESS | GP_SCULPT_SETT_FLAG_APPLY_UV)) == 0) {
- gso->settings->flag |= GP_SCULPT_SETT_FLAG_APPLY_POSITION;
- }
/* apply random to position */
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_POSITION) {
+ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_POSITION) {
/* Jitter is applied perpendicular to the mouse movement vector
* - We compute all effects in screenspace (since it's easier)
* and then project these to get the points/distances in
@@ -886,35 +832,20 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
/* convert to dataspace */
if (gps->flag & GP_STROKE_3DSPACE) {
/* 3D: Project to 3D space */
- if (gso->sa->spacetype == SPACE_VIEW3D) {
- bool flip;
- RegionView3D *rv3d = gso->ar->regiondata;
- float zfac = ED_view3d_calc_zfac(rv3d, &pt->x, &flip);
- if (flip == false) {
- float dvec[3];
- ED_view3d_win_to_delta(gso->gsc.ar, svec, dvec, zfac);
- add_v3_v3(&pt->x, dvec);
- /* compute lock axis */
- gpsculpt_compute_lock_axis(gso, pt, save_pt);
- }
+ bool flip;
+ RegionView3D *rv3d = gso->region->regiondata;
+ float zfac = ED_view3d_calc_zfac(rv3d, &pt->x, &flip);
+ if (flip == false) {
+ float dvec[3];
+ ED_view3d_win_to_delta(gso->gsc.region, svec, dvec, zfac);
+ add_v3_v3(&pt->x, dvec);
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
}
- else {
- /* ERROR */
- BLI_assert(!"3D stroke being sculpted in non-3D view");
- }
- }
- else {
- /* 2D: As-is */
- // XXX: v2d scaling/offset?
- float nco[2];
- nco[0] = (float)co[0] + svec[0];
- nco[1] = (float)co[1] + svec[1];
-
- copy_v2_v2(&pt->x, nco);
}
}
/* apply random to strength */
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_STRENGTH) {
+ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_STRENGTH) {
if (BLI_rng_get_float(gso->rng) > 0.5f) {
pt->strength += fac;
}
@@ -925,7 +856,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
CLAMP_MAX(pt->strength, 1.0f);
}
/* apply random to thickness (use pressure) */
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_THICKNESS) {
+ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_THICKNESS) {
if (BLI_rng_get_float(gso->rng) > 0.5f) {
pt->pressure += fac;
}
@@ -936,7 +867,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
CLAMP_MIN(pt->pressure, 0.0f);
}
/* apply random to UV (use pressure) */
- if (gso->settings->flag & GP_SCULPT_SETT_FLAG_APPLY_UV) {
+ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_UV) {
if (BLI_rng_get_float(gso->rng) > 0.5f) {
pt->uv_rot += fac;
}
@@ -946,69 +877,10 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
}
- gp_recalc_geometry(gps);
-
/* done */
return true;
}
-/* Weight Paint Brush */
-/* Change weight paint for vertex groups */
-static bool gp_brush_weight_apply(tGP_BrushEditData *gso,
- bGPDstroke *gps,
- float UNUSED(rot_eval),
- int pt_index,
- const int radius,
- const int co[2])
-{
- /* create dvert */
- BKE_gpencil_dvert_ensure(gps);
-
- MDeformVert *dvert = gps->dvert + pt_index;
- float inf;
-
- /* Compute strength of effect
- * - We divide the strength by 10, so that users can set "sane" values.
- * Otherwise, good default values are in the range of 0.093
- */
- inf = gp_brush_influence_calc(gso, radius, co) / 10.0f;
-
- /* need a vertex group */
- if (gso->vrgroup == -1) {
- if (gso->object) {
- BKE_object_defgroup_add(gso->object);
- DEG_relations_tag_update(gso->bmain);
- gso->vrgroup = 0;
- }
- }
- else {
- bDeformGroup *defgroup = BLI_findlink(&gso->object->defbase, gso->vrgroup);
- if (defgroup->flag & DG_LOCK_WEIGHT) {
- return false;
- }
- }
- /* get current weight */
- MDeformWeight *dw = defvert_verify_index(dvert, gso->vrgroup);
- float curweight = dw ? dw->weight : 0.0f;
-
- if (gp_brush_invert_check(gso)) {
- curweight -= inf;
- }
- else {
- /* increase weight */
- curweight += inf;
- /* verify maximum target weight */
- CLAMP_MAX(curweight, gso->gp_brush->weight);
- }
-
- CLAMP(curweight, 0.0f, 1.0f);
- if (dw) {
- dw->weight = curweight;
- }
-
- return true;
-}
-
/* ************************************************ */
/* Non Callback-Based Brushes */
/* Clone Brush ------------------------------------- */
@@ -1112,9 +984,9 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
{
tGPSB_CloneBrushData *data = gso->customdata;
- Object *ob = CTX_data_active_object(C);
+ Object *ob = gso->object;
bGPdata *gpd = (bGPdata *)ob->data;
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = gso->scene;
bGPDstroke *gps;
float delta[3];
@@ -1136,31 +1008,24 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
bGPDlayer *gpl = NULL;
/* Try to use original layer. */
if (gps->runtime.tmp_layerinfo != NULL) {
- gpl = BLI_findstring(&gpd->layers, gps->runtime.tmp_layerinfo, offsetof(bGPDlayer, info));
+ gpl = BKE_gpencil_layer_named_get(gpd, gps->runtime.tmp_layerinfo);
}
/* if not available, use active layer. */
if (gpl == NULL) {
gpl = CTX_data_active_gpencil_layer(C);
}
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
/* Make a new stroke */
- new_stroke = MEM_dupallocN(gps);
-
- new_stroke->points = MEM_dupallocN(gps->points);
- if (gps->dvert != NULL) {
- new_stroke->dvert = MEM_dupallocN(gps->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps, new_stroke);
- }
- new_stroke->triangles = MEM_dupallocN(gps->triangles);
+ new_stroke = BKE_gpencil_stroke_duplicate(gps, true);
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
/* Fix color references */
Material *ma = BLI_ghash_lookup(data->new_colors, POINTER_FROM_INT(new_stroke->mat_nr));
- new_stroke->mat_nr = BKE_gpencil_object_material_get_index(ob, ma);
+ new_stroke->mat_nr = BKE_gpencil_object_material_index_get(ob, ma);
if (!ma || new_stroke->mat_nr < 0) {
new_stroke->mat_nr = 0;
}
@@ -1204,26 +1069,20 @@ static void gp_brush_clone_adjust(tGP_BrushEditData *gso)
int i;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (gso->gp_brush->flag & GP_SCULPT_FLAG_USE_FALLOFF) {
- /* "Smudge" Effect when falloff is enabled */
- float delta[3] = {0.0f};
- int sco[2] = {0};
- float influence;
+ /* "Smudge" Effect falloff */
+ float delta[3] = {0.0f};
+ int sco[2] = {0};
+ float influence;
- /* compute influence on point */
- gp_point_to_xy(&gso->gsc, gps, pt, &sco[0], &sco[1]);
- influence = gp_brush_influence_calc(gso, gso->gp_brush->size, sco);
+ /* compute influence on point */
+ gp_point_to_xy(&gso->gsc, gps, pt, &sco[0], &sco[1]);
+ influence = gp_brush_influence_calc(gso, gso->brush->size, sco);
- /* adjust the amount of displacement to apply */
- mul_v3_v3fl(delta, gso->dvec, influence);
+ /* adjust the amount of displacement to apply */
+ mul_v3_v3fl(delta, gso->dvec, influence);
- /* apply */
- add_v3_v3(&pt->x, delta);
- }
- else {
- /* Just apply the offset - All points move perfectly in sync with the cursor */
- add_v3_v3(&pt->x, gso->dvec);
- }
+ /* apply */
+ add_v3_v3(&pt->x, delta);
}
}
}
@@ -1258,17 +1117,15 @@ static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso)
static void gpsculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso)
{
- const char *brush_name = NULL;
+ Brush *brush = gso->brush;
char str[UI_MAX_DRAW_STR] = "";
- RNA_enum_name(rna_enum_gpencil_sculpt_brush_items, gso->brush_type, &brush_name);
-
BLI_snprintf(str,
sizeof(str),
TIP_("GPencil Sculpt: %s Stroke | LMB to paint | RMB/Escape to Exit"
" | Ctrl to Invert Action | Wheel Up/Down for Size "
" | Shift-Wheel Up/Down for Strength"),
- (brush_name) ? brush_name : "<?>");
+ brush->id.name + 2);
ED_workspace_status_text(C, str);
}
@@ -1281,33 +1138,20 @@ static void gpsculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso)
static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ ToolSettings *ts = scene->toolsettings;
Object *ob = CTX_data_active_object(C);
- const bool is_weight_mode = ob->mode == OB_MODE_WEIGHT_GPENCIL;
/* set the brush using the tool */
-#if 0
- GP_Sculpt_Settings *gset = &ts->gp_sculpt;
- eGP_Sculpt_Types mode = is_weight_mode ? gset->weighttype : gset->brushtype;
-#endif
tGP_BrushEditData *gso;
/* setup operator data */
gso = MEM_callocN(sizeof(tGP_BrushEditData), "tGP_BrushEditData");
op->customdata = gso;
+ gso->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
gso->bmain = CTX_data_main(C);
/* store state */
gso->settings = gpsculpt_get_settings(scene);
- gso->gp_brush = gpsculpt_get_brush(scene, is_weight_mode);
- gso->is_weight_mode = is_weight_mode;
-
- if (is_weight_mode) {
- gso->brush_type = gso->settings->weighttype;
- }
- else {
- gso->brush_type = gso->settings->brushtype;
- }
/* Random generator, only init once. */
uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
@@ -1320,11 +1164,6 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
gso->gpd = ED_gpencil_data_get_active(C);
gso->cfra = INT_MAX; /* NOTE: So that first stroke will get handled in init_stroke() */
- /* some brushes cannot use pressure for radius */
- if (ELEM(gso->brush_type, GP_SCULPT_TYPE_GRAB, GP_SCULPT_TYPE_CLONE)) {
- gso->gp_brush->flag &= ~GP_SCULPT_FLAG_PRESSURE_RADIUS;
- }
-
gso->scene = scene;
gso->object = ob;
if (ob) {
@@ -1342,8 +1181,12 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
gso->is_transformed = false;
}
- gso->sa = CTX_wm_area(C);
- gso->ar = CTX_wm_region(C);
+ gso->area = CTX_wm_area(C);
+ gso->region = CTX_wm_region(C);
+
+ Paint *paint = &ts->gp_sculptpaint->paint;
+ gso->brush = paint->brush;
+ BKE_curvemapping_initialize(gso->brush->curve);
/* save mask */
gso->mask = ts->gpencil_selectmode_sculpt;
@@ -1359,8 +1202,9 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
}
/* initialise custom data for brushes */
- switch (gso->brush_type) {
- case GP_SCULPT_TYPE_CLONE: {
+ char tool = gso->brush->gpencil_sculpt_tool;
+ switch (tool) {
+ case GPSCULPT_TOOL_CLONE: {
bGPDstroke *gps;
bool found = false;
@@ -1390,7 +1234,7 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
break;
}
- case GP_SCULPT_TYPE_GRAB: {
+ case GPSCULPT_TOOL_GRAB: {
/* initialise the cache needed for this brush */
gso->stroke_customdata = BLI_ghash_ptr_new("GP Grab Brush - Strokes Hash");
break;
@@ -1407,11 +1251,6 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
/* update header */
gpsculpt_brush_header_set(C, gso);
- /* setup cursor drawing */
- // WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_CROSS);
- if (gso->sa->spacetype != SPACE_VIEW3D) {
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
- }
return true;
}
@@ -1419,10 +1258,11 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
{
tGP_BrushEditData *gso = op->customdata;
wmWindow *win = CTX_wm_window(C);
+ char tool = gso->brush->gpencil_sculpt_tool;
/* free brush-specific data */
- switch (gso->brush_type) {
- case GP_SCULPT_TYPE_GRAB: {
+ switch (tool) {
+ case GPSCULPT_TOOL_GRAB: {
/* Free per-stroke customdata
* - Keys don't need to be freed, as those are the strokes
* - Values assigned to those keys do, as they are custom structs
@@ -1431,7 +1271,7 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
break;
}
- case GP_SCULPT_TYPE_CLONE: {
+ case GPSCULPT_TOOL_CLONE: {
/* Free customdata */
gp_brush_clone_free(gso);
break;
@@ -1450,15 +1290,14 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
BLI_rng_free(gso->rng);
}
- /* disable cursor and headerprints */
+ /* Disable headerprints. */
ED_workspace_status_text(C, NULL);
- WM_cursor_modal_restore(win);
- if (gso->sa->spacetype != SPACE_VIEW3D) {
- ED_gpencil_toggle_brush_cursor(C, false, NULL);
- }
/* disable temp invert flag */
- gso->gp_brush->flag &= ~GP_SCULPT_FLAG_TMP_INVERT;
+ gso->brush->gpencil_settings->sculpt_flag &= ~GP_SCULPT_FLAG_TMP_INVERT;
+
+ /* Update geometry data for tagged strokes. */
+ gpencil_update_geometry(gso->gpd);
/* free operator data */
MEM_freeN(gso);
@@ -1468,6 +1307,11 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
/* poll callback for stroke sculpting operator(s) */
static bool gpsculpt_brush_poll(bContext *C)
{
+ ScrArea *area = CTX_wm_area(C);
+ if (area && area->spacetype != SPACE_VIEW3D) {
+ return false;
+ }
+
/* NOTE: this is a bit slower, but is the most accurate... */
return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
}
@@ -1478,7 +1322,6 @@ static void gpsculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso)
{
bGPdata *gpd = gso->gpd;
- bGPDlayer *gpl;
Scene *scene = gso->scene;
int cfra = CFRA;
@@ -1488,9 +1331,9 @@ static void gpsculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso)
}
/* go through each layer, and ensure that we've got a valid frame to use */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
/* Make a new frame to work on if the layer's frame
@@ -1528,7 +1371,7 @@ static float gpsculpt_rotation_eval_get(tGP_BrushEditData *gso,
}
GP_SpaceConversion *gsc = &gso->gsc;
- bGPDstroke *gps_orig = gps_eval->runtime.gps_orig;
+ bGPDstroke *gps_orig = (gps_eval->runtime.gps_orig) ? gps_eval->runtime.gps_orig : gps_eval;
bGPDspoint *pt_orig = &gps_orig->points[pt_eval->runtime.idx_orig];
bGPDspoint *pt_prev_eval = NULL;
bGPDspoint *pt_orig_prev = NULL;
@@ -1578,12 +1421,12 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
{
GP_SpaceConversion *gsc = &gso->gsc;
rcti *rect = &gso->brush_rect;
- GP_Sculpt_Data *gp_brush = gso->gp_brush;
- const int radius = (gp_brush->flag & GP_SCULPT_FLAG_PRESSURE_RADIUS) ?
- gso->gp_brush->size * gso->pressure :
- gso->gp_brush->size;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ Brush *brush = gso->brush;
+ char tool = gso->brush->gpencil_sculpt_tool;
+ const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
+ gso->brush->size;
+
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt_active = NULL;
bGPDspoint *pt1, *pt2;
@@ -1595,13 +1438,19 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
bool include_last = false;
bool changed = false;
float rot_eval = 0.0f;
+
+ /* Check if the stroke collide with brush. */
+ if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) {
+ return false;
+ }
+
if (gps->totpoints == 1) {
bGPDspoint pt_temp;
pt = &gps->points[0];
gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
/* only check if point is inside */
@@ -1627,7 +1476,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
/* Skip if neither one is selected
* (and we are only allowed to edit/consider selected points) */
- if ((GPENCIL_ANY_SCULPT_MASK(gso->mask)) && (!gso->is_weight_mode)) {
+ if (GPENCIL_ANY_SCULPT_MASK(gso->mask)) {
if (!(pt1->flag & GP_SPOINT_SELECT) && !(pt2->flag & GP_SPOINT_SELECT)) {
include_last = false;
continue;
@@ -1647,16 +1496,18 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
* brush region (either within stroke painted, or on its lines)
* - this assumes that linewidth is irrelevant
*/
- if (gp_stroke_inside_circle(
- gso->mval, gso->mval_prev, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
+ if (gp_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
/* Apply operation to these points */
bool ok = false;
/* To each point individually... */
pt = &gps->points[i];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i;
- if (pt_active != NULL) {
+ if ((pt->runtime.pt_orig == NULL) && (tool != GPSCULPT_TOOL_GRAB)) {
+ continue;
+ }
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
+ if ((pt_active != NULL) && (index < gps_active->totpoints)) {
rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, i);
ok = apply(gso, gps_active, rot_eval, index, radius, pc1);
}
@@ -1671,9 +1522,9 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
*/
if (i + 1 == gps->totpoints - 1) {
pt = &gps->points[i + 1];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i + 1;
- if (pt_active != NULL) {
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1;
+ if ((pt_active != NULL) && (index < gps_active->totpoints)) {
rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, i + 1);
ok |= apply(gso, gps_active, rot_eval, index, radius, pc2);
include_last = false;
@@ -1692,9 +1543,9 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
* (but wasn't added then, to avoid double-ups).
*/
pt = &gps->points[i];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i;
- if (pt_active != NULL) {
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
+ if ((pt_active != NULL) && (index < gps_active->totpoints)) {
rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, i);
changed |= apply(gso, gps_active, rot_eval, index, radius, pc1);
include_last = false;
@@ -1715,10 +1566,11 @@ static bool gpsculpt_brush_do_frame(bContext *C,
const float diff_mat[4][4])
{
bool changed = false;
- Object *ob = CTX_data_active_object(C);
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
+ bool redo_geom = false;
+ Object *ob = gso->object;
+ char tool = gso->brush->gpencil_sculpt_tool;
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -1728,28 +1580,29 @@ static bool gpsculpt_brush_do_frame(bContext *C,
continue;
}
- switch (gso->brush_type) {
- case GP_SCULPT_TYPE_SMOOTH: /* Smooth strokes */
+ switch (tool) {
+ case GPSCULPT_TOOL_SMOOTH: /* Smooth strokes */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_smooth_apply);
+ redo_geom |= changed;
break;
}
- case GP_SCULPT_TYPE_THICKNESS: /* Adjust stroke thickness */
+ case GPSCULPT_TOOL_THICKNESS: /* Adjust stroke thickness */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_thickness_apply);
break;
}
- case GP_SCULPT_TYPE_STRENGTH: /* Adjust stroke color strength */
+ case GPSCULPT_TOOL_STRENGTH: /* Adjust stroke color strength */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_strength_apply);
break;
}
- case GP_SCULPT_TYPE_GRAB: /* Grab points */
+ case GPSCULPT_TOOL_GRAB: /* Grab points */
{
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
if (gps_active != NULL) {
if (gso->first) {
/* First time this brush stroke is being applied:
@@ -1757,7 +1610,8 @@ static bool gpsculpt_brush_do_frame(bContext *C,
* 2) Use the points now under the cursor
*/
gp_brush_grab_stroke_init(gso, gps_active);
- changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_grab_store_points);
+ changed |= gpsculpt_brush_do_stroke(
+ gso, gps_active, diff_mat, gp_brush_grab_store_points);
}
else {
/* Apply effect to the stored points */
@@ -1765,45 +1619,61 @@ static bool gpsculpt_brush_do_frame(bContext *C,
changed |= true;
}
}
+ redo_geom |= changed;
break;
}
- case GP_SCULPT_TYPE_PUSH: /* Push points */
+ case GPSCULPT_TOOL_PUSH: /* Push points */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_push_apply);
+ redo_geom |= changed;
break;
}
- case GP_SCULPT_TYPE_PINCH: /* Pinch points */
+ case GPSCULPT_TOOL_PINCH: /* Pinch points */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_pinch_apply);
+ redo_geom |= changed;
break;
}
- case GP_SCULPT_TYPE_TWIST: /* Twist points around midpoint */
+ case GPSCULPT_TOOL_TWIST: /* Twist points around midpoint */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_twist_apply);
+ redo_geom |= changed;
break;
}
- case GP_SCULPT_TYPE_RANDOMIZE: /* Apply jitter */
+ case GPSCULPT_TOOL_RANDOMIZE: /* Apply jitter */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_randomize_apply);
- break;
- }
-
- case GP_SCULPT_TYPE_WEIGHT: /* Adjust vertex group weight */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_weight_apply);
+ redo_geom |= changed;
break;
}
default:
- printf("ERROR: Unknown type of GPencil Sculpt brush - %u\n", gso->brush_type);
+ printf("ERROR: Unknown type of GPencil Sculpt brush \n");
break;
}
- /* Triangulation must be calculated if changed */
- gp_recalc_geometry(gps);
+
+ /* Triangulation must be calculated. */
+ if (redo_geom) {
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ if (gpl->actframe == gpf) {
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ /* Update active frame now, only if material has fill. */
+ if (gp_style->flag & GP_MATERIAL_FILL_SHOW) {
+ BKE_gpencil_stroke_geometry_update(gps_active);
+ }
+ else {
+ gpencil_recalc_geometry_tag(gps_active);
+ }
+ }
+ else {
+ /* Delay a full recalculation for other frames. */
+ gpencil_recalc_geometry_tag(gps_active);
+ }
+ }
}
return changed;
@@ -1812,17 +1682,19 @@ static bool gpsculpt_brush_do_frame(bContext *C,
/* Perform two-pass brushes which modify the existing strokes */
static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ToolSettings *ts = gso->scene->toolsettings;
+ Depsgraph *depsgraph = gso->depsgraph;
Object *obact = gso->object;
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, obact);
- bGPdata *gpd = gso->gpd;
bool changed = false;
+ Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obact->id);
+ bGPdata *gpd = (bGPdata *)ob_eval->data;
+
/* Calculate brush-specific data which applies equally to all points */
- switch (gso->brush_type) {
- case GP_SCULPT_TYPE_GRAB: /* Grab points */
- case GP_SCULPT_TYPE_PUSH: /* Push points */
+ char tool = gso->brush->gpencil_sculpt_tool;
+ switch (tool) {
+ case GPSCULPT_TOOL_GRAB: /* Grab points */
+ case GPSCULPT_TOOL_PUSH: /* Push points */
{
/* calculate amount of displacement to apply */
gso->rot_eval = 0.0f;
@@ -1830,15 +1702,15 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
break;
}
- case GP_SCULPT_TYPE_PINCH: /* Pinch points */
- case GP_SCULPT_TYPE_TWIST: /* Twist points around midpoint */
+ case GPSCULPT_TOOL_PINCH: /* Pinch points */
+ case GPSCULPT_TOOL_TWIST: /* Twist points around midpoint */
{
/* calculate midpoint of the brush (in data space) */
gp_brush_calc_midpoint(gso);
break;
}
- case GP_SCULPT_TYPE_RANDOMIZE: /* Random jitter */
+ case GPSCULPT_TOOL_RANDOMIZE: /* Random jitter */
{
/* compute the displacement vector for the cursor (in data space) */
gso->rot_eval = 0.0f;
@@ -1851,21 +1723,15 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
}
/* Find visible strokes, and perform operations on those if hit */
- CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* If no active frame, don't do anything... */
- if (gpl->actframe == NULL) {
- continue;
- }
- /* Get evaluated frames array data */
- int idx_eval = BLI_findindex(&gpd->layers, gpl);
- bGPDframe *gpf_eval = &ob_eval->runtime.gpencil_evaluated_frames[idx_eval];
- if (gpf_eval == NULL) {
+ if ((!BKE_gpencil_layer_is_editable(gpl)) || (gpl->actframe == NULL)) {
continue;
}
/* calculate difference matrix */
float diff_mat[4][4];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* Active Frame or MultiFrame? */
if (gso->is_multiframe) {
@@ -1874,15 +1740,16 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
int f_end = 0;
if (gso->use_multiframe_falloff) {
- BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
+ BKE_gpencil_frame_range_selected(gpl, &f_init, &f_end);
}
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* Always do active frame; Otherwise, only include selected frames */
if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
/* compute multiframe falloff factor */
if (gso->use_multiframe_falloff) {
- /* Faloff depends on distance to active frame (relative to the overall frame range) */
+ /* Falloff depends on distance to active frame
+ * (relative to the overall frame range). */
gso->mf_falloff = BKE_gpencil_multiframe_falloff_calc(
gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
}
@@ -1897,12 +1764,13 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
}
}
else {
- /* Apply to active frame's strokes */
- gso->mf_falloff = 1.0f;
- changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpf_eval, diff_mat);
+ if (gpl->actframe != NULL) {
+ /* Apply to active frame's strokes */
+ gso->mf_falloff = 1.0f;
+ changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat);
+ }
}
}
- CTX_DATA_END;
return changed;
}
@@ -1911,10 +1779,9 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
{
tGP_BrushEditData *gso = op->customdata;
- GP_Sculpt_Data *gp_brush = gso->gp_brush;
- const int radius = ((gp_brush->flag & GP_SCULPT_FLAG_PRESSURE_RADIUS) ?
- gso->gp_brush->size * gso->pressure :
- gso->gp_brush->size);
+ Brush *brush = gso->brush;
+ const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
+ gso->brush->size;
float mousef[2];
int mouse[2];
bool changed = false;
@@ -1947,7 +1814,8 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt
gso->brush_rect.ymax = mouse[1] + radius;
/* Apply brush */
- if (gso->brush_type == GP_SCULPT_TYPE_CLONE) {
+ char tool = gso->brush->gpencil_sculpt_tool;
+ if (tool == GPSCULPT_TOOL_CLONE) {
changed = gpsculpt_brush_apply_clone(C, gso);
}
else {
@@ -1968,13 +1836,18 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt
}
/* Running --------------------------------------------- */
+static Brush *gpsculpt_get_smooth_brush(tGP_BrushEditData *gso)
+{
+ Main *bmain = gso->bmain;
+ Brush *brush = BLI_findstring(&bmain->brushes, "Smooth Stroke", offsetof(ID, name) + 2);
+
+ return brush;
+}
/* helper - a record stroke, and apply paint event */
static void gpsculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEvent *event)
{
tGP_BrushEditData *gso = op->customdata;
- ToolSettings *ts = CTX_data_tool_settings(C);
- GP_Sculpt_Settings *gset = &ts->gp_sculpt;
PointerRNA itemptr;
float mouse[2];
@@ -1997,19 +1870,17 @@ static void gpsculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEven
}
RNA_float_set(&itemptr, "pressure", pressure);
- if (!gso->is_weight_mode) {
- if (event->shift) {
- gso->gp_brush_old = gso->gp_brush;
- gso->brush_type_old = gso->brush_type;
+ if (event->shift) {
+ gso->brush_prev = gso->brush;
- gso->gp_brush = &gset->brush[GP_SCULPT_TYPE_SMOOTH];
- gso->brush_type = GP_SCULPT_TYPE_SMOOTH;
+ gso->brush = gpsculpt_get_smooth_brush(gso);
+ if (gso->brush == NULL) {
+ gso->brush = gso->brush_prev;
}
- else {
- if (gso->gp_brush_old != NULL) {
- gso->gp_brush = gso->gp_brush_old;
- gso->brush_type = gso->brush_type_old;
- }
+ }
+ else {
+ if (gso->brush_prev != NULL) {
+ gso->brush = gso->brush_prev;
}
}
@@ -2058,25 +1929,26 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve
gso = op->customdata;
/* initialise type-specific data (used for the entire session) */
- switch (gso->brush_type) {
+ char tool = gso->brush->gpencil_sculpt_tool;
+ switch (tool) {
/* Brushes requiring timer... */
- case GP_SCULPT_TYPE_THICKNESS:
- brush_rate = 0.01f; // XXX: hardcoded
+ case GPSCULPT_TOOL_THICKNESS:
+ brush_rate = 0.01f;
needs_timer = true;
break;
- case GP_SCULPT_TYPE_STRENGTH:
- brush_rate = 0.01f; // XXX: hardcoded
+ case GPSCULPT_TOOL_STRENGTH:
+ brush_rate = 0.01f;
needs_timer = true;
break;
- case GP_SCULPT_TYPE_PINCH:
- brush_rate = 0.001f; // XXX: hardcoded
+ case GPSCULPT_TOOL_PINCH:
+ brush_rate = 0.001f;
needs_timer = true;
break;
- case GP_SCULPT_TYPE_TWIST:
- brush_rate = 0.01f; // XXX: hardcoded
+ case GPSCULPT_TOOL_TWIST:
+ brush_rate = 0.01f;
needs_timer = true;
break;
@@ -2094,7 +1966,7 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve
/* start drawing immediately? */
if (is_modal == false) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* ensure that we'll have a new frame to draw on */
gpsculpt_brush_init_stroke(C, gso);
@@ -2104,7 +1976,7 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve
gpsculpt_brush_apply_event(C, op, event);
/* redraw view with feedback */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
return OPERATOR_RUNNING_MODAL;
@@ -2141,42 +2013,6 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
}
break;
- /* Adjust brush settings */
- /* FIXME: Step increments and modifier keys are hardcoded here! */
- case WHEELUPMOUSE:
- case PADPLUSKEY:
- if (event->shift) {
- /* increase strength */
- gso->gp_brush->strength += 0.05f;
- CLAMP_MAX(gso->gp_brush->strength, 1.0f);
- }
- else {
- /* increase brush size */
- gso->gp_brush->size += 3;
- CLAMP_MAX(gso->gp_brush->size, 300);
- }
-
- redraw_region = true;
- redraw_toolsettings = true;
- break;
-
- case WHEELDOWNMOUSE:
- case PADMINUS:
- if (event->shift) {
- /* decrease strength */
- gso->gp_brush->strength -= 0.05f;
- CLAMP_MIN(gso->gp_brush->strength, 0.0f);
- }
- else {
- /* decrease brush size */
- gso->gp_brush->size -= 3;
- CLAMP_MIN(gso->gp_brush->size, 1);
- }
-
- redraw_region = true;
- redraw_toolsettings = true;
- break;
-
/* Painting mbut release = Stop painting (back to idle) */
case LEFTMOUSE:
// BLI_assert(event->val == KM_RELEASE);
@@ -2196,7 +2032,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
/* Abort painting if any of the usual things are tried */
case MIDDLEMOUSE:
case RIGHTMOUSE:
- case ESCKEY:
+ case EVT_ESCKEY:
gpsculpt_brush_exit(C, op);
return OPERATOR_FINISHED;
}
@@ -2218,7 +2054,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
/* Exit modal operator, based on the "standard" ops */
case RIGHTMOUSE:
- case ESCKEY:
+ case EVT_ESCKEY:
gpsculpt_brush_exit(C, op);
return OPERATOR_FINISHED;
@@ -2232,61 +2068,25 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
redraw_region = true;
break;
- /* Adjust brush settings */
- /* FIXME: Step increments and modifier keys are hardcoded here! */
- case WHEELUPMOUSE:
- case PADPLUSKEY:
- if (event->shift) {
- /* increase strength */
- gso->gp_brush->strength += 0.05f;
- CLAMP_MAX(gso->gp_brush->strength, 1.0f);
- }
- else {
- /* increase brush size */
- gso->gp_brush->size += 3;
- CLAMP_MAX(gso->gp_brush->size, 300);
- }
-
- redraw_region = true;
- redraw_toolsettings = true;
- break;
-
- case WHEELDOWNMOUSE:
- case PADMINUS:
- if (event->shift) {
- /* decrease strength */
- gso->gp_brush->strength -= 0.05f;
- CLAMP_MIN(gso->gp_brush->strength, 0.0f);
- }
- else {
- /* decrease brush size */
- gso->gp_brush->size -= 3;
- CLAMP_MIN(gso->gp_brush->size, 1);
- }
-
- redraw_region = true;
- redraw_toolsettings = true;
- break;
-
- /* Change Frame - Allowed */
- case LEFTARROWKEY:
- case RIGHTARROWKEY:
- case UPARROWKEY:
- case DOWNARROWKEY:
+ /* Change Frame - Allowed */
+ case EVT_LEFTARROWKEY:
+ case EVT_RIGHTARROWKEY:
+ case EVT_UPARROWKEY:
+ case EVT_DOWNARROWKEY:
return OPERATOR_PASS_THROUGH;
/* Camera/View Gizmo's - Allowed */
/* (See rationale in gpencil_paint.c -> gpencil_draw_modal()) */
- case PAD0:
- case PAD1:
- case PAD2:
- case PAD3:
- case PAD4:
- case PAD5:
- case PAD6:
- case PAD7:
- case PAD8:
- case PAD9:
+ case EVT_PAD0:
+ case EVT_PAD1:
+ case EVT_PAD2:
+ case EVT_PAD3:
+ case EVT_PAD4:
+ case EVT_PAD5:
+ case EVT_PAD6:
+ case EVT_PAD7:
+ case EVT_PAD8:
+ case EVT_PAD9:
return OPERATOR_PASS_THROUGH;
/* Unhandled event */
@@ -2297,8 +2097,8 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even
/* Redraw region? */
if (redraw_region) {
- ARegion *ar = CTX_wm_region(C);
- ED_region_tag_redraw(ar);
+ ARegion *region = CTX_wm_region(C);
+ ED_region_tag_redraw(region);
}
/* Redraw toolsettings (brush settings)? */
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index be265ed4bd5..69d22b52ded 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -21,25 +21,25 @@
* \ingroup edgpencil
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_lasso_2d.h"
-#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
-#include "DNA_object_types.h"
+#include "DNA_space_types.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
@@ -84,17 +84,40 @@ static int gpencil_select_mode_from_sculpt(eGP_Sculpt_SelectMaskFlag mode)
}
}
+/* Convert vertex mask mode to Select mode */
+static int gpencil_select_mode_from_vertex(eGP_Sculpt_SelectMaskFlag mode)
+{
+ if (mode & GP_VERTEX_MASK_SELECTMODE_POINT) {
+ return GP_SELECTMODE_POINT;
+ }
+ else if (mode & GP_VERTEX_MASK_SELECTMODE_STROKE) {
+ return GP_SELECTMODE_STROKE;
+ }
+ else if (mode & GP_VERTEX_MASK_SELECTMODE_SEGMENT) {
+ return GP_SELECTMODE_SEGMENT;
+ }
+ else {
+ return GP_SELECTMODE_POINT;
+ }
+}
+
static bool gpencil_select_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
if (GPENCIL_SCULPT_MODE(gpd)) {
- ToolSettings *ts = CTX_data_tool_settings(C);
if (!(GPENCIL_ANY_SCULPT_MASK(ts->gpencil_selectmode_sculpt))) {
return false;
}
}
+ if (GPENCIL_VERTEX_MODE(gpd)) {
+ if (!(GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex))) {
+ return false;
+ }
+ }
+
/* we just need some visible strokes, and to be in editmode or other modes only to catch event */
if (GPENCIL_ANY_MODE(gpd)) {
/* TODO: include a check for visible strokes? */
@@ -350,7 +373,7 @@ static void gp_select_same_layer(bContext *C)
Scene *scene = CTX_data_scene(C);
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
bGPDstroke *gps;
bool found = false;
@@ -832,7 +855,7 @@ void GPENCIL_OT_select_less(wmOperatorType *ot)
* from gpencil_paint.c #gp_stroke_eraser_dostroke().
* It would be great to de-duplicate the logic here sometime, but that can wait.
*/
-static bool gp_stroke_do_circle_sel(bGPdata *gpd,
+static bool gp_stroke_do_circle_sel(bGPdata *UNUSED(gpd),
bGPDlayer *gpl,
bGPDstroke *gps,
GP_SpaceConversion *gsc,
@@ -845,13 +868,12 @@ static bool gp_stroke_do_circle_sel(bGPdata *gpd,
const int selectmode,
const float scale)
{
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
bGPDspoint *pt1 = NULL;
bGPDspoint *pt2 = NULL;
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
int i;
bool changed = false;
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt_active = NULL;
if (gps->totpoints == 1) {
@@ -897,35 +919,34 @@ static bool gp_stroke_do_circle_sel(bGPdata *gpd,
if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) ||
((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) {
float mval[2] = {(float)mx, (float)my};
- float mvalo[2] = {(float)mx, (float)my}; /* dummy - this isn't used... */
/* check if point segment of stroke had anything to do with
* eraser region (either within stroke painted, or on its lines)
* - this assumes that linewidth is irrelevant
*/
- if (gp_stroke_inside_circle(mval, mvalo, radius, x0, y0, x1, y1)) {
+ if (gp_stroke_inside_circle(mval, radius, x0, y0, x1, y1)) {
/* change selection of stroke, and then of both points
* (as the last point otherwise wouldn't get selected
* as we only do n-1 loops through).
*/
hit = true;
if (select) {
- pt_active = (!is_multiedit) ? pt1->runtime.pt_orig : pt1;
+ pt_active = pt1->runtime.pt_orig;
if (pt_active != NULL) {
pt_active->flag |= GP_SPOINT_SELECT;
}
- pt_active = (!is_multiedit) ? pt2->runtime.pt_orig : pt2;
+ pt_active = pt2->runtime.pt_orig;
if (pt_active != NULL) {
pt_active->flag |= GP_SPOINT_SELECT;
}
changed = true;
}
else {
- pt_active = (!is_multiedit) ? pt1->runtime.pt_orig : pt1;
+ pt_active = pt1->runtime.pt_orig;
if (pt_active != NULL) {
pt_active->flag &= ~GP_SPOINT_SELECT;
}
- pt_active = (!is_multiedit) ? pt2->runtime.pt_orig : pt2;
+ pt_active = pt2->runtime.pt_orig;
if (pt_active != NULL) {
pt_active->flag &= ~GP_SPOINT_SELECT;
}
@@ -942,7 +963,7 @@ static bool gp_stroke_do_circle_sel(bGPdata *gpd,
/* if stroke mode expand selection */
if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) {
for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) {
- pt_active = (!is_multiedit) ? pt1->runtime.pt_orig : pt1;
+ pt_active = (pt1->runtime.pt_orig) ? pt1->runtime.pt_orig : pt1;
if (pt_active != NULL) {
if (select) {
pt_active->flag |= GP_SPOINT_SELECT;
@@ -955,7 +976,7 @@ static bool gp_stroke_do_circle_sel(bGPdata *gpd,
}
/* expand selection to segment */
- pt_active = (!is_multiedit) ? pt1->runtime.pt_orig : pt1;
+ pt_active = (pt1->runtime.pt_orig) ? pt1->runtime.pt_orig : pt1;
if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select) && (pt_active != NULL)) {
float r_hita[3], r_hitb[3];
bool hit_select = (bool)(pt1->flag & GP_SPOINT_SELECT);
@@ -976,9 +997,17 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
- const int selectmode = (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) ?
- gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) :
- ts->gpencil_selectmode_edit;
+ int selectmode;
+ if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) {
+ selectmode = gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt);
+ }
+ else if (ob && ob->mode == OB_MODE_VERTEX_GPENCIL) {
+ selectmode = gpencil_select_mode_from_vertex(ts->gpencil_selectmode_vertex);
+ }
+ else {
+ selectmode = ts->gpencil_selectmode_edit;
+ }
+
const float scale = ts->gp_sculpt.isect_threshold;
/* if not edit/sculpt mode, the event is catched but not processed */
@@ -986,7 +1015,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
const int mx = RNA_int_get(op->ptr, "x");
const int my = RNA_int_get(op->ptr, "y");
@@ -999,7 +1028,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
bool changed = false;
/* sanity checks */
- if (sa == NULL) {
+ if (area == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active area");
return OPERATOR_CANCELLED;
}
@@ -1022,8 +1051,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
rect.ymax = my + radius;
/* find visible strokes, and select if hit */
- GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
+ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
changed |= gp_stroke_do_circle_sel(gpd,
gpl,
gps,
@@ -1098,11 +1126,18 @@ static int gpencil_generic_select_exec(bContext *C,
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
ToolSettings *ts = CTX_data_tool_settings(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- const short selectmode = (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) ?
- gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) :
- ts->gpencil_selectmode_edit;
+ int selectmode;
+ if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) {
+ selectmode = gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt);
+ }
+ else if (ob && ob->mode == OB_MODE_VERTEX_GPENCIL) {
+ selectmode = gpencil_select_mode_from_vertex(ts->gpencil_selectmode_vertex);
+ }
+ else {
+ selectmode = ts->gpencil_selectmode_edit;
+ }
const bool strokemode = ((selectmode == GP_SELECTMODE_STROKE) &&
((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
@@ -1118,7 +1153,7 @@ static int gpencil_generic_select_exec(bContext *C,
bool changed = false;
/* sanity checks */
- if (sa == NULL) {
+ if (area == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active area");
return OPERATOR_CANCELLED;
}
@@ -1127,7 +1162,7 @@ static int gpencil_generic_select_exec(bContext *C,
gp_point_conversion_init(C, &gsc);
/* deselect all strokes first? */
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ if (SEL_OP_USE_PRE_DESELECT(sel_op) || (GPENCIL_PAINT_MODE(gpd))) {
CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
bGPDspoint *pt;
@@ -1143,18 +1178,17 @@ static int gpencil_generic_select_exec(bContext *C,
}
/* select/deselect points */
- GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt;
int i;
bool hit = false;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
+ if (pt->runtime.pt_orig == NULL) {
continue;
}
- bGPDspoint *pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+ bGPDspoint *pt_active = pt->runtime.pt_orig;
/* convert point coords to screenspace */
const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
@@ -1192,7 +1226,7 @@ static int gpencil_generic_select_exec(bContext *C,
if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
continue;
}
- bGPDspoint *pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+ bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
if (sel_op_result) {
pt_active->flag |= GP_SPOINT_SELECT;
@@ -1211,7 +1245,7 @@ static int gpencil_generic_select_exec(bContext *C,
GP_EVALUATED_STROKES_END(gpstroke_iter);
/* if paint mode,delete selected points */
- if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
+ if (GPENCIL_PAINT_MODE(gpd)) {
gp_delete_selected_point_wrap(C);
changed = true;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -1293,8 +1327,8 @@ void GPENCIL_OT_select_box(wmOperatorType *ot)
struct GP_SelectLassoUserData {
rcti rect;
- const int (*mcords)[2];
- int mcords_len;
+ const int (*mcoords)[2];
+ int mcoords_len;
};
static bool gpencil_test_lasso(bGPDstroke *gps,
@@ -1310,25 +1344,25 @@ static bool gpencil_test_lasso(bGPDstroke *gps,
gp_point_to_xy(gsc, gps, &pt2, &x0, &y0);
/* test if in lasso boundbox + within the lasso noose */
return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0) &&
- BLI_lasso_is_point_inside(data->mcords, data->mcords_len, x0, y0, INT_MAX));
+ BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, x0, y0, INT_MAX));
}
static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
{
struct GP_SelectLassoUserData data = {0};
- data.mcords = WM_gesture_lasso_path_to_array(C, op, &data.mcords_len);
+ data.mcoords = WM_gesture_lasso_path_to_array(C, op, &data.mcoords_len);
/* Sanity check. */
- if (data.mcords == NULL) {
+ if (data.mcoords == NULL) {
return OPERATOR_PASS_THROUGH;
}
/* Compute boundbox of lasso (for faster testing later). */
- BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len);
+ BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len);
int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, &data);
- MEM_freeN((void *)data.mcords);
+ MEM_freeN((void *)data.mcoords);
return ret;
}
@@ -1382,7 +1416,7 @@ static void deselect_all_selected(bContext *C)
static int gpencil_select_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
ToolSettings *ts = CTX_data_tool_settings(C);
@@ -1393,11 +1427,12 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
const float radius = 0.50f * U.widget_unit;
const int radius_squared = (int)(radius * radius);
- bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool use_shift_extend = RNA_boolean_get(op->ptr, "use_shift_extend");
+ bool extend = RNA_boolean_get(op->ptr, "extend") || use_shift_extend;
bool deselect = RNA_boolean_get(op->ptr, "deselect");
bool toggle = RNA_boolean_get(op->ptr, "toggle");
bool whole = RNA_boolean_get(op->ptr, "entire_strokes");
- const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+ const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all") && !use_shift_extend;
int mval[2] = {0};
@@ -1409,7 +1444,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
int hit_distance = radius_squared;
/* sanity checks */
- if (sa == NULL) {
+ if (area == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active area");
return OPERATOR_CANCELLED;
}
@@ -1419,6 +1454,10 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
whole = (bool)(gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) ==
GP_SELECTMODE_STROKE);
}
+ else if ((ob) && (ob->mode == OB_MODE_VERTEX_GPENCIL)) {
+ whole = (bool)(gpencil_select_mode_from_vertex(ts->gpencil_selectmode_sculpt) ==
+ GP_SELECTMODE_STROKE);
+ }
else {
whole = (bool)(ts->gpencil_selectmode_edit == GP_SELECTMODE_STROKE);
}
@@ -1431,9 +1470,8 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
/* First Pass: Find stroke point which gets hit */
/* XXX: maybe we should go from the top of the stack down instead... */
- GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
- {
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt;
int i;
@@ -1526,9 +1564,16 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
hit_stroke->flag |= GP_STROKE_SELECT;
/* expand selection to segment */
- const short selectmode = (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) ?
- gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) :
- ts->gpencil_selectmode_edit;
+ int selectmode;
+ if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) {
+ selectmode = gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt);
+ }
+ else if (ob && ob->mode == OB_MODE_VERTEX_GPENCIL) {
+ selectmode = gpencil_select_mode_from_vertex(ts->gpencil_selectmode_vertex);
+ }
+ else {
+ selectmode = ts->gpencil_selectmode_edit;
+ }
if (selectmode == GP_SELECTMODE_SEGMENT) {
float r_hita[3], r_hitb[3];
@@ -1563,6 +1608,11 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RNA_int_set_array(op->ptr, "location", event->mval);
+
+ if (!RNA_struct_property_is_set(op->ptr, "use_shift_extend")) {
+ RNA_boolean_set(op->ptr, "use_shift_extend", event->shift);
+ }
+
return gpencil_select_exec(C, op);
}
@@ -1604,6 +1654,187 @@ void GPENCIL_OT_select(wmOperatorType *ot)
INT_MIN,
INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_boolean(ot->srna, "use_shift_extend", false, "Extend", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
+/* Select by Vertex Color. */
+/* Helper to create a hash of colors. */
+static void gpencil_selected_hue_table(bContext *C,
+ Object *ob,
+ const int threshold,
+ GHash *hue_table)
+{
+ const float range = pow(10, 5 - threshold);
+ float hsv[3];
+
+ /* Extract all colors. */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+ if ((gps->flag & GP_STROKE_SELECT) == 0) {
+ continue;
+ }
+
+ /* Read all points to get all colors selected. */
+ bGPDspoint *pt;
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (((pt->flag & GP_SPOINT_SELECT) == 0) || (pt->vert_color[3] == 0.0f)) {
+ continue;
+ }
+ /* Round Hue value. */
+ rgb_to_hsv_compat_v(pt->vert_color, hsv);
+ uint key = truncf(hsv[0] * range);
+ if (!BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) {
+ BLI_ghash_insert(hue_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+}
+
+static bool gpencil_select_vertex_color_poll(bContext *C)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ if (GPENCIL_VERTEX_MODE(gpd)) {
+ if (!(GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex))) {
+ return false;
+ }
+
+ /* Any data to use. */
+ if (gpd->layers.first) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int gpencil_select_vertex_color_exec(bContext *C, wmOperator *op)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+
+ const float threshold = RNA_int_get(op->ptr, "threshold");
+ const int selectmode = gpencil_select_mode_from_vertex(ts->gpencil_selectmode_vertex);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const float range = pow(10, 5 - threshold);
+
+ bool done = false;
+
+ /* Create a hash table with all selected colors. */
+ GHash *hue_table = BLI_ghash_int_new(__func__);
+ gpencil_selected_hue_table(C, ob, threshold, hue_table);
+ if (BLI_ghash_len(hue_table) == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Select before some Vertex to use as a filter color");
+ BLI_ghash_free(hue_table, NULL, NULL);
+
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Select any visible stroke that uses any of these colors. */
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ bGPDspoint *pt;
+ int i;
+ bool gps_selected = false;
+ /* Check all stroke points. */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->vert_color[3] == 0.0f) {
+ continue;
+ }
+
+ /* Only check Hue to get value and saturation full ranges. */
+ float hsv[3];
+ /* Round Hue value. */
+ rgb_to_hsv_compat_v(pt->vert_color, hsv);
+ uint key = truncf(hsv[0] * range);
+
+ if (BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) {
+ pt->flag |= GP_SPOINT_SELECT;
+ gps_selected = true;
+ }
+ }
+
+ if (gps_selected) {
+ gps->flag |= GP_STROKE_SELECT;
+ done = true;
+
+ /* Extend stroke selection. */
+ if (selectmode == GP_SELECTMODE_STROKE) {
+ bGPDspoint *pt1 = NULL;
+
+ for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) {
+ pt1->flag |= GP_SPOINT_SELECT;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (done) {
+ /* updates */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ }
+
+ /* Free memory. */
+ if (hue_table != NULL) {
+ BLI_ghash_free(hue_table, NULL, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_vertex_color(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Vertex Color";
+ ot->idname = "GPENCIL_OT_select_vertex_color";
+ ot->description = "Select all points with similar vertex color of current selected";
+
+ /* callbacks */
+ ot->exec = gpencil_select_vertex_color_exec;
+ ot->poll = gpencil_select_vertex_color_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(
+ ot->srna,
+ "threshold",
+ 0,
+ 0,
+ 5,
+ "Threshold",
+ "Tolerance of the selection. Higher values select a wider range of similar colors",
+ 0,
+ 5);
+ /* avoid re-using last var */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
index 7b57dacd3e4..c2504ce329e 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -27,8 +27,8 @@
#include "MEM_guardedalloc.h"
#include "DNA_gpencil_types.h"
-#include "DNA_object_types.h"
#include "DNA_listBase.h"
+#include "DNA_object_types.h"
#include "DNA_windowmanager_types.h"
#include "BLI_listbase.h"
@@ -90,14 +90,14 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
if (gpd_ptr) {
if (*gpd_ptr) {
bGPdata *gpd = *gpd_ptr;
- bGPDlayer *gpl, *gpld;
+ bGPDlayer *gpld;
BKE_gpencil_free_layers(&gpd->layers);
/* copy layers */
BLI_listbase_clear(&gpd->layers);
- for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* make a copy of source layer and its data */
gpld = BKE_gpencil_layer_duplicate(gpl);
BLI_addtail(&gpd->layers, gpld);
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 9b1551fe2a5..3cab26eab44 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -20,24 +20,27 @@
* \ingroup edgpencil
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
+#include "BLI_hash.h"
+#include "BLI_math.h"
+#include "BLI_rand.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
-#include "BLI_rand.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_gpencil_types.h"
+#include "PIL_time.h"
+
#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -45,21 +48,22 @@
#include "DNA_view3d_types.h"
#include "BKE_action.h"
-#include "BKE_colortools.h"
-#include "BKE_collection.h"
-#include "BKE_deform.h"
-#include "BKE_main.h"
#include "BKE_brush.h"
+#include "BKE_collection.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
+#include "BKE_deform.h"
#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_material.h"
#include "BKE_tracking.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -68,12 +72,13 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "ED_gpencil.h"
#include "ED_clip.h"
-#include "ED_view3d.h"
+#include "ED_gpencil.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
+#include "ED_transform_snap_object_context.h"
+#include "ED_view3d.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
@@ -92,13 +97,13 @@
* and an RNA-pointer to trace back to whatever owns it,
* when context info is not available.
*/
-bGPdata **ED_gpencil_data_get_pointers_direct(ScrArea *sa, Object *ob, PointerRNA *r_ptr)
+bGPdata **ED_gpencil_data_get_pointers_direct(ScrArea *area, Object *ob, PointerRNA *r_ptr)
{
/* if there's an active area, check if the particular editor may
* have defined any special Grease Pencil context for editing...
*/
- if (sa) {
- switch (sa->spacetype) {
+ if (area) {
+ switch (area->spacetype) {
case SPACE_PROPERTIES: /* properties */
case SPACE_INFO: /* header info */
case SPACE_TOPBAR: /* Topbar */
@@ -131,16 +136,16 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ScrArea *sa, Object *ob, PointerRN
* when context info is not available.
*/
bGPdata **ED_annotation_data_get_pointers_direct(ID *screen_id,
- ScrArea *sa,
+ ScrArea *area,
Scene *scene,
PointerRNA *r_ptr)
{
/* If there's an active area, check if the particular editor may
* have defined any special Grease Pencil context for editing. */
- if (sa) {
- SpaceLink *sl = sa->spacedata.first;
+ if (area) {
+ SpaceLink *sl = area->spacedata.first;
- switch (sa->spacetype) {
+ switch (area->spacetype) {
case SPACE_PROPERTIES: /* properties */
case SPACE_INFO: /* header info */
{
@@ -235,10 +240,10 @@ bGPdata **ED_annotation_data_get_pointers_direct(ID *screen_id,
* and an RNA-pointer to trace back to whatever owns it. */
bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Object *ob = CTX_data_active_object(C);
- return ED_gpencil_data_get_pointers_direct(sa, ob, r_ptr);
+ return ED_gpencil_data_get_pointers_direct(area, ob, r_ptr);
}
/* Get pointer to active Grease Pencil datablock,
@@ -247,23 +252,23 @@ bGPdata **ED_annotation_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
{
ID *screen_id = (ID *)CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- return ED_annotation_data_get_pointers_direct(screen_id, sa, scene, r_ptr);
+ return ED_annotation_data_get_pointers_direct(screen_id, area, scene, r_ptr);
}
/* -------------------------------------------------------- */
/* Get the active Grease Pencil datablock, when context is not available */
-bGPdata *ED_gpencil_data_get_active_direct(ScrArea *sa, Object *ob)
+bGPdata *ED_gpencil_data_get_active_direct(ScrArea *area, Object *ob)
{
- bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(sa, ob, NULL);
+ bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(area, ob, NULL);
return (gpd_ptr) ? *(gpd_ptr) : NULL;
}
/* Get the active Grease Pencil datablock, when context is not available */
-bGPdata *ED_annotation_data_get_active_direct(ID *screen_id, ScrArea *sa, Scene *scene)
+bGPdata *ED_annotation_data_get_active_direct(ID *screen_id, ScrArea *area, Scene *scene)
{
- bGPdata **gpd_ptr = ED_annotation_data_get_pointers_direct(screen_id, sa, scene, NULL);
+ bGPdata **gpd_ptr = ED_annotation_data_get_pointers_direct(screen_id, area, scene, NULL);
return (gpd_ptr) ? *(gpd_ptr) : NULL;
}
@@ -273,12 +278,10 @@ bGPdata *ED_annotation_data_get_active_direct(ID *screen_id, ScrArea *sa, Scene
bGPdata *ED_gpencil_data_get_active(const bContext *C)
{
Object *ob = CTX_data_active_object(C);
- if (ob == NULL) {
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
return NULL;
}
- bGPdata *gpd = (bGPdata *)ob->data;
-
- return gpd;
+ return ob->data;
}
/* Get the active Grease Pencil datablock
@@ -300,13 +303,13 @@ bGPdata *ED_annotation_data_get_active(const bContext *C)
*/
bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob = CTX_data_active_object(C);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- return ED_gpencil_data_get_active_direct(sa, ob_eval);
+ return ED_gpencil_data_get_active_direct(area, ob_eval);
}
/* -------------------------------------------------------- */
@@ -330,7 +333,7 @@ bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr)
bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra)
{
if (ob && ob->data && (ob->type == OB_GPENCIL)) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->data);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(ob->data);
if (gpl) {
if (gpl->actframe) {
// XXX: assumes that frame has been fetched already
@@ -338,7 +341,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra)
}
else {
/* XXX: disabled as could be too much of a penalty */
- /* return BKE_gpencil_layer_find_frame(gpl, cfra); */
+ /* return BKE_gpencil_layer_frame_find(gpl, cfra); */
}
}
}
@@ -369,7 +372,7 @@ bool gp_active_layer_poll(bContext *C)
return false;
}
bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return (gpl != NULL);
}
@@ -482,6 +485,40 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
return item;
}
+/* Just existing Materials */
+const EnumPropertyItem *ED_gpencil_material_enum_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ Object *ob = CTX_data_active_object(C);
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+ int i = 0;
+
+ if (ELEM(NULL, C, ob)) {
+ return DummyRNA_DEFAULT_items;
+ }
+
+ /* Existing materials */
+ for (i = 1; i <= ob->totcol; i++) {
+ Material *ma = BKE_object_material_get(ob, i);
+ if (ma) {
+ item_tmp.identifier = ma->id.name + 2;
+ item_tmp.name = ma->id.name + 2;
+ item_tmp.value = i;
+ item_tmp.icon = ma->preview ? ma->preview->icon_id : ICON_NONE;
+
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
/* ******************************************************** */
/* Brush Tool Core */
@@ -495,8 +532,7 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
* \param x0, y0: The screen-space x and y coordinates of the start of the stroke segment
* \param x1, y1: The screen-space x and y coordinates of the end of the stroke segment
*/
-bool gp_stroke_inside_circle(
- const float mval[2], const float UNUSED(mvalo[2]), int rad, int x0, int y0, int x1, int y1)
+bool gp_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1)
{
/* simple within-radius check for now */
const float screen_co_a[2] = {x0, y0};
@@ -515,25 +551,25 @@ bool gp_stroke_inside_circle(
/* Check whether given stroke can be edited given the supplied context */
/* TODO: do we need additional flags for screenspace vs dataspace? */
-bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps)
+bool ED_gpencil_stroke_can_use_direct(const ScrArea *area, const bGPDstroke *gps)
{
/* sanity check */
- if (ELEM(NULL, sa, gps)) {
+ if (ELEM(NULL, area, gps)) {
return false;
}
/* filter stroke types by flags + spacetype */
if (gps->flag & GP_STROKE_3DSPACE) {
/* 3D strokes - only in 3D view */
- return ((sa->spacetype == SPACE_VIEW3D) || (sa->spacetype == SPACE_PROPERTIES));
+ return ((area->spacetype == SPACE_VIEW3D) || (area->spacetype == SPACE_PROPERTIES));
}
else if (gps->flag & GP_STROKE_2DIMAGE) {
/* Special "image" strokes - only in Image Editor */
- return (sa->spacetype == SPACE_IMAGE);
+ return (area->spacetype == SPACE_IMAGE);
}
else if (gps->flag & GP_STROKE_2DSPACE) {
/* 2D strokes (dataspace) - for any 2D view (i.e. everything other than 3D view) */
- return (sa->spacetype != SPACE_VIEW3D);
+ return (area->spacetype != SPACE_VIEW3D);
}
else {
/* view aligned - anything goes */
@@ -544,21 +580,21 @@ bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps)
/* Check whether given stroke can be edited in the current context */
bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
{
- ScrArea *sa = CTX_wm_area(C);
- return ED_gpencil_stroke_can_use_direct(sa, gps);
+ ScrArea *area = CTX_wm_area(C);
+ return ED_gpencil_stroke_can_use_direct(area, gps);
}
/* Check whether given stroke can be edited for the current color */
bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps)
{
/* check if the color is editable */
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
if (gp_style != NULL) {
- if (gp_style->flag & GP_STYLE_COLOR_HIDE) {
+ if (gp_style->flag & GP_MATERIAL_HIDE) {
return false;
}
- if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_MATERIAL_LOCKED)) {
return false;
}
}
@@ -576,8 +612,8 @@ bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstr
*/
void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
/* zero out the storage (just in case) */
memset(r_gsc, 0, sizeof(GP_SpaceConversion));
@@ -587,27 +623,28 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
r_gsc->scene = CTX_data_scene(C);
r_gsc->ob = CTX_data_active_object(C);
- r_gsc->sa = sa;
- r_gsc->ar = ar;
- r_gsc->v2d = &ar->v2d;
+ r_gsc->area = area;
+ r_gsc->region = region;
+ r_gsc->v2d = &region->v2d;
/* init region-specific stuff */
- if (sa->spacetype == SPACE_VIEW3D) {
+ if (area->spacetype == SPACE_VIEW3D) {
wmWindow *win = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
View3D *v3d = (View3D *)CTX_wm_space_data(C);
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
/* init 3d depth buffers */
view3d_operator_needs_opengl(C);
- view3d_region_operator_needs_opengl(win, ar);
- ED_view3d_autodist_init(depsgraph, ar, v3d, 0);
+ view3d_region_operator_needs_opengl(win, region);
+ ED_view3d_autodist_init(depsgraph, region, v3d, 0);
/* for camera view set the subrect */
if (rv3d->persp == RV3D_CAMOB) {
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &r_gsc->subrect_data, true);
+ ED_view3d_calc_camera_border(
+ scene, depsgraph, region, v3d, rv3d, &r_gsc->subrect_data, true);
r_gsc->subrect = &r_gsc->subrect_data;
}
}
@@ -631,8 +668,7 @@ void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4],
/**
* Change position relative to parent object
*/
-void gp_apply_parent(
- Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
+void gp_apply_parent(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, bGPDstroke *gps)
{
bGPDspoint *pt;
int i;
@@ -642,7 +678,7 @@ void gp_apply_parent(
float inverse_diff_mat[4][4];
float fpt[3];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
for (i = 0; i < gps->totpoints; i++) {
@@ -655,15 +691,14 @@ void gp_apply_parent(
/**
* Change point position relative to parent object
*/
-void gp_apply_parent_point(
- Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt)
+void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, bGPDspoint *pt)
{
/* undo matrix */
float diff_mat[4][4];
float inverse_diff_mat[4][4];
float fpt[3];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
@@ -673,8 +708,8 @@ void gp_apply_parent_point(
/**
* Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
*
- * \param[out] r_x The screen-space x-coordinate of the point
- * \param[out] r_y The screen-space y-coordinate of the point
+ * \param[out] r_x: The screen-space x-coordinate of the point
+ * \param[out] r_y: The screen-space y-coordinate of the point
*
* \warning This assumes that the caller has already checked
* whether the stroke in question can be drawn.
@@ -682,17 +717,18 @@ void gp_apply_parent_point(
void gp_point_to_xy(
const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y)
{
- const ARegion *ar = gsc->ar;
+ const ARegion *region = gsc->region;
const View2D *v2d = gsc->v2d;
const rctf *subrect = gsc->subrect;
int xyval[2];
/* sanity checks */
- BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
- BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
+ BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->area->spacetype == SPACE_VIEW3D));
+ BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->area->spacetype != SPACE_VIEW3D));
if (gps->flag & GP_STROKE_3DSPACE) {
- if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_int_global(region, &pt->x, xyval, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK) {
*r_x = xyval[0];
*r_y = xyval[1];
}
@@ -709,8 +745,8 @@ void gp_point_to_xy(
else {
if (subrect == NULL) {
/* normal 3D view (or view space) */
- *r_x = (int)(pt->x / 100 * ar->winx);
- *r_y = (int)(pt->y / 100 * ar->winy);
+ *r_x = (int)(pt->x / 100 * region->winx);
+ *r_y = (int)(pt->y / 100 * region->winy);
}
else {
/* camera view, use subrect */
@@ -739,17 +775,18 @@ void gp_point_to_xy_fl(const GP_SpaceConversion *gsc,
float *r_x,
float *r_y)
{
- const ARegion *ar = gsc->ar;
+ const ARegion *region = gsc->region;
const View2D *v2d = gsc->v2d;
const rctf *subrect = gsc->subrect;
float xyval[2];
/* sanity checks */
- BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
- BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
+ BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->area->spacetype == SPACE_VIEW3D));
+ BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->area->spacetype != SPACE_VIEW3D));
if (gps->flag & GP_STROKE_3DSPACE) {
- if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_global(region, &pt->x, xyval, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK) {
*r_x = xyval[0];
*r_y = xyval[1];
}
@@ -778,8 +815,8 @@ void gp_point_to_xy_fl(const GP_SpaceConversion *gsc,
else {
if (subrect == NULL) {
/* normal 3D view (or view space) */
- *r_x = (pt->x / 100.0f * ar->winx);
- *r_y = (pt->y / 100.0f * ar->winy);
+ *r_x = (pt->x / 100.0f * region->winx);
+ *r_y = (pt->y / 100.0f * region->winy);
}
else {
/* camera view, use subrect */
@@ -797,16 +834,16 @@ void gp_point_3d_to_xy(const GP_SpaceConversion *gsc,
const float pt[3],
float xy[2])
{
- const ARegion *ar = gsc->ar;
+ const ARegion *region = gsc->region;
const View2D *v2d = gsc->v2d;
const rctf *subrect = gsc->subrect;
float xyval[2];
/* sanity checks */
- BLI_assert((gsc->sa->spacetype == SPACE_VIEW3D));
+ BLI_assert((gsc->area->spacetype == SPACE_VIEW3D));
if (flag & GP_STROKE_3DSPACE) {
- if (ED_view3d_project_float_global(ar, pt, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_global(region, pt, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
xy[0] = xyval[0];
xy[1] = xyval[1];
}
@@ -835,8 +872,8 @@ void gp_point_3d_to_xy(const GP_SpaceConversion *gsc,
else {
if (subrect == NULL) {
/* normal 3D view (or view space) */
- xy[0] = (pt[0] / 100.0f * ar->winx);
- xy[1] = (pt[1] / 100.0f * ar->winy);
+ xy[0] = (pt[0] / 100.0f * region->winx);
+ xy[1] = (pt[1] / 100.0f * region->winy);
}
else {
/* camera view, use subrect */
@@ -866,11 +903,10 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc,
const float screen_co[2],
float r_out[3])
{
- const RegionView3D *rv3d = gsc->ar->regiondata;
+ const RegionView3D *rv3d = gsc->region->regiondata;
float rvec[3];
- ED_gp_get_drawing_reference(
- scene, gsc->ob, gsc->gpl, scene->toolsettings->gpencil_v3d_align, rvec);
+ ED_gpencil_drawing_reference_get(scene, gsc->ob, scene->toolsettings->gpencil_v3d_align, rvec);
float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
@@ -879,10 +915,10 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc,
copy_v2_v2(mval_f, screen_co);
- if (ED_view3d_project_float_global(gsc->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
+ if (ED_view3d_project_float_global(gsc->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK) {
sub_v2_v2v2(mval_f, mval_prj, mval_f);
- ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac);
+ ED_view3d_win_to_delta(gsc->region, mval_f, dvec, zfac);
sub_v3_v3v3(r_out, rvec, dvec);
return true;
@@ -903,9 +939,8 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc,
* \param[out] r_out: The resulting 2D point data.
*/
void gp_stroke_convertcoords_tpoint(Scene *scene,
- ARegion *ar,
+ ARegion *region,
Object *ob,
- bGPDlayer *gpl,
const tGPspoint *point2D,
float *depth,
float r_out[3])
@@ -915,7 +950,7 @@ void gp_stroke_convertcoords_tpoint(Scene *scene,
int mval_i[2];
round_v2i_v2fl(mval_i, &point2D->x);
- if ((depth != NULL) && (ED_view3d_autodist_simple(ar, mval_i, r_out, 0, depth))) {
+ if ((depth != NULL) && (ED_view3d_autodist_simple(region, mval_i, r_out, 0, depth))) {
/* projecting onto 3D-Geometry
* - nothing more needs to be done here, since view_autodist_simple() has already done it
*/
@@ -929,12 +964,13 @@ void gp_stroke_convertcoords_tpoint(Scene *scene,
/* Current method just converts each point in screen-coordinates to
* 3D-coordinates using the 3D-cursor as reference.
*/
- ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, rvec);
- zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
+ ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, rvec);
+ zfac = ED_view3d_calc_zfac(region->regiondata, rvec, NULL);
- if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_global(region, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK) {
sub_v2_v2v2(mval_f, mval_prj, mval_f);
- ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
+ ED_view3d_win_to_delta(region, mval_f, dvec, zfac);
sub_v3_v3v3(r_out, rvec, dvec);
}
else {
@@ -947,8 +983,10 @@ void gp_stroke_convertcoords_tpoint(Scene *scene,
* Get drawing reference point for conversion or projection of the stroke
* \param[out] r_vec : Reference point found
*/
-void ED_gp_get_drawing_reference(
- const Scene *scene, const Object *ob, bGPDlayer *UNUSED(gpl), char align_flag, float r_vec[3])
+void ED_gpencil_drawing_reference_get(const Scene *scene,
+ const Object *ob,
+ char align_flag,
+ float r_vec[3])
{
const float *fp = scene->cursor.location;
@@ -977,7 +1015,6 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = (bGPdata *)ob->data;
GP_SpaceConversion gsc = {NULL};
bGPDspoint *pt;
@@ -988,7 +1025,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *
/* init space conversion stuff */
gp_point_conversion_init(C, &gsc);
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
/* Adjust each point */
@@ -1180,7 +1217,6 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* move points from last to first to new place */
i2 = gps->totpoints - 1;
@@ -1195,6 +1231,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
pt_final->flag = pt->flag;
pt_final->uv_fac = pt->uv_fac;
pt_final->uv_rot = pt->uv_rot;
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
MDeformVert *dvert = &gps->dvert[i];
@@ -1221,6 +1258,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f);
pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f);
+ interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
if (gps->dvert != NULL) {
MDeformVert *dvert_final = &gps->dvert[i2];
@@ -1249,116 +1287,11 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
/* free temp memory */
MEM_SAFE_FREE(temp_points);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
-/**
- * Add randomness to stroke
- * \param gps: Stroke data
- * \param brush: Brush data
- */
-void gp_randomize_stroke(bGPDstroke *gps, Brush *brush, RNG *rng)
-{
- bGPDspoint *pt1, *pt2, *pt3;
- float v1[3];
- float v2[3];
- if (gps->totpoints < 3) {
- return;
- }
-
- /* get two vectors using 3 points */
- pt1 = &gps->points[0];
- pt2 = &gps->points[1];
- pt3 = &gps->points[(int)(gps->totpoints * 0.75)];
-
- sub_v3_v3v3(v1, &pt2->x, &pt1->x);
- sub_v3_v3v3(v2, &pt3->x, &pt2->x);
- normalize_v3(v1);
- normalize_v3(v2);
-
- /* get normal vector to plane created by two vectors */
- float normal[3];
- cross_v3_v3v3(normal, v1, v2);
- normalize_v3(normal);
-
- /* get orthogonal vector to plane to rotate random effect */
- float ortho[3];
- cross_v3_v3v3(ortho, v1, normal);
- normalize_v3(ortho);
-
- /* Read all points and apply shift vector (first and last point not modified) */
- for (int i = 1; i < gps->totpoints - 1; i++) {
- bGPDspoint *pt = &gps->points[i];
- /* get vector with shift (apply a division because random is too sensitive */
- const float fac = BLI_rng_get_float(rng) * (brush->gpencil_settings->draw_random_sub / 10.0f);
- float svec[3];
- copy_v3_v3(svec, ortho);
- if (BLI_rng_get_float(rng) > 0.5f) {
- mul_v3_fl(svec, -fac);
- }
- else {
- mul_v3_fl(svec, fac);
- }
-
- /* apply shift */
- add_v3_v3(&pt->x, svec);
- }
-}
-
-/* ******************************************************** */
-/* Layer Parenting - Compute Parent Transforms */
-
-/* calculate difference matrix */
-void ED_gpencil_parent_location(const Depsgraph *depsgraph,
- Object *obact,
- bGPdata *UNUSED(gpd),
- bGPDlayer *gpl,
- float diff_mat[4][4])
-{
- Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
- Object *obparent = gpl->parent;
- Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) :
- obparent;
-
- /* if not layer parented, try with object parented */
- if (obparent_eval == NULL) {
- if (ob_eval != NULL) {
- if (ob_eval->type == OB_GPENCIL) {
- copy_m4_m4(diff_mat, ob_eval->obmat);
- return;
- }
- }
- /* not gpencil object */
- unit_m4(diff_mat);
- return;
- }
- else {
- if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
- mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
- add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
- return;
- }
- else if (gpl->partype == PARBONE) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
- if (pchan) {
- float tmp_mat[4][4];
- mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
- mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
- add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
- }
- else {
- /* if bone not found use object (armature) */
- mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
- add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
- }
- return;
- }
- else {
- unit_m4(diff_mat); /* not defined type */
- }
- }
-}
-
-/* reset parent matrix for all layers */
+/* Reset parent matrix for all layers. */
void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd)
{
bGPDspoint *pt;
@@ -1368,7 +1301,7 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata
float gpl_loc[3];
zero_v3(gpl_loc);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->parent != NULL) {
/* calculate new matrix */
if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
@@ -1388,12 +1321,12 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata
/* only redo if any change */
if (!equals_m4m4(gpl->inverse, cur_mat)) {
/* first apply current transformation to all strokes */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* undo local object */
sub_v3_v3(diff_mat[3], gpl_loc);
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
mul_m4_v3(diff_mat, &pt->x);
}
@@ -1409,10 +1342,7 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata
/* GP Object Stuff */
/* Helper function to create new OB_GPENCIL Object */
-Object *ED_gpencil_add_object(bContext *C,
- Scene *UNUSED(scene),
- const float loc[3],
- ushort local_view_bits)
+Object *ED_gpencil_add_object(bContext *C, const float loc[3], ushort local_view_bits)
{
float rot[3] = {0.0f};
@@ -1435,7 +1365,7 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob)
/* if not exist, create a new one */
if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
- BKE_brush_gpencil_presets(bmain, ts);
+ BKE_brush_gpencil_paint_presets(bmain, ts, true);
}
/* ensure a color exists and is assigned to object */
@@ -1491,7 +1421,7 @@ void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight)
bGPDspoint *pt = &gps->points[i];
MDeformVert *dvert = &gps->dvert[i];
if (pt->flag & GP_SPOINT_SELECT) {
- MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr);
if (dw) {
dw->weight = weight;
}
@@ -1545,9 +1475,9 @@ void ED_gpencil_vgroup_remove(bContext *C, Object *ob)
MDeformVert *dvert = &gps->dvert[i];
if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) {
- MDeformWeight *dw = defvert_find_index(dvert, def_nr);
+ MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr);
if (dw != NULL) {
- defvert_remove_group(dvert, dw);
+ BKE_defvert_remove_group(dvert, dw);
}
}
}
@@ -1597,7 +1527,7 @@ void ED_gpencil_vgroup_select(bContext *C, Object *ob)
}
MDeformVert *dvert = &gps->dvert[i];
- if (defvert_find_index(dvert, def_nr) != NULL) {
+ if (BKE_defvert_find_index(dvert, def_nr) != NULL) {
pt->flag |= GP_SPOINT_SELECT;
gps->flag |= GP_STROKE_SELECT;
}
@@ -1648,7 +1578,7 @@ void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
}
MDeformVert *dvert = &gps->dvert[i];
- if (defvert_find_index(dvert, def_nr) != NULL) {
+ if (BKE_defvert_find_index(dvert, def_nr) != NULL) {
pt->flag &= ~GP_SPOINT_SELECT;
}
}
@@ -1670,24 +1600,27 @@ void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
/* check if cursor is in drawing region */
static bool gp_check_cursor_region(bContext *C, int mval_i[2])
{
- ARegion *ar = CTX_wm_region(C);
- ScrArea *sa = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
Object *ob = CTX_data_active_object(C);
- if ((ob == NULL) ||
- (!ELEM(ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL))) {
+ if ((ob == NULL) || (!ELEM(ob->mode,
+ OB_MODE_PAINT_GPENCIL,
+ OB_MODE_SCULPT_GPENCIL,
+ OB_MODE_WEIGHT_GPENCIL,
+ OB_MODE_VERTEX_GPENCIL))) {
return false;
}
/* TODO: add more spacetypes */
- if (!ELEM(sa->spacetype, SPACE_VIEW3D)) {
+ if (!ELEM(area->spacetype, SPACE_VIEW3D)) {
return false;
}
- if ((ar) && (ar->regiontype != RGN_TYPE_WINDOW)) {
+ if ((region) && (region->regiontype != RGN_TYPE_WINDOW)) {
return false;
}
- else if (ar) {
- return BLI_rcti_isect_pt_v(&ar->winrct, mval_i);
+ else if (region) {
+ return BLI_rcti_isect_pt_v(&region->winrct, mval_i);
}
else {
return false;
@@ -1750,23 +1683,15 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
- GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
bGPdata *gpd = ED_gpencil_data_get_active(C);
- GP_Sculpt_Data *gp_brush = NULL;
Brush *brush = NULL;
Material *ma = NULL;
MaterialGPencilStyle *gp_style = NULL;
float *last_mouse_position = customdata;
- if ((gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE)) {
- gp_brush = &gset->brush[gset->weighttype];
- }
- else {
- gp_brush = &gset->brush[gset->brushtype];
- }
-
/* default radius and color */
float color[3] = {1.0f, 1.0f, 1.0f};
float darkcolor[3];
@@ -1792,7 +1717,7 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
return;
}
- if ((brush->gpencil_settings->flag & GP_BRUSH_ENABLE_CURSOR) == 0) {
+ if ((paint->flags & PAINT_SHOW_BRUSH) == 0) {
return;
}
@@ -1803,7 +1728,7 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
}
/* get current drawing color */
- ma = BKE_gpencil_object_material_get_from_brush(ob, brush);
+ ma = BKE_gpencil_object_material_from_brush_get(ob, brush);
if (ma) {
gp_style = ma->gp_style;
@@ -1820,29 +1745,73 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
copy_v3_v3(color, gp_style->stroke_rgba);
}
else {
- radius = 5.0f;
- copy_v3_v3(color, brush->add_col);
+ /* Only Tint tool must show big cursor. */
+ if (brush->gpencil_tool == GPAINT_TOOL_TINT) {
+ radius = brush->size;
+ copy_v3_v3(color, brush->rgb);
+ }
+ else {
+ radius = 5.0f;
+ copy_v3_v3(color, brush->add_col);
+ }
}
}
}
- /* for sculpt use sculpt brush size */
- if (GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd)) {
- if (gp_brush) {
- if ((gp_brush->flag & GP_SCULPT_FLAG_ENABLE_CURSOR) == 0) {
- return;
- }
+ /* Sculpt use sculpt brush size */
+ if (GPENCIL_SCULPT_MODE(gpd)) {
+ brush = scene->toolsettings->gp_sculptpaint->paint.brush;
+ if ((brush == NULL) || (brush->gpencil_settings == NULL)) {
+ return;
+ }
+ if ((paint->flags & PAINT_SHOW_BRUSH) == 0) {
+ return;
+ }
- radius = gp_brush->size;
- if (gp_brush->flag & (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT)) {
- copy_v3_v3(color, gp_brush->curcolor_sub);
- }
- else {
- copy_v3_v3(color, gp_brush->curcolor_add);
- }
+ radius = brush->size;
+ if (brush->gpencil_settings->sculpt_flag &
+ (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT)) {
+ copy_v3_v3(color, brush->sub_col);
+ }
+ else {
+ copy_v3_v3(color, brush->add_col);
}
}
+ /* Weight Paint */
+ if (GPENCIL_WEIGHT_MODE(gpd)) {
+ brush = scene->toolsettings->gp_weightpaint->paint.brush;
+ if ((brush == NULL) || (brush->gpencil_settings == NULL)) {
+ return;
+ }
+ if ((paint->flags & PAINT_SHOW_BRUSH) == 0) {
+ return;
+ }
+
+ radius = brush->size;
+ if (brush->gpencil_settings->sculpt_flag &
+ (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT)) {
+ copy_v3_v3(color, brush->sub_col);
+ }
+ else {
+ copy_v3_v3(color, brush->add_col);
+ }
+ }
+
+ /* For Vertex Paint use brush size. */
+ if (GPENCIL_VERTEX_MODE(gpd)) {
+ brush = scene->toolsettings->gp_vertexpaint->paint.brush;
+ if ((brush == NULL) || (brush->gpencil_settings == NULL)) {
+ return;
+ }
+ if ((paint->flags & PAINT_SHOW_BRUSH) == 0) {
+ return;
+ }
+
+ radius = brush->size;
+ copy_v3_v3(color, brush->rgb);
+ }
+
/* draw icon */
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -1881,8 +1850,9 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, x, y);
- immVertex2f(
- pos, last_mouse_position[0] + ar->winrct.xmin, last_mouse_position[1] + ar->winrct.ymin);
+ immVertex2f(pos,
+ last_mouse_position[0] + region->winrct.xmin,
+ last_mouse_position[1] + region->winrct.ymin);
immEnd();
GPU_blend(false);
@@ -1921,30 +1891,6 @@ void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata)
}
}
-/* verify if is using the right brush */
-static void gpencil_verify_brush_type(bContext *C, int newmode)
-{
- ToolSettings *ts = CTX_data_tool_settings(C);
- GP_Sculpt_Settings *gset = &ts->gp_sculpt;
-
- switch (newmode) {
- case OB_MODE_SCULPT_GPENCIL:
- gset->flag &= ~GP_SCULPT_SETT_FLAG_WEIGHT_MODE;
- if ((gset->brushtype < 0) || (gset->brushtype >= GP_SCULPT_TYPE_WEIGHT)) {
- gset->brushtype = GP_SCULPT_TYPE_PUSH;
- }
- break;
- case OB_MODE_WEIGHT_GPENCIL:
- gset->flag |= GP_SCULPT_SETT_FLAG_WEIGHT_MODE;
- if ((gset->weighttype < GP_SCULPT_TYPE_WEIGHT) || (gset->weighttype >= GP_SCULPT_TYPE_MAX)) {
- gset->weighttype = GP_SCULPT_TYPE_WEIGHT;
- }
- break;
- default:
- break;
- }
-}
-
/* set object modes */
void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
{
@@ -1958,6 +1904,7 @@ void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, false, NULL);
break;
case OB_MODE_PAINT_GPENCIL:
@@ -1965,6 +1912,7 @@ void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
gpd->flag |= GP_DATA_STROKE_PAINTMODE;
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, true, NULL);
break;
case OB_MODE_SCULPT_GPENCIL:
@@ -1972,7 +1920,7 @@ void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
gpd->flag |= GP_DATA_STROKE_SCULPTMODE;
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
- gpencil_verify_brush_type(C, OB_MODE_SCULPT_GPENCIL);
+ gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, true, NULL);
break;
case OB_MODE_WEIGHT_GPENCIL:
@@ -1980,7 +1928,15 @@ void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
gpd->flag |= GP_DATA_STROKE_WEIGHTMODE;
- gpencil_verify_brush_type(C, OB_MODE_WEIGHT_GPENCIL);
+ gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ break;
+ case OB_MODE_VERTEX_GPENCIL:
+ gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
+ gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ gpd->flag |= GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, true, NULL);
break;
default:
@@ -1988,13 +1944,14 @@ void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
+ gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
ED_gpencil_toggle_brush_cursor(C, false, NULL);
break;
}
}
/* helper to convert 2d to 3d for simple drawing buffer */
-static void gpencil_stroke_convertcoords(ARegion *ar,
+static void gpencil_stroke_convertcoords(ARegion *region,
const tGPspoint *point2D,
const float origin[3],
float out[3])
@@ -2006,11 +1963,12 @@ static void gpencil_stroke_convertcoords(ARegion *ar,
copy_v3_v3(rvec, origin);
- zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
+ zfac = ED_view3d_calc_zfac(region->regiondata, rvec, NULL);
- if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_global(region, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK) {
sub_v2_v2v2(mval_f, mval_prj, mval_f);
- ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
+ ED_view3d_win_to_delta(region, mval_f, dvec, zfac);
sub_v3_v3v3(out, rvec, dvec);
}
else {
@@ -2019,12 +1977,16 @@ static void gpencil_stroke_convertcoords(ARegion *ar,
}
/* convert 2d tGPspoint to 3d bGPDspoint */
-void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *tpt, bGPDspoint *pt)
+void ED_gpencil_tpoint_to_point(ARegion *region,
+ float origin[3],
+ const tGPspoint *tpt,
+ bGPDspoint *pt)
{
float p3d[3];
/* conversion to 3d format */
- gpencil_stroke_convertcoords(ar, tpt, origin, p3d);
+ gpencil_stroke_convertcoords(region, tpt, origin, p3d);
copy_v3_v3(&pt->x, p3d);
+ zero_v4(pt->vert_color);
pt->pressure = tpt->pressure;
pt->strength = tpt->strength;
@@ -2032,63 +1994,6 @@ void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *t
pt->uv_rot = tpt->uv_rot;
}
-/* texture coordinate utilities */
-void ED_gpencil_calc_stroke_uv(Object *ob, bGPDstroke *gps)
-{
- if (gps == NULL) {
- return;
- }
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
- float pixsize;
- if (gp_style) {
- pixsize = gp_style->texture_pixsize / 1000000.0f;
- }
- else {
- /* use this value by default */
- pixsize = 0.0001f;
- }
- pixsize = MAX2(pixsize, 0.0000001f);
-
- bGPDspoint *pt = NULL;
- bGPDspoint *ptb = NULL;
- int i;
- float totlen = 0.0f;
-
- /* first read all points and calc distance */
- for (i = 0; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- /* first point */
- if (i == 0) {
- pt->uv_fac = 0.0f;
- continue;
- }
-
- ptb = &gps->points[i - 1];
- totlen += len_v3v3(&pt->x, &ptb->x) / pixsize;
- pt->uv_fac = totlen;
- }
-
- /* normalize the distance using a factor */
- float factor;
-
- /* if image, use texture width */
- if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) &&
- (gp_style->sima)) {
- factor = gp_style->sima->gen_x;
- }
- else if (totlen == 0) {
- return;
- }
- else {
- factor = totlen;
- }
-
- for (i = 0; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- pt->uv_fac /= factor;
- }
-}
-
/* recalc uv for any stroke using the material */
void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
{
@@ -2101,19 +2006,19 @@ void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
continue;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl)) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (BKE_gpencil_layer_is_editable(gpl)) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* check if it is editable */
if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
continue;
}
- gps_ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
+ gps_ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
/* update */
if ((gps_ma) && (gps_ma == mat)) {
- ED_gpencil_calc_stroke_uv(ob, gps);
+ BKE_gpencil_stroke_uv_update(gps);
}
}
}
@@ -2190,6 +2095,7 @@ static void gp_copy_points(bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final
pt_final->flag = pt->flag;
pt_final->uv_fac = pt->uv_fac;
pt_final->uv_rot = pt->uv_rot;
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
MDeformVert *dvert = &gps->dvert[i];
@@ -2244,7 +2150,6 @@ static void gp_insert_point(
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* copy all points */
int i2 = 0;
@@ -2268,6 +2173,8 @@ static void gp_insert_point(
i2++;
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
MEM_SAFE_FREE(temp_points);
}
@@ -2304,7 +2211,8 @@ int ED_gpencil_select_stroke_segment(bGPDlayer *gpl,
float f = 0.0f;
int i2 = 0;
- bGPDframe *gpf = gpl->actframe;
+ bGPDlayer *gpl_orig = (gpl->runtime.gpl_orig) ? gpl->runtime.gpl_orig : gpl;
+ bGPDframe *gpf = gpl_orig->actframe;
if (gpf == NULL) {
return 0;
}
@@ -2317,7 +2225,7 @@ int ED_gpencil_select_stroke_segment(bGPDlayer *gpl,
/* Save list of strokes to check */
int totstrokes = 0;
- for (bGPDstroke *gps_iter = gpf->strokes.first; gps_iter; gps_iter = gps_iter->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps_iter, &gpf->strokes) {
if (gps_iter->totpoints < 2) {
continue;
}
@@ -2511,10 +2419,9 @@ void ED_gpencil_select_toggle_all(bContext *C, int action)
* nothing should be able to touch it
*/
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- bGPDframe *gpf;
/* deselect all strokes on all frames */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
bGPDstroke *gps;
for (gps = gpf->strokes.first; gps; gps = gps->next) {
@@ -2611,6 +2518,18 @@ tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array,
return buffer_array;
}
+void ED_gpencil_sbuffer_update_eval(bGPdata *gpd, Object *ob_eval)
+{
+ bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
+
+ gpd_eval->runtime.sbuffer = gpd->runtime.sbuffer;
+ gpd_eval->runtime.sbuffer_sflag = gpd->runtime.sbuffer_sflag;
+ gpd_eval->runtime.sbuffer_used = gpd->runtime.sbuffer_used;
+ gpd_eval->runtime.sbuffer_size = gpd->runtime.sbuffer_size;
+ gpd_eval->runtime.tot_cp_points = gpd->runtime.tot_cp_points;
+ gpd_eval->runtime.cp_points = gpd->runtime.cp_points;
+}
+
/* Tag all scene grease pencil object to update. */
void ED_gpencil_tag_scene_gpencil(Scene *scene)
{
@@ -2631,3 +2550,253 @@ void ED_gpencil_tag_scene_gpencil(Scene *scene)
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
+
+void ED_gpencil_fill_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDstroke *gps)
+{
+ if (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush)) {
+ copy_v3_v3(gps->vert_color_fill, brush->rgb);
+ gps->vert_color_fill[3] = brush->gpencil_settings->vertex_factor;
+ srgb_to_linearrgb_v4(gps->vert_color_fill, gps->vert_color_fill);
+ }
+ else {
+ zero_v4(gps->vert_color_fill);
+ }
+}
+
+void ED_gpencil_point_vertex_color_set(ToolSettings *ts,
+ Brush *brush,
+ bGPDspoint *pt,
+ tGPspoint *tpt)
+{
+ if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) {
+ if (tpt == NULL) {
+ copy_v3_v3(pt->vert_color, brush->rgb);
+ pt->vert_color[3] = brush->gpencil_settings->vertex_factor;
+ srgb_to_linearrgb_v4(pt->vert_color, pt->vert_color);
+ }
+ else {
+ copy_v3_v3(pt->vert_color, tpt->vert_color);
+ pt->vert_color[3] = brush->gpencil_settings->vertex_factor;
+ }
+ }
+ else {
+ zero_v4(pt->vert_color);
+ }
+}
+
+void ED_gpencil_init_random_settings(Brush *brush,
+ const int mval[2],
+ GpRandomSettings *random_settings)
+{
+ int seed = ((uint)(ceil(PIL_check_seconds_timer())) + 1) % 128;
+ /* Use mouse position to get randomness. */
+ int ix = mval[0] * seed;
+ int iy = mval[1] * seed;
+ int iz = ix + iy * seed;
+ zero_v3(random_settings->hsv);
+
+ BrushGpencilSettings *brush_settings = brush->gpencil_settings;
+ /* Random to Hue. */
+ if (brush_settings->random_hue > 0.0f) {
+ float rand = BLI_hash_int_01(BLI_hash_int_2d(ix, iy)) * 2.0f - 1.0f;
+ random_settings->hsv[0] = rand * brush_settings->random_hue * 0.5f;
+ }
+ /* Random to Saturation. */
+ if (brush_settings->random_saturation > 0.0f) {
+ float rand = BLI_hash_int_01(BLI_hash_int_2d(iy, ix)) * 2.0f - 1.0f;
+ random_settings->hsv[1] = rand * brush_settings->random_saturation;
+ }
+ /* Random to Value. */
+ if (brush_settings->random_value > 0.0f) {
+ float rand = BLI_hash_int_01(BLI_hash_int_2d(ix * iz, iy * iz)) * 2.0f - 1.0f;
+ random_settings->hsv[2] = rand * brush_settings->random_value;
+ }
+
+ /* Random to pressure. */
+ if (brush_settings->draw_random_press > 0.0f) {
+ random_settings->pressure = BLI_hash_int_01(BLI_hash_int_2d(ix + iz, iy + iz)) * 2.0f - 1.0f;
+ }
+
+ /* Randomn to color strength. */
+ if (brush_settings->draw_random_strength) {
+ random_settings->strength = BLI_hash_int_01(BLI_hash_int_2d(ix + iy, iy + iz + ix)) * 2.0f -
+ 1.0f;
+ }
+
+ /* Random to uv texture rotation. */
+ if (brush_settings->uv_random > 0.0f) {
+ random_settings->uv = BLI_hash_int_01(BLI_hash_int_2d(iy + iz, ix * iz)) * 2.0f - 1.0f;
+ }
+}
+
+static void gpencil_sbuffer_vertex_color_random(
+ bGPdata *gpd, Brush *brush, tGPspoint *tpt, float random_color[3], float pen_pressure)
+{
+ BrushGpencilSettings *brush_settings = brush->gpencil_settings;
+ if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) {
+ int seed = ((uint)(ceil(PIL_check_seconds_timer())) + 1) % 128;
+
+ int ix = (int)(tpt->x * seed);
+ int iy = (int)(tpt->y * seed);
+ int iz = ix + iy * seed;
+ float hsv[3];
+ float factor_value[3];
+ zero_v3(factor_value);
+
+ /* Apply randomness to Hue. */
+ if (brush_settings->random_hue > 0.0f) {
+ if ((brush_settings->flag2 & GP_BRUSH_USE_HUE_AT_STROKE) == 0) {
+
+ float rand = BLI_hash_int_01(BLI_hash_int_2d(ix, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f;
+ factor_value[0] = rand * brush_settings->random_hue * 0.5f;
+ }
+ else {
+ factor_value[0] = random_color[0];
+ }
+
+ /* Apply random curve. */
+ if (brush_settings->flag2 & GP_BRUSH_USE_HUE_RAND_PRESS) {
+ factor_value[0] *= BKE_curvemapping_evaluateF(
+ brush_settings->curve_rand_hue, 0, pen_pressure);
+ }
+ }
+
+ /* Apply randomness to Saturation. */
+ if (brush_settings->random_saturation > 0.0f) {
+ if ((brush_settings->flag2 & GP_BRUSH_USE_SAT_AT_STROKE) == 0) {
+ float rand = BLI_hash_int_01(BLI_hash_int_2d(iy, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f;
+ factor_value[1] = rand * brush_settings->random_saturation;
+ }
+ else {
+ factor_value[1] = random_color[1];
+ }
+
+ /* Apply random curve. */
+ if (brush_settings->flag2 & GP_BRUSH_USE_SAT_RAND_PRESS) {
+ factor_value[1] *= BKE_curvemapping_evaluateF(
+ brush_settings->curve_rand_saturation, 0, pen_pressure);
+ }
+ }
+
+ /* Apply randomness to Value. */
+ if (brush_settings->random_value > 0.0f) {
+ if ((brush_settings->flag2 & GP_BRUSH_USE_VAL_AT_STROKE) == 0) {
+ float rand = BLI_hash_int_01(BLI_hash_int_2d(iz, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f;
+ factor_value[2] = rand * brush_settings->random_value;
+ }
+ else {
+ factor_value[2] = random_color[2];
+ }
+
+ /* Apply random curve. */
+ if (brush_settings->flag2 & GP_BRUSH_USE_VAL_RAND_PRESS) {
+ factor_value[2] *= BKE_curvemapping_evaluateF(
+ brush_settings->curve_rand_value, 0, pen_pressure);
+ }
+ }
+
+ rgb_to_hsv_v(tpt->vert_color, hsv);
+ add_v3_v3(hsv, factor_value);
+ /* For Hue need to cover all range, but for Saturation and Value
+ * is not logic because the effect is too hard, so the value is just clamped. */
+ if (hsv[0] < 0.0f) {
+ hsv[0] += 1.0f;
+ }
+ else if (hsv[0] > 1.0f) {
+ hsv[0] -= 1.0f;
+ }
+
+ CLAMP3(hsv, 0.0f, 1.0f);
+ hsv_to_rgb_v(hsv, tpt->vert_color);
+ }
+}
+
+void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph,
+ Object *ob,
+ ToolSettings *ts,
+ Brush *brush,
+ Material *material,
+ float random_color[3],
+ float pen_pressure)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &ob->id);
+ bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
+ MaterialGPencilStyle *gp_style = material->gp_style;
+
+ int idx = gpd->runtime.sbuffer_used;
+ tGPspoint *tpt = (tGPspoint *)gpd->runtime.sbuffer + idx;
+
+ float vertex_color[4];
+ copy_v3_v3(vertex_color, brush->rgb);
+ vertex_color[3] = brush->gpencil_settings->vertex_factor;
+ srgb_to_linearrgb_v4(vertex_color, vertex_color);
+
+ /* Copy fill vertex color. */
+ if (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush)) {
+ copy_v4_v4(gpd->runtime.vert_color_fill, vertex_color);
+ }
+ else {
+ copy_v4_v4(gpd->runtime.vert_color_fill, gp_style->fill_rgba);
+ }
+ /* Copy stroke vertex color. */
+ if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) {
+ copy_v4_v4(tpt->vert_color, vertex_color);
+ }
+ else {
+ copy_v4_v4(tpt->vert_color, gp_style->stroke_rgba);
+ }
+
+ /* Random Color. */
+ gpencil_sbuffer_vertex_color_random(gpd, brush, tpt, random_color, pen_pressure);
+
+ /* Copy to eval data because paint operators don't tag refresh until end for speedup
+ painting. */
+ if (gpd_eval != NULL) {
+ copy_v4_v4(gpd_eval->runtime.vert_color_fill, gpd->runtime.vert_color_fill);
+ gpd_eval->runtime.matid = gpd->runtime.matid;
+ }
+}
+
+/* Check if the stroke collides with brush. */
+bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc,
+ bGPDstroke *gps,
+ float mouse[2],
+ const int radius,
+ const float diff_mat[4][4])
+{
+ const int offset = (int)ceil(sqrt((radius * radius) * 2));
+ bGPDspoint pt_dummy, pt_dummy_ps;
+ float boundbox_min[2] = {0.0f};
+ float boundbox_max[2] = {0.0f};
+
+ /* Check we have something to use (only for old files). */
+ if (is_zero_v3(gps->boundbox_min)) {
+ BKE_gpencil_stroke_boundingbox_calc(gps);
+ }
+
+ /* Convert bound box to 2d */
+ copy_v3_v3(&pt_dummy.x, gps->boundbox_min);
+ gp_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps);
+ gp_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_min[0], &boundbox_min[1]);
+
+ copy_v3_v3(&pt_dummy.x, gps->boundbox_max);
+ gp_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps);
+ gp_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_max[0], &boundbox_max[1]);
+
+ /* Ensure the bounding box is oriented to axis. */
+ if (boundbox_max[0] < boundbox_min[0]) {
+ SWAP(float, boundbox_min[0], boundbox_max[0]);
+ }
+ if (boundbox_max[1] < boundbox_min[1]) {
+ SWAP(float, boundbox_min[1], boundbox_max[1]);
+ }
+
+ rcti rect_stroke = {boundbox_min[0], boundbox_max[0], boundbox_min[1], boundbox_max[1]};
+
+ /* For mouse, add a small offet to avoid false negative in corners. */
+ rcti rect_mouse = {mouse[0] - offset, mouse[0] + offset, mouse[1] - offset, mouse[1] + offset};
+
+ /* Check collision between both rectangles. */
+ return BLI_rcti_isect(&rect_stroke, &rect_mouse, NULL);
+}
diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c
new file mode 100644
index 00000000000..2238d768bcd
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_uv.c
@@ -0,0 +1,590 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edgpencil
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_gpencil_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_unit.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+
+#include "ED_gpencil.h"
+#include "ED_numinput.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_view3d.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "gpencil_intern.h"
+
+typedef struct GpUvData {
+ Object *ob;
+ bGPdata *gpd;
+ GP_SpaceConversion gsc;
+ float ob_scale;
+
+ float initial_length;
+ float pixel_size; /* use when mouse input is interpreted as spatial distance */
+ bool is_modal;
+
+ /* Arrays of original loc/rot/scale by stroke. */
+ float (*array_loc)[2];
+ float *array_rot;
+ float *array_scale;
+
+ /* modal only */
+ float mcenter[2];
+ float mouse[2];
+
+ /** Vector with the original orientation. */
+ float vinit_rotation[2];
+
+ void *draw_handle_pixel;
+} GpUvData;
+
+enum {
+ GP_UV_ROTATE = 0,
+ GP_UV_TRANSLATE = 1,
+ GP_UV_SCALE = 2,
+ GP_UV_ALL = 3,
+};
+
+#define SMOOTH_FACTOR 0.3f
+
+static void gpencil_uv_transform_update_header(wmOperator *op, bContext *C)
+{
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ const char *str = TIP_("Confirm: Enter/LClick, Cancel: (Esc/RClick) %s");
+
+ char msg[UI_MAX_DRAW_STR];
+ ScrArea *area = CTX_wm_area(C);
+
+ if (area) {
+ char flts_str[NUM_STR_REP_LEN * 2];
+ switch (mode) {
+ case GP_UV_TRANSLATE: {
+ float location[2];
+ RNA_float_get_array(op->ptr, "location", location);
+ BLI_snprintf(
+ flts_str, NUM_STR_REP_LEN, ", Translation: (%f, %f)", location[0], location[1]);
+ break;
+ }
+ case GP_UV_ROTATE: {
+ BLI_snprintf(flts_str,
+ NUM_STR_REP_LEN,
+ ", Rotation: %f",
+ RAD2DEG(RNA_float_get(op->ptr, "rotation")));
+ break;
+ }
+ case GP_UV_SCALE: {
+ BLI_snprintf(
+ flts_str, NUM_STR_REP_LEN, ", Scale: %f", RAD2DEG(RNA_float_get(op->ptr, "scale")));
+ break;
+ }
+ default:
+ break;
+ }
+ BLI_snprintf(msg, sizeof(msg), str, flts_str, flts_str + NUM_STR_REP_LEN);
+ ED_area_status_text(area, msg);
+ }
+}
+
+/* Helper: Get stroke center. */
+static void gpencil_stroke_center(bGPDstroke *gps, float r_center[3])
+{
+ bGPDspoint *pt;
+ int i;
+
+ zero_v3(r_center);
+ if (gps->totpoints > 0) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ add_v3_v3(r_center, &pt->x);
+ }
+
+ mul_v3_fl(r_center, 1.0f / gps->totpoints);
+ }
+}
+
+static bool gpencil_uv_transform_init(bContext *C, wmOperator *op, const bool is_modal)
+{
+ GpUvData *opdata;
+ if (is_modal) {
+ float zero[2] = {0.0f};
+ RNA_float_set_array(op->ptr, "location", zero);
+ RNA_float_set(op->ptr, "rotation", 0.0f);
+ RNA_float_set(op->ptr, "scale", 1.0f);
+ }
+
+ op->customdata = opdata = MEM_mallocN(sizeof(GpUvData), __func__);
+
+ opdata->is_modal = is_modal;
+ opdata->ob = CTX_data_active_object(C);
+ opdata->gpd = (bGPdata *)opdata->ob->data;
+ gp_point_conversion_init(C, &opdata->gsc);
+ opdata->array_loc = NULL;
+ opdata->array_rot = NULL;
+ opdata->array_scale = NULL;
+ opdata->ob_scale = mat4_to_scale(opdata->ob->obmat);
+
+ opdata->vinit_rotation[0] = 1.0f;
+ opdata->vinit_rotation[1] = 0.0f;
+
+ if (is_modal) {
+ ARegion *region = CTX_wm_region(C);
+
+ opdata->draw_handle_pixel = ED_region_draw_cb_activate(
+ region->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
+ }
+
+ /* Calc selected strokes center. */
+ zero_v2(opdata->mcenter);
+ float center[3] = {0.0f};
+ int i = 0;
+ /* Need use evaluated to get the viewport final position. */
+ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ float r_center[3];
+ gpencil_stroke_center(gps, r_center);
+ /* Add object location. */
+ add_v3_v3(r_center, opdata->ob->obmat[3]);
+ add_v3_v3(center, r_center);
+ i++;
+ }
+ }
+ GP_EVALUATED_STROKES_END(gpstroke_iter);
+
+ if (i > 0) {
+ mul_v3_fl(center, 1.0f / i);
+ /* Create arrays to save all transformations. */
+ opdata->array_loc = MEM_calloc_arrayN(i, 2 * sizeof(float), __func__);
+ opdata->array_rot = MEM_calloc_arrayN(i, sizeof(float), __func__);
+ opdata->array_scale = MEM_calloc_arrayN(i, sizeof(float), __func__);
+ i = 0;
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ copy_v2_v2(opdata->array_loc[i], gps->uv_translation);
+ opdata->array_rot[i] = gps->uv_rotation;
+ opdata->array_scale[i] = gps->uv_scale;
+ i++;
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+ }
+ /* convert to 2D */
+ gp_point_3d_to_xy(&opdata->gsc, GP_STROKE_3DSPACE, center, opdata->mcenter);
+
+ return true;
+}
+
+static void gpencil_uv_transform_exit(bContext *C, wmOperator *op)
+{
+ GpUvData *opdata;
+ ScrArea *area = CTX_wm_area(C);
+
+ opdata = op->customdata;
+
+ if (opdata->is_modal) {
+ ARegion *region = CTX_wm_region(C);
+
+ ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel);
+ }
+
+ WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT);
+
+ if (area) {
+ ED_area_status_text(area, NULL);
+ }
+ WM_main_add_notifier(NC_GEOM | ND_DATA, NULL);
+
+ MEM_SAFE_FREE(opdata->array_loc);
+ MEM_SAFE_FREE(opdata->array_rot);
+ MEM_SAFE_FREE(opdata->array_scale);
+ MEM_SAFE_FREE(op->customdata);
+}
+
+static void gpencil_transform_fill_cancel(bContext *C, wmOperator *op)
+{
+ GpUvData *opdata = op->customdata;
+ UNUSED_VARS(opdata);
+
+ gpencil_uv_transform_exit(C, op);
+
+ /* need to force redisplay or we may still view the modified result */
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
+{
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ GpUvData *opdata = op->customdata;
+ bGPdata *gpd = opdata->gpd;
+ bool changed = false;
+ /* Get actual vector. */
+ float vr[2];
+ sub_v2_v2v2(vr, opdata->mouse, opdata->mcenter);
+ normalize_v2(vr);
+
+ float location[2];
+ RNA_float_get_array(op->ptr, "location", location);
+
+ float uv_rotation = (opdata->is_modal) ? angle_signed_v2v2(opdata->vinit_rotation, vr) :
+ RNA_float_get(op->ptr, "rotation");
+ uv_rotation *= SMOOTH_FACTOR;
+
+ if (opdata->is_modal) {
+ RNA_float_set(op->ptr, "rotation", uv_rotation);
+ }
+
+ int i = 0;
+
+ /* Apply transformations to all strokes. */
+ if ((mode == GP_UV_TRANSLATE) || (!opdata->is_modal)) {
+ float mdiff[2];
+ mdiff[0] = opdata->mcenter[0] - opdata->mouse[0];
+ mdiff[1] = opdata->mcenter[1] - opdata->mouse[1];
+
+ /* Apply a big amount of smooth always for translate to get smooth result. */
+ mul_v2_fl(mdiff, 0.006f);
+
+ /* Apply angle in translation. */
+ mdiff[0] *= cos(uv_rotation);
+ mdiff[1] *= sin(uv_rotation);
+ if (opdata->is_modal) {
+ RNA_float_set_array(op->ptr, "location", mdiff);
+ }
+
+ changed = (bool)((mdiff[0] != 0.0f) || (mdiff[1] != 0.0f));
+ if (changed) {
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ if (opdata->is_modal) {
+ add_v2_v2v2(gps->uv_translation, opdata->array_loc[i], mdiff);
+ }
+ else {
+ copy_v2_v2(gps->uv_translation, location);
+ }
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+ i++;
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+ }
+ }
+
+ if ((mode == GP_UV_ROTATE) || (!opdata->is_modal)) {
+ changed = (bool)(uv_rotation != 0.0f);
+ if (changed) {
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ gps->uv_rotation = (opdata->is_modal) ? opdata->array_rot[i] + uv_rotation : uv_rotation;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+ i++;
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+ }
+ }
+
+ if ((mode == GP_UV_SCALE) || (!opdata->is_modal)) {
+ float mdiff[2];
+ mdiff[0] = opdata->mcenter[0] - opdata->mouse[0];
+ mdiff[1] = opdata->mcenter[1] - opdata->mouse[1];
+ float scale = (opdata->is_modal) ?
+ ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size) /
+ opdata->ob_scale :
+ RNA_float_get(op->ptr, "scale");
+ scale *= SMOOTH_FACTOR;
+
+ if (opdata->is_modal) {
+ RNA_float_set(op->ptr, "scale", scale);
+ }
+
+ changed = (bool)(scale != 0.0f);
+ if (changed) {
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ gps->uv_scale = (opdata->is_modal) ? opdata->array_scale[i] + scale : scale;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+ i++;
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+ }
+ }
+
+ if ((!opdata->is_modal) || (changed)) {
+ /* Update cursor line. */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, NULL);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ return changed;
+}
+
+static int gpencil_transform_fill_exec(bContext *C, wmOperator *op)
+{
+ if (!gpencil_uv_transform_init(C, op, false)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!gpencil_uv_transform_calc(C, op)) {
+ gpencil_uv_transform_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ gpencil_uv_transform_exit(C, op);
+ return OPERATOR_FINISHED;
+}
+
+static bool gpencil_transform_fill_poll(bContext *C)
+{
+ if (!ED_operator_view3d_active(C)) {
+ return false;
+ }
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (gpd == NULL) {
+ return false;
+ }
+
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
+
+ if ((gpl == NULL) || (ob->mode != OB_MODE_EDIT_GPENCIL)) {
+ return false;
+ }
+
+ return true;
+}
+
+static int gpencil_transform_fill_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float mlen[2];
+ float center_3d[3];
+
+ if (!gpencil_uv_transform_init(C, op, true)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ GpUvData *opdata = op->customdata;
+ /* initialize mouse values */
+ opdata->mouse[0] = event->mval[0];
+ opdata->mouse[1] = event->mval[1];
+
+ copy_v3_v3(center_3d, opdata->ob->loc);
+ mlen[0] = opdata->mcenter[0] - event->mval[0];
+ mlen[1] = opdata->mcenter[1] - event->mval[1];
+ opdata->initial_length = len_v2(mlen);
+
+ opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
+
+ /* Calc init rotation vector. */
+ float mouse[2] = {event->mval[0], event->mval[1]};
+ sub_v2_v2v2(opdata->vinit_rotation, mouse, opdata->mcenter);
+ normalize_v2(opdata->vinit_rotation);
+
+ gpencil_uv_transform_calc(C, op);
+
+ gpencil_uv_transform_update_header(op, C);
+ WM_cursor_set(CTX_wm_window(C), WM_CURSOR_EW_ARROW);
+
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int gpencil_transform_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ GpUvData *opdata = op->customdata;
+
+ switch (event->type) {
+ case EVT_ESCKEY:
+ case RIGHTMOUSE: {
+ gpencil_transform_fill_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ case MOUSEMOVE: {
+ opdata->mouse[0] = event->mval[0];
+ opdata->mouse[1] = event->mval[1];
+
+ if (gpencil_uv_transform_calc(C, op)) {
+ gpencil_uv_transform_update_header(op, C);
+ }
+ else {
+ gpencil_transform_fill_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ }
+ case LEFTMOUSE:
+ case EVT_PADENTER:
+ case EVT_RETKEY: {
+ if ((event->val == KM_PRESS) ||
+ ((event->val == KM_RELEASE) && RNA_boolean_get(op->ptr, "release_confirm"))) {
+ gpencil_uv_transform_calc(C, op);
+ gpencil_uv_transform_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void GPENCIL_OT_transform_fill(wmOperatorType *ot)
+{
+ static const EnumPropertyItem uv_mode[] = {
+ {GP_UV_TRANSLATE, "TRANSLATE", 0, "Translate", ""},
+ {GP_UV_ROTATE, "ROTATE", 0, "Rotate", ""},
+ {GP_UV_SCALE, "SCALE", 0, "Scale", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Transform Stroke Fill";
+ ot->idname = "GPENCIL_OT_transform_fill";
+ ot->description = "Transform Grease Pencil Stroke Fill";
+
+ /* api callbacks */
+ ot->invoke = gpencil_transform_fill_invoke;
+ ot->modal = gpencil_transform_fill_modal;
+ ot->exec = gpencil_transform_fill_exec;
+ ot->cancel = gpencil_transform_fill_cancel;
+ ot->poll = gpencil_transform_fill_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR_XY | OPTYPE_BLOCKING;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "mode", uv_mode, GP_UV_ROTATE, "Mode", "");
+
+ prop = RNA_def_float_vector(
+ ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_float_rotation(ot->srna,
+ "rotation",
+ 0,
+ NULL,
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f),
+ "Rotation",
+ "",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(0.0f));
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_float(ot->srna, "scale", 1.0f, 0.001f, 100.0f, "Scale", "", 0.001f, 100.0f);
+ RNA_def_property_float_default(prop, 0.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
+/* Clear UV transformations. */
+static int gpencil_reset_transform_fill_exec(bContext *C, wmOperator *op)
+{
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bool changed = false;
+
+ /* Loop all selected strokes and reset. */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ if ((mode == GP_UV_TRANSLATE) || (mode == GP_UV_ALL)) {
+ zero_v2(gps->uv_translation);
+ }
+ if ((mode == GP_UV_ROTATE) || (mode == GP_UV_ALL)) {
+ gps->uv_rotation = 0.0f;
+ }
+ if ((mode == GP_UV_SCALE) || (mode == GP_UV_ALL)) {
+ gps->uv_scale = 1.0f;
+ }
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+ changed = true;
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* notifiers */
+ if (changed) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_reset_transform_fill(wmOperatorType *ot)
+{
+ static const EnumPropertyItem uv_clear_mode[] = {
+ {GP_UV_ALL, "ALL", 0, "All", ""},
+ {GP_UV_TRANSLATE, "TRANSLATE", 0, "Translate", ""},
+ {GP_UV_ROTATE, "ROTATE", 0, "Rotate", ""},
+ {GP_UV_SCALE, "SCALE", 0, "Scale", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Reset Fill Transformations";
+ ot->idname = "GPENCIL_OT_reset_transform_fill";
+ ot->description = "Reset any UV transformation and back to default values";
+
+ /* callbacks */
+ ot->exec = gpencil_reset_transform_fill_exec;
+ ot->poll = gpencil_transform_fill_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "mode", uv_clear_mode, GP_UV_ALL, "Mode", "");
+}
diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c
new file mode 100644
index 00000000000..4db88bd552f
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c
@@ -0,0 +1,899 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ * This is a new part of Blender
+ * Brush based operators for editing Grease Pencil strokes
+ */
+
+/** \file
+ * \ingroup edgpencil
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_paint.h"
+#include "BKE_report.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "gpencil_intern.h"
+
+enum {
+ GP_PAINT_VERTEX_STROKE = 0,
+ GP_PAINT_VERTEX_FILL = 1,
+ GP_PAINT_VERTEX_BOTH = 2,
+};
+
+static const EnumPropertyItem gpencil_modesEnumPropertyItem_mode[] = {
+ {GP_PAINT_VERTEX_STROKE, "STROKE", 0, "Stroke", ""},
+ {GP_PAINT_VERTEX_FILL, "FILL", 0, "Fill", ""},
+ {GP_PAINT_VERTEX_BOTH, "BOTH", 0, "Both", ""},
+ {0, NULL, 0, NULL, NULL},
+};
+
+/* Poll callback for stroke vertex paint operator. */
+static bool gp_vertexpaint_mode_poll(bContext *C)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (GPENCIL_VERTEX_MODE(gpd)) {
+ if (!(GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex))) {
+ return false;
+ }
+
+ /* Any data to use. */
+ if (gpd->layers.first) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int gp_vertexpaint_brightness_contrast_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bool changed = false;
+ int i;
+ bGPDspoint *pt;
+ const int mode = RNA_enum_get(op->ptr, "mode");
+
+ float gain, offset;
+ {
+ float brightness = RNA_float_get(op->ptr, "brightness");
+ float contrast = RNA_float_get(op->ptr, "contrast");
+ brightness /= 100.0f;
+ float delta = contrast / 200.0f;
+ /*
+ * The algorithm is by Werner D. Streidt
+ * (http://visca.com/ffactory/archives/5-99/msg00021.html)
+ * Extracted of OpenCV demhist.c
+ */
+ if (contrast > 0) {
+ gain = 1.0f - delta * 2.0f;
+ gain = 1.0f / max_ff(gain, FLT_EPSILON);
+ offset = gain * (brightness - delta);
+ }
+ else {
+ delta *= -1;
+ gain = max_ff(1.0f - delta * 2.0f, 0.0f);
+ offset = gain * brightness + delta;
+ }
+ }
+
+ /* Loop all selected strokes. */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ changed = true;
+ /* Fill color. */
+ if (gps->flag & GP_STROKE_SELECT) {
+ changed = true;
+ if (mode != GP_PAINT_VERTEX_STROKE) {
+ if (gps->vert_color_fill[3] > 0.0f) {
+ for (int i2 = 0; i2 < 3; i2++) {
+ gps->vert_color_fill[i2] = gain * gps->vert_color_fill[i2] + offset;
+ }
+ }
+ }
+ }
+
+ /* Stroke points. */
+ if (mode != GP_PAINT_VERTEX_FILL) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) {
+ for (int i2 = 0; i2 < 3; i2++) {
+ pt->vert_color[i2] = gain * pt->vert_color[i2] + offset;
+ }
+ }
+ }
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* notifiers */
+ if (changed) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Vertex Paint Bright/Contrast";
+ ot->idname = "GPENCIL_OT_vertex_color_brightness_contrast";
+ ot->description = "Adjust vertex color brightness/contrast";
+
+ /* api callbacks */
+ ot->exec = gp_vertexpaint_brightness_contrast_exec;
+ ot->poll = gp_vertexpaint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", "");
+ const float min = -100, max = +100;
+ prop = RNA_def_float(ot->srna, "brightness", 0.0f, min, max, "Brightness", "", min, max);
+ prop = RNA_def_float(ot->srna, "contrast", 0.0f, min, max, "Contrast", "", min, max);
+ RNA_def_property_ui_range(prop, min, max, 1, 1);
+}
+
+static int gp_vertexpaint_hsv_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ bool changed = false;
+ int i;
+ bGPDspoint *pt;
+ float hsv[3];
+
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ float hue = RNA_float_get(op->ptr, "h");
+ float sat = RNA_float_get(op->ptr, "s");
+ float val = RNA_float_get(op->ptr, "v");
+
+ /* Loop all selected strokes. */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ changed = true;
+
+ /* Fill color. */
+ if (mode != GP_PAINT_VERTEX_STROKE) {
+ if (gps->vert_color_fill[3] > 0.0f) {
+
+ rgb_to_hsv_v(gps->vert_color_fill, hsv);
+
+ hsv[0] += (hue - 0.5f);
+ if (hsv[0] > 1.0f) {
+ hsv[0] -= 1.0f;
+ }
+ else if (hsv[0] < 0.0f) {
+ hsv[0] += 1.0f;
+ }
+ hsv[1] *= sat;
+ hsv[2] *= val;
+
+ hsv_to_rgb_v(hsv, gps->vert_color_fill);
+ }
+ }
+
+ /* Stroke points. */
+ if (mode != GP_PAINT_VERTEX_FILL) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) {
+ rgb_to_hsv_v(pt->vert_color, hsv);
+
+ hsv[0] += (hue - 0.5f);
+ if (hsv[0] > 1.0f) {
+ hsv[0] -= 1.0f;
+ }
+ else if (hsv[0] < 0.0f) {
+ hsv[0] += 1.0f;
+ }
+ hsv[1] *= sat;
+ hsv[2] *= val;
+
+ hsv_to_rgb_v(hsv, pt->vert_color);
+ }
+ }
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* notifiers */
+ if (changed) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_vertex_color_hsv(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Paint Hue Saturation Value";
+ ot->idname = "GPENCIL_OT_vertex_color_hsv";
+ ot->description = "Adjust vertex color HSV values";
+
+ /* api callbacks */
+ ot->exec = gp_vertexpaint_hsv_exec;
+ ot->poll = gp_vertexpaint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", "");
+ RNA_def_float(ot->srna, "h", 0.5f, 0.0f, 1.0f, "Hue", "", 0.0f, 1.0f);
+ RNA_def_float(ot->srna, "s", 1.0f, 0.0f, 2.0f, "Saturation", "", 0.0f, 2.0f);
+ RNA_def_float(ot->srna, "v", 1.0f, 0.0f, 2.0f, "Value", "", 0.0f, 2.0f);
+}
+
+static int gp_vertexpaint_invert_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ bool changed = false;
+ int i;
+ bGPDspoint *pt;
+
+ const int mode = RNA_enum_get(op->ptr, "mode");
+
+ /* Loop all selected strokes. */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ changed = true;
+ /* Fill color. */
+ if (gps->flag & GP_STROKE_SELECT) {
+ changed = true;
+ if (mode != GP_PAINT_VERTEX_STROKE) {
+ if (gps->vert_color_fill[3] > 0.0f) {
+ for (int i2 = 0; i2 < 3; i2++) {
+ gps->vert_color_fill[i2] = 1.0f - gps->vert_color_fill[i2];
+ }
+ }
+ }
+ }
+
+ /* Stroke points. */
+ if (mode != GP_PAINT_VERTEX_FILL) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) {
+ for (int i2 = 0; i2 < 3; i2++) {
+ pt->vert_color[i2] = 1.0f - pt->vert_color[i2];
+ }
+ }
+ }
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* notifiers */
+ if (changed) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_vertex_color_invert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Paint Invert";
+ ot->idname = "GPENCIL_OT_vertex_color_invert";
+ ot->description = "Invert RGB values";
+
+ /* api callbacks */
+ ot->exec = gp_vertexpaint_invert_exec;
+ ot->poll = gp_vertexpaint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", "");
+}
+
+static int gp_vertexpaint_levels_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ bool changed = false;
+ bGPDspoint *pt;
+
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ float gain = RNA_float_get(op->ptr, "gain");
+ float offset = RNA_float_get(op->ptr, "offset");
+
+ /* Loop all selected strokes. */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+
+ /* Fill color. */
+ if (gps->flag & GP_STROKE_SELECT) {
+ changed = true;
+ if (mode != GP_PAINT_VERTEX_STROKE) {
+ if (gps->vert_color_fill[3] > 0.0f) {
+ for (int i2 = 0; i2 < 3; i2++) {
+ gps->vert_color_fill[i2] = gain * (gps->vert_color_fill[i2] + offset);
+ }
+ }
+ }
+ }
+
+ /* Stroke points. */
+ if (mode != GP_PAINT_VERTEX_FILL) {
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) {
+ for (int i2 = 0; i2 < 3; i2++) {
+ pt->vert_color[i2] = gain * (pt->vert_color[i2] + offset);
+ }
+ }
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* notifiers */
+ if (changed) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_vertex_color_levels(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name = "Vertex Paint Levels";
+ ot->idname = "GPENCIL_OT_vertex_color_levels";
+ ot->description = "Adjust levels of vertex colors";
+
+ /* api callbacks */
+ ot->exec = gp_vertexpaint_levels_exec;
+ ot->poll = gp_vertexpaint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", "");
+
+ RNA_def_float(
+ ot->srna, "offset", 0.0f, -1.0f, 1.0f, "Offset", "Value to add to colors", -1.0f, 1.0f);
+ RNA_def_float(
+ ot->srna, "gain", 1.0f, 0.0f, FLT_MAX, "Gain", "Value to multiply colors by", 0.0f, 10.0f);
+}
+
+static int gp_vertexpaint_set_exec(bContext *C, wmOperator *op)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ Paint *paint = &ts->gp_vertexpaint->paint;
+ Brush *brush = brush = paint->brush;
+
+ bool changed = false;
+ int i;
+ bGPDspoint *pt;
+
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ float factor = RNA_float_get(op->ptr, "factor");
+
+ /* Loop all selected strokes. */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+
+ /* Fill color. */
+ if (gps->flag & GP_STROKE_SELECT) {
+ changed = true;
+ if (mode != GP_PAINT_VERTEX_STROKE) {
+ copy_v3_v3(gps->vert_color_fill, brush->rgb);
+ gps->vert_color_fill[3] = factor;
+ }
+ }
+
+ /* Stroke points. */
+ if (mode != GP_PAINT_VERTEX_FILL) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ copy_v3_v3(pt->vert_color, brush->rgb);
+ pt->vert_color[3] = factor;
+ }
+ }
+ }
+ }
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
+
+ /* notifiers */
+ if (changed) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_vertex_color_set(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name = "Vertex Paint Set Color";
+ ot->idname = "GPENCIL_OT_vertex_color_set";
+ ot->description = "Set active color to all selected vertex";
+
+ /* api callbacks */
+ ot->exec = gp_vertexpaint_set_exec;
+ ot->poll = gp_vertexpaint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", "");
+ RNA_def_float(ot->srna, "factor", 1.0f, 0.001f, 1.0f, "Factor", "Mix Factor", 0.001f, 1.0f);
+}
+
+/* Helper to extract color from vertex color to create a palette. */
+static bool gp_extract_palette_from_vertex(bContext *C, const bool selected, const int threshold)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ bool done = false;
+ const float range = pow(10.0f, threshold);
+ float col[3];
+
+ GHash *color_table = BLI_ghash_int_new(__func__);
+
+ /* Extract all colors. */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ if (gp_style == NULL) {
+ continue;
+ }
+
+ if ((selected) && ((gps->flag & GP_STROKE_SELECT) == 0)) {
+ continue;
+ }
+
+ bool use_stroke = (gp_style->flag & GP_MATERIAL_STROKE_SHOW);
+ bool use_fill = (gp_style->flag & GP_MATERIAL_FILL_SHOW);
+
+ /* Material is disabled. */
+ if ((!use_fill) && (!use_stroke)) {
+ continue;
+ }
+
+ /* Only solid strokes or stencil. */
+ if ((use_stroke) && ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) &&
+ ((gp_style->flag & GP_MATERIAL_STROKE_PATTERN) == 0))) {
+ continue;
+ }
+
+ /* Only solid fill. */
+ if ((use_fill) && (gp_style->fill_style != GP_MATERIAL_FILL_STYLE_SOLID)) {
+ continue;
+ }
+
+ /* Fill color. */
+ if (gps->vert_color_fill[3] > 0.0f) {
+ col[0] = truncf(gps->vert_color_fill[0] * range) / range;
+ col[1] = truncf(gps->vert_color_fill[1] * range) / range;
+ col[2] = truncf(gps->vert_color_fill[2] * range) / range;
+
+ uint key = rgb_to_cpack(col[0], col[1], col[2]);
+
+ if (!BLI_ghash_haskey(color_table, POINTER_FROM_INT(key))) {
+ BLI_ghash_insert(color_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
+ }
+ }
+
+ /* Read all points to get all colors. */
+ bGPDspoint *pt;
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ col[0] = truncf(pt->vert_color[0] * range) / range;
+ col[1] = truncf(pt->vert_color[1] * range) / range;
+ col[2] = truncf(pt->vert_color[2] * range) / range;
+
+ uint key = rgb_to_cpack(col[0], col[1], col[2]);
+ if (!BLI_ghash_haskey(color_table, POINTER_FROM_INT(key))) {
+ BLI_ghash_insert(color_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* Create the Palette. */
+ done = BKE_palette_from_hash(bmain, color_table, ob->id.name + 2, true);
+
+ /* Free memory. */
+ BLI_ghash_free(color_table, NULL, NULL);
+
+ return done;
+}
+
+/* Convert Materials to Vertex Color. */
+typedef struct GPMatArray {
+ uint key;
+ Material *ma;
+ int index;
+} GPMatArray;
+
+static uint get_material_type(MaterialGPencilStyle *gp_style,
+ bool use_stroke,
+ bool use_fill,
+ char *name)
+{
+ uint r_i = 0;
+ if ((use_stroke) && (use_fill)) {
+ switch (gp_style->mode) {
+ case GP_MATERIAL_MODE_LINE: {
+ r_i = 1;
+ strcpy(name, "Line Stroke-Fill");
+ break;
+ }
+ case GP_MATERIAL_MODE_DOT: {
+ r_i = 2;
+ strcpy(name, "Dots Stroke-Fill");
+ break;
+ }
+ case GP_MATERIAL_MODE_SQUARE: {
+ r_i = 3;
+ strcpy(name, "Squares Stroke-Fill");
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else if (use_stroke) {
+ switch (gp_style->mode) {
+ case GP_MATERIAL_MODE_LINE: {
+ r_i = 4;
+ strcpy(name, "Line Stroke");
+ break;
+ }
+ case GP_MATERIAL_MODE_DOT: {
+ r_i = 5;
+ strcpy(name, "Dots Stroke");
+ break;
+ }
+ case GP_MATERIAL_MODE_SQUARE: {
+ r_i = 6;
+ strcpy(name, "Squares Stroke");
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else {
+ r_i = 7;
+ strcpy(name, "Solid Fill");
+ }
+
+ /* Create key TSSSSFFFF (T: Type S: Stroke Alpha F: Fill Alpha) */
+ r_i *= 1e8;
+ if (use_stroke) {
+ r_i += gp_style->stroke_rgba[3] * 1e7;
+ }
+ if (use_fill) {
+ r_i += gp_style->fill_rgba[3] * 1e3;
+ }
+
+ return r_i;
+}
+
+static bool gp_material_to_vertex_poll(bContext *C)
+{
+ /* only supported with grease pencil objects */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ return true;
+}
+
+static int gp_material_to_vertex_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const bool remove = RNA_boolean_get(op->ptr, "remove");
+ const bool palette = RNA_boolean_get(op->ptr, "palette");
+ const bool selected = RNA_boolean_get(op->ptr, "selected");
+
+ char name[32] = "";
+ Material *ma = NULL;
+ GPMatArray *mat_elm = NULL;
+ int i;
+
+ bool changed = false;
+
+ short *totcol = BKE_object_material_len_p(ob);
+ if (totcol == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* These arrays hold all materials and index in the material slots for all combinations. */
+ int totmat = *totcol;
+ GPMatArray *mat_table = MEM_calloc_arrayN(totmat, sizeof(GPMatArray), __func__);
+
+ /* Update stroke material index. */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+
+ if ((selected) && ((gps->flag & GP_STROKE_SELECT) == 0)) {
+ continue;
+ }
+
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ if (gp_style == NULL) {
+ continue;
+ }
+
+ bool use_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) &&
+ (gp_style->stroke_rgba[3] > 0.0f));
+ bool use_fill = ((gp_style->flag & GP_MATERIAL_FILL_SHOW) &&
+ (gp_style->fill_rgba[3] > 0.0f));
+ bool is_stencil = ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) &&
+ (gp_style->flag & GP_MATERIAL_STROKE_PATTERN));
+ /* Material is disabled. */
+ if ((!use_fill) && (!use_stroke)) {
+ continue;
+ }
+
+ /* Only solid strokes or stencil. */
+ if ((use_stroke) && ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) &&
+ ((gp_style->flag & GP_MATERIAL_STROKE_PATTERN) == 0))) {
+ continue;
+ }
+
+ /* Only solid fill. */
+ if ((use_fill) && (gp_style->fill_style != GP_MATERIAL_FILL_STYLE_SOLID)) {
+ continue;
+ }
+
+ /* Only for no Stencil materials. */
+ if (!is_stencil) {
+ /* Create material type unique key by type and alpha. */
+ uint key = get_material_type(gp_style, use_stroke, use_fill, name);
+
+ /* Check if material exist. */
+ bool found = false;
+ for (i = 0; i < totmat; i++) {
+ mat_elm = &mat_table[i];
+ if (mat_elm->ma == NULL) {
+ break;
+ }
+ if (key == mat_elm->key) {
+ found = true;
+ break;
+ }
+ }
+
+ /* If not found create a new material. */
+ if (!found) {
+ ma = BKE_gpencil_material_add(bmain, name);
+ if (use_stroke) {
+ ma->gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ }
+ else {
+ ma->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ }
+
+ if (use_fill) {
+ ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
+ }
+ else {
+ ma->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
+ }
+
+ ma->gp_style->stroke_rgba[3] = gp_style->stroke_rgba[3];
+ ma->gp_style->fill_rgba[3] = gp_style->fill_rgba[3];
+
+ BKE_object_material_slot_add(bmain, ob);
+ BKE_object_material_assign(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
+
+ mat_elm->key = key;
+ mat_elm->ma = ma;
+ mat_elm->index = ob->totcol - 1;
+ }
+ else {
+ mat_elm = &mat_table[i];
+ }
+
+ /* Update stroke */
+ gps->mat_nr = mat_elm->index;
+ }
+
+ changed = true;
+ copy_v3_v3(gps->vert_color_fill, gp_style->fill_rgba);
+ gps->vert_color_fill[3] = 1.0f;
+
+ /* Update all points. */
+ bGPDspoint *pt;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ copy_v3_v3(pt->vert_color, gp_style->stroke_rgba);
+ pt->vert_color[3] = 1.0f;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ /* notifiers */
+ if (changed) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ /* Free memory. */
+ MEM_SAFE_FREE(mat_table);
+
+ /* Generate a Palette. */
+ if (palette) {
+ gp_extract_palette_from_vertex(C, selected, 1);
+ }
+
+ /* Clean unused materials. */
+ if (remove) {
+ WM_operator_name_call(
+ C, "OBJECT_OT_material_slot_remove_unused", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_material_to_vertex_color(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Convert Stroke Materials to Vertex Color";
+ ot->idname = "GPENCIL_OT_material_to_vertex_color";
+ ot->description = "Replace materials in strokes with Vertex Color";
+
+ /* api callbacks */
+ ot->exec = gp_material_to_vertex_exec;
+ ot->poll = gp_material_to_vertex_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(ot->srna,
+ "remove",
+ true,
+ "Remove Unused Materials",
+ "Remove any unused material after the conversion");
+ RNA_def_boolean(ot->srna, "palette", true, "Create Palette", "Create a new palette with colors");
+ RNA_def_boolean(ot->srna, "selected", false, "Only Selected", "Convert only selected strokes");
+ RNA_def_int(ot->srna, "threshold", 3, 1, 4, "Threshold", "", 1, 4);
+}
+
+/* Extract Palette from Vertex Color. */
+static bool gp_extract_palette_vertex_poll(bContext *C)
+{
+ /* only supported with grease pencil objects */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ return true;
+}
+
+static int gp_extract_palette_vertex_exec(bContext *C, wmOperator *op)
+{
+ const bool selected = RNA_boolean_get(op->ptr, "selected");
+ const int threshold = RNA_int_get(op->ptr, "threshold");
+
+ if (gp_extract_palette_from_vertex(C, selected, threshold)) {
+ BKE_reportf(op->reports, RPT_INFO, "Palette created");
+ }
+ else {
+ BKE_reportf(op->reports, RPT_ERROR, "Unable to find Vertex Information to create palette");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_extract_palette_vertex(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Extract Palette from Vertex Color";
+ ot->idname = "GPENCIL_OT_extract_palette_vertex";
+ ot->description = "Extract all colors used in Grease Pencil Vertex and create a Palette";
+
+ /* api callbacks */
+ ot->exec = gp_extract_palette_vertex_exec;
+ ot->poll = gp_extract_palette_vertex_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna, "selected", false, "Only Selected", "Convert only selected strokes");
+ RNA_def_int(ot->srna, "threshold", 1, 1, 4, "Threshold", "", 1, 4);
+}
diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c
new file mode 100644
index 00000000000..10867bd1e0d
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c
@@ -0,0 +1,1410 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ * This is a new part of Blender
+ * Brush based operators for editing Grease Pencil strokes
+ */
+
+/** \file
+ * \ingroup edgpencil
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_report.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "gpencil_intern.h"
+
+/* ************************************************ */
+/* General Brush Editing Context */
+#define GP_SELECT_BUFFER_CHUNK 256
+#define GP_GRID_PIXEL_SIZE 10.0f
+
+/* Temp Flags while Painting. */
+typedef enum eGPDvertex_brush_Flag {
+ /* invert the effect of the brush */
+ GP_VERTEX_FLAG_INVERT = (1 << 0),
+ /* temporary invert action */
+ GP_VERTEX_FLAG_TMP_INVERT = (1 << 1),
+} eGPDvertex_brush_Flag;
+
+/* Grid of Colors for Smear. */
+typedef struct tGP_Grid {
+ /** Lower right corner of rectangle of grid cell. */
+ float bottom[2];
+ /** Upper left corner of rectangle of grid cell. */
+ float top[2];
+ /** Average Color */
+ float color[4];
+ /** Total points included. */
+ int totcol;
+
+} tGP_Grid;
+
+/* List of points affected by brush. */
+typedef struct tGP_Selected {
+ /** Referenced stroke. */
+ bGPDstroke *gps;
+ /** Point index in points array. */
+ int pt_index;
+ /** Position */
+ int pc[2];
+ /** Color */
+ float color[4];
+} tGP_Selected;
+
+/* Context for brush operators */
+typedef struct tGP_BrushVertexpaintData {
+ Scene *scene;
+ Object *object;
+
+ ARegion *region;
+
+ /* Current GPencil datablock */
+ bGPdata *gpd;
+
+ Brush *brush;
+ float linear_color[3];
+ eGPDvertex_brush_Flag flag;
+ eGP_Vertex_SelectMaskFlag mask;
+
+ /* Space Conversion Data */
+ GP_SpaceConversion gsc;
+
+ /* Is the brush currently painting? */
+ bool is_painting;
+
+ /* Start of new paint */
+ bool first;
+
+ /* Is multiframe editing enabled, and are we using falloff for that? */
+ bool is_multiframe;
+ bool use_multiframe_falloff;
+
+ /* Brush Runtime Data: */
+ /* - position and pressure
+ * - the *_prev variants are the previous values
+ */
+ float mval[2], mval_prev[2];
+ float pressure, pressure_prev;
+
+ /* - Effect 2D vector */
+ float dvec[2];
+
+ /* - multiframe falloff factor */
+ float mf_falloff;
+
+ /* brush geometry (bounding box) */
+ rcti brush_rect;
+
+ /* Temp data to save selected points */
+ /** Stroke buffer. */
+ tGP_Selected *pbuffer;
+ /** Number of elements currently used in cache. */
+ int pbuffer_used;
+ /** Number of total elements available in cache. */
+ int pbuffer_size;
+
+ /** Grid of average colors */
+ tGP_Grid *grid;
+ /** Total number of rows/cols. */
+ int grid_size;
+ /** Total number of cells elments in the grid array. */
+ int grid_len;
+ /** Grid sample position (used to determine distance of falloff) */
+ int grid_sample[2];
+ /** Grid is ready to use */
+ bool grid_ready;
+
+} tGP_BrushVertexpaintData;
+
+/* Ensure the buffer to hold temp selected point size is enough to save all points selected. */
+static tGP_Selected *gpencil_select_buffer_ensure(tGP_Selected *buffer_array,
+ int *buffer_size,
+ int *buffer_used,
+ const bool clear)
+{
+ tGP_Selected *p = NULL;
+
+ /* By default a buffer is created with one block with a predefined number of free slots,
+ * if the size is not enough, the cache is reallocated adding a new block of free slots.
+ * This is done in order to keep cache small and improve speed. */
+ if (*buffer_used + 1 > *buffer_size) {
+ if ((*buffer_size == 0) || (buffer_array == NULL)) {
+ p = MEM_callocN(sizeof(struct tGP_Selected) * GP_SELECT_BUFFER_CHUNK, __func__);
+ *buffer_size = GP_SELECT_BUFFER_CHUNK;
+ }
+ else {
+ *buffer_size += GP_SELECT_BUFFER_CHUNK;
+ p = MEM_recallocN(buffer_array, sizeof(struct tGP_Selected) * *buffer_size);
+ }
+
+ if (p == NULL) {
+ *buffer_size = *buffer_used = 0;
+ }
+
+ buffer_array = p;
+ }
+
+ /* clear old data */
+ if (clear) {
+ *buffer_used = 0;
+ if (buffer_array != NULL) {
+ memset(buffer_array, 0, sizeof(tGP_Selected) * *buffer_size);
+ }
+ }
+
+ return buffer_array;
+}
+
+/* Brush Operations ------------------------------- */
+
+/* Invert behavior of brush? */
+static bool brush_invert_check(tGP_BrushVertexpaintData *gso)
+{
+ /* The basic setting is no inverted */
+ bool invert = false;
+
+ /* During runtime, the user can hold down the Ctrl key to invert the basic behavior */
+ if (gso->flag & GP_VERTEX_FLAG_INVERT) {
+ invert ^= true;
+ }
+
+ return invert;
+}
+
+/* Compute strength of effect. */
+static float brush_influence_calc(tGP_BrushVertexpaintData *gso, const int radius, const int co[2])
+{
+ Brush *brush = gso->brush;
+ float influence = brush->size;
+
+ /* use pressure? */
+ if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
+ influence *= gso->pressure;
+ }
+
+ /* distance fading */
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, gso->mval);
+ float distance = (float)len_v2v2_int(mval_i, co);
+
+ /* Apply Brush curve. */
+ float brush_fallof = BKE_brush_curve_strength(brush, distance, (float)radius);
+ influence *= brush_fallof;
+
+ /* apply multiframe falloff */
+ influence *= gso->mf_falloff;
+
+ /* return influence */
+ return influence;
+}
+
+/* Compute effect vector for directional brushes. */
+static void brush_calc_dvec_2d(tGP_BrushVertexpaintData *gso)
+{
+ gso->dvec[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
+ gso->dvec[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
+
+ normalize_v2(gso->dvec);
+}
+
+/* Init a grid of cells around mouse position.
+ *
+ * For each Cell.
+ *
+ * *--------* Top
+ * | |
+ * | |
+ * Bottom *--------*
+ *
+ * The number of cells is calculated using the brush size and a predefined
+ * number of pixels (see: GP_GRID_PIXEL_SIZE)
+ */
+
+static void gp_grid_cells_init(tGP_BrushVertexpaintData *gso)
+{
+ tGP_Grid *grid;
+ float bottom[2];
+ float top[2];
+ int grid_index = 0;
+
+ /* The grid center is (0,0). */
+ bottom[0] = gso->brush_rect.xmin - gso->mval[0];
+ bottom[1] = gso->brush_rect.ymax - GP_GRID_PIXEL_SIZE - gso->mval[1];
+
+ /* Calc all cell of the grid from top/left. */
+ for (int y = gso->grid_size - 1; y >= 0; y--) {
+ top[1] = bottom[1] + GP_GRID_PIXEL_SIZE;
+
+ for (int x = 0; x < gso->grid_size; x++) {
+ top[0] = bottom[0] + GP_GRID_PIXEL_SIZE;
+
+ grid = &gso->grid[grid_index];
+
+ copy_v2_v2(grid->bottom, bottom);
+ copy_v2_v2(grid->top, top);
+
+ bottom[0] += GP_GRID_PIXEL_SIZE;
+
+ grid_index++;
+ }
+
+ /* Reset for new row. */
+ bottom[0] = gso->brush_rect.xmin - gso->mval[0];
+ bottom[1] -= GP_GRID_PIXEL_SIZE;
+ }
+}
+
+/* Get the index used in the grid base on dvec. */
+static void gp_grid_cell_average_color_idx_get(tGP_BrushVertexpaintData *gso, int r_idx[2])
+{
+ /* Lower direction. */
+ if (gso->dvec[1] < 0.0f) {
+ if ((gso->dvec[0] >= -1.0f) && (gso->dvec[0] < -0.8f)) {
+ r_idx[0] = 0;
+ r_idx[1] = -1;
+ }
+ else if ((gso->dvec[0] >= -0.8f) && (gso->dvec[0] < -0.6f)) {
+ r_idx[0] = -1;
+ r_idx[1] = -1;
+ }
+ else if ((gso->dvec[0] >= -0.6f) && (gso->dvec[0] < 0.6f)) {
+ r_idx[0] = -1;
+ r_idx[1] = 0;
+ }
+ else if ((gso->dvec[0] >= 0.6f) && (gso->dvec[0] < 0.8f)) {
+ r_idx[0] = -1;
+ r_idx[1] = 1;
+ }
+ else if (gso->dvec[0] >= 0.8f) {
+ r_idx[0] = 0;
+ r_idx[1] = 1;
+ }
+ }
+ /* Upper direction. */
+ else {
+ if ((gso->dvec[0] >= -1.0f) && (gso->dvec[0] < -0.8f)) {
+ r_idx[0] = 0;
+ r_idx[1] = -1;
+ }
+ else if ((gso->dvec[0] >= -0.8f) && (gso->dvec[0] < -0.6f)) {
+ r_idx[0] = 1;
+ r_idx[1] = -1;
+ }
+ else if ((gso->dvec[0] >= -0.6f) && (gso->dvec[0] < 0.6f)) {
+ r_idx[0] = 1;
+ r_idx[1] = 0;
+ }
+ else if ((gso->dvec[0] >= 0.6f) && (gso->dvec[0] < 0.8f)) {
+ r_idx[0] = 1;
+ r_idx[1] = 1;
+ }
+ else if (gso->dvec[0] >= 0.8f) {
+ r_idx[0] = 0;
+ r_idx[1] = 1;
+ }
+ }
+}
+
+static int gp_grid_cell_index_get(tGP_BrushVertexpaintData *gso, int pc[2])
+{
+ float bottom[2], top[2];
+
+ for (int i = 0; i < gso->grid_len; i++) {
+ tGP_Grid *grid = &gso->grid[i];
+ add_v2_v2v2(bottom, grid->bottom, gso->mval);
+ add_v2_v2v2(top, grid->top, gso->mval);
+
+ if (pc[0] >= bottom[0] && pc[0] <= top[0] && pc[1] >= bottom[1] && pc[1] <= top[1]) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* Fill the grid with the color in each cell and assign point cell index. */
+static void gp_grid_colors_calc(tGP_BrushVertexpaintData *gso)
+{
+ tGP_Selected *selected = NULL;
+ bGPDstroke *gps_selected = NULL;
+ bGPDspoint *pt = NULL;
+ tGP_Grid *grid = NULL;
+
+ /* Don't calculate again. */
+ if (gso->grid_ready) {
+ return;
+ }
+
+ /* Extract colors by cell. */
+ for (int i = 0; i < gso->pbuffer_used; i++) {
+ selected = &gso->pbuffer[i];
+ gps_selected = selected->gps;
+ pt = &gps_selected->points[selected->pt_index];
+ int grid_index = gp_grid_cell_index_get(gso, selected->pc);
+
+ if (grid_index > -1) {
+ grid = &gso->grid[grid_index];
+ /* Add stroke mix color (only if used). */
+ if (pt->vert_color[3] > 0.0f) {
+ add_v3_v3(grid->color, selected->color);
+ grid->color[3] = 1.0f;
+ grid->totcol++;
+ }
+ }
+ }
+
+ /* Average colors. */
+ for (int i = 0; i < gso->grid_len; i++) {
+ grid = &gso->grid[i];
+ if (grid->totcol > 0) {
+ mul_v3_fl(grid->color, (1.0f / (float)grid->totcol));
+ }
+ }
+
+ /* Save sample position. */
+ round_v2i_v2fl(gso->grid_sample, gso->mval);
+
+ gso->grid_ready = true;
+
+ return;
+}
+
+/* ************************************************ */
+/* Brush Callbacks
+ * This section defines the callbacks used by each brush to perform their magic.
+ * These are called on each point within the brush's radius. */
+
+/* Tint Brush */
+static bool brush_tint_apply(tGP_BrushVertexpaintData *gso,
+ bGPDstroke *gps,
+ int pt_index,
+ const int radius,
+ const int co[2])
+{
+ Brush *brush = gso->brush;
+
+ /* Attenuate factor to get a smoother tinting. */
+ float inf = (brush_influence_calc(gso, radius, co) * brush->gpencil_settings->draw_strength) /
+ 100.0f;
+ float inf_fill = (gso->pressure * brush->gpencil_settings->draw_strength) / 1000.0f;
+
+ CLAMP(inf, 0.0f, 1.0f);
+ CLAMP(inf_fill, 0.0f, 1.0f);
+
+ bGPDspoint *pt = &gps->points[pt_index];
+
+ /* Apply color to Stroke point. */
+ if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
+ if (brush_invert_check(gso)) {
+ pt->vert_color[3] -= inf;
+ CLAMP_MIN(pt->vert_color[3], 0.0f);
+ }
+ else {
+ /* Premult. */
+ mul_v3_fl(pt->vert_color, pt->vert_color[3]);
+ /* "Alpha over" blending. */
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, gso->linear_color, inf);
+ pt->vert_color[3] = pt->vert_color[3] * (1.0 - inf) + inf;
+ /* Un-premult. */
+ if (pt->vert_color[3] > 0.0f) {
+ mul_v3_fl(pt->vert_color, 1.0f / pt->vert_color[3]);
+ }
+ }
+ }
+
+ /* Apply color to Fill area (all with same color and factor). */
+ if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
+ if (brush_invert_check(gso)) {
+ gps->vert_color_fill[3] -= inf_fill;
+ CLAMP_MIN(gps->vert_color_fill[3], 0.0f);
+ }
+ else {
+ /* Premult. */
+ mul_v3_fl(gps->vert_color_fill, gps->vert_color_fill[3]);
+ /* "Alpha over" blending. */
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, gso->linear_color, inf_fill);
+ gps->vert_color_fill[3] = gps->vert_color_fill[3] * (1.0 - inf_fill) + inf_fill;
+ /* Un-premult. */
+ if (gps->vert_color_fill[3] > 0.0f) {
+ mul_v3_fl(gps->vert_color_fill, 1.0f / gps->vert_color_fill[3]);
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Replace Brush (Don't use pressure or invert). */
+static bool brush_replace_apply(tGP_BrushVertexpaintData *gso, bGPDstroke *gps, int pt_index)
+{
+ Brush *brush = gso->brush;
+ bGPDspoint *pt = &gps->points[pt_index];
+
+ /* Apply color to Stroke point. */
+ if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
+ if (pt->vert_color[3] > 0.0f) {
+ copy_v3_v3(pt->vert_color, gso->linear_color);
+ }
+ }
+
+ /* Apply color to Fill area (all with same color and factor). */
+ if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
+ if (gps->vert_color_fill[3] > 0.0f) {
+ copy_v3_v3(gps->vert_color_fill, gso->linear_color);
+ }
+ }
+
+ return true;
+}
+
+/* Get surrounding color. */
+static bool get_surrounding_color(tGP_BrushVertexpaintData *gso,
+ bGPDstroke *gps,
+ int pt_index,
+ float r_color[3])
+{
+ tGP_Selected *selected = NULL;
+ bGPDstroke *gps_selected = NULL;
+ bGPDspoint *pt = NULL;
+
+ int totcol = 0;
+ zero_v3(r_color);
+
+ /* Average the surrounding points except current one. */
+ for (int i = 0; i < gso->pbuffer_used; i++) {
+ selected = &gso->pbuffer[i];
+ gps_selected = selected->gps;
+ /* current point is not evaluated. */
+ if ((gps_selected == gps) && (selected->pt_index == pt_index)) {
+ continue;
+ }
+
+ pt = &gps_selected->points[selected->pt_index];
+
+ /* Add stroke mix color (only if used). */
+ if (pt->vert_color[3] > 0.0f) {
+ add_v3_v3(r_color, selected->color);
+ totcol++;
+ }
+ }
+ if (totcol > 0) {
+ mul_v3_fl(r_color, (1.0f / (float)totcol));
+ return true;
+ }
+
+ return false;
+}
+
+/* Blur Brush */
+static bool brush_blur_apply(tGP_BrushVertexpaintData *gso,
+ bGPDstroke *gps,
+ int pt_index,
+ const int radius,
+ const int co[2])
+{
+ Brush *brush = gso->brush;
+
+ /* Attenuate factor to get a smoother tinting. */
+ float inf = (brush_influence_calc(gso, radius, co) * brush->gpencil_settings->draw_strength) /
+ 100.0f;
+ float inf_fill = (gso->pressure * brush->gpencil_settings->draw_strength) / 1000.0f;
+
+ bGPDspoint *pt = &gps->points[pt_index];
+
+ /* Get surrounding color. */
+ float blur_color[3];
+ if (get_surrounding_color(gso, gps, pt_index, blur_color)) {
+ /* Apply color to Stroke point. */
+ if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, blur_color, inf);
+ }
+
+ /* Apply color to Fill area (all with same color and factor). */
+ if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, blur_color, inf_fill);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+/* Average Brush */
+static bool brush_average_apply(tGP_BrushVertexpaintData *gso,
+ bGPDstroke *gps,
+ int pt_index,
+ const int radius,
+ const int co[2],
+ float average_color[3])
+{
+ Brush *brush = gso->brush;
+
+ /* Attenuate factor to get a smoother tinting. */
+ float inf = (brush_influence_calc(gso, radius, co) * brush->gpencil_settings->draw_strength) /
+ 100.0f;
+ float inf_fill = (gso->pressure * brush->gpencil_settings->draw_strength) / 1000.0f;
+
+ bGPDspoint *pt = &gps->points[pt_index];
+
+ float alpha = pt->vert_color[3];
+ float alpha_fill = gps->vert_color_fill[3];
+
+ if (brush_invert_check(gso)) {
+ alpha -= inf;
+ alpha_fill -= inf_fill;
+ }
+ else {
+ alpha += inf;
+ alpha_fill += inf_fill;
+ }
+
+ /* Apply color to Stroke point. */
+ if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
+ CLAMP(alpha, 0.0f, 1.0f);
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, average_color, inf);
+ pt->vert_color[3] = alpha;
+ }
+
+ /* Apply color to Fill area (all with same color and factor). */
+ if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
+ CLAMP(alpha_fill, 0.0f, 1.0f);
+ copy_v3_v3(gps->vert_color_fill, average_color);
+ gps->vert_color_fill[3] = alpha_fill;
+ }
+
+ return true;
+}
+
+/* Smear Brush */
+static bool brush_smear_apply(tGP_BrushVertexpaintData *gso,
+ bGPDstroke *gps,
+ int pt_index,
+ tGP_Selected *selected)
+{
+ Brush *brush = gso->brush;
+ tGP_Grid *grid = NULL;
+ int average_idx[2];
+ ARRAY_SET_ITEMS(average_idx, 0, 0);
+
+ bool changed = false;
+
+ /* Need some movement, so first input is not done. */
+ if (gso->first) {
+ return false;
+ }
+
+ bGPDspoint *pt = &gps->points[pt_index];
+
+ /* Need get average colors in the grid. */
+ if ((!gso->grid_ready) && (gso->pbuffer_used > 0)) {
+ gp_grid_colors_calc(gso);
+ }
+
+ /* The influence is equal to strength and no decay around brush radius. */
+ float inf = brush->gpencil_settings->draw_strength;
+ if (brush->flag & GP_BRUSH_USE_PRESSURE) {
+ inf *= gso->pressure;
+ }
+
+ /* Calc distance from initial sample location and add a fallof effect. */
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, gso->mval);
+ float distance = (float)len_v2v2_int(mval_i, gso->grid_sample);
+ float fac = 1.0f - (distance / (float)(brush->size * 2));
+ CLAMP(fac, 0.0f, 1.0f);
+ inf *= fac;
+
+ /* Retry row and col for average color. */
+ gp_grid_cell_average_color_idx_get(gso, average_idx);
+
+ /* Retry average color cell. */
+ int grid_index = gp_grid_cell_index_get(gso, selected->pc);
+ if (grid_index > -1) {
+ int row = grid_index / gso->grid_size;
+ int col = grid_index - (gso->grid_size * row);
+ row += average_idx[0];
+ col += average_idx[1];
+ CLAMP(row, 0, gso->grid_size);
+ CLAMP(col, 0, gso->grid_size);
+
+ int new_index = (row * gso->grid_size) + col;
+ CLAMP(new_index, 0, gso->grid_len - 1);
+ grid = &gso->grid[new_index];
+ }
+
+ /* Apply color to Stroke point. */
+ if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
+ if (grid_index > -1) {
+ if (grid->color[3] > 0.0f) {
+ // copy_v3_v3(pt->vert_color, grid->color);
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, grid->color, inf);
+ changed = true;
+ }
+ }
+ }
+
+ /* Apply color to Fill area (all with same color and factor). */
+ if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
+ if (grid_index > -1) {
+ if (grid->color[3] > 0.0f) {
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, grid->color, inf);
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
+}
+
+/* ************************************************ */
+/* Header Info */
+static void gp_vertexpaint_brush_header_set(bContext *C)
+{
+ ED_workspace_status_text(C,
+ TIP_("GPencil Vertex Paint: LMB to paint | RMB/Escape to Exit"
+ " | Ctrl to Invert Action"));
+}
+
+/* ************************************************ */
+/* Grease Pencil Vertex Paint Operator */
+
+/* Init/Exit ----------------------------------------------- */
+
+static bool gp_vertexpaint_brush_init(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+ Paint *paint = ob->mode == OB_MODE_VERTEX_GPENCIL ? &ts->gp_vertexpaint->paint :
+ &ts->gp_paint->paint;
+
+ /* set the brush using the tool */
+ tGP_BrushVertexpaintData *gso;
+
+ /* setup operator data */
+ gso = MEM_callocN(sizeof(tGP_BrushVertexpaintData), "tGP_BrushVertexpaintData");
+ op->customdata = gso;
+
+ gso->brush = paint->brush;
+ srgb_to_linearrgb_v3_v3(gso->linear_color, gso->brush->rgb);
+ BKE_curvemapping_initialize(gso->brush->curve);
+
+ gso->is_painting = false;
+ gso->first = true;
+
+ gso->pbuffer = NULL;
+ gso->pbuffer_size = 0;
+ gso->pbuffer_used = 0;
+
+ /* Alloc grid array */
+ gso->grid_size = (int)(((gso->brush->size * 2.0f) / GP_GRID_PIXEL_SIZE) + 1.0);
+ /* Square value. */
+ gso->grid_len = gso->grid_size * gso->grid_size;
+ gso->grid = MEM_callocN(sizeof(tGP_Grid) * gso->grid_len, "tGP_Grid");
+ gso->grid_ready = false;
+
+ gso->gpd = ED_gpencil_data_get_active(C);
+ gso->scene = scene;
+ gso->object = ob;
+
+ gso->region = CTX_wm_region(C);
+
+ /* Save mask. */
+ gso->mask = ts->gpencil_selectmode_vertex;
+
+ /* Multiframe settings. */
+ gso->is_multiframe = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
+ gso->use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
+
+ /* Init multi-edit falloff curve data before doing anything,
+ * so we won't have to do it again later. */
+ if (gso->is_multiframe) {
+ BKE_curvemapping_initialize(ts->gp_sculpt.cur_falloff);
+ }
+
+ /* Setup space conversions. */
+ gp_point_conversion_init(C, &gso->gsc);
+
+ /* Update header. */
+ gp_vertexpaint_brush_header_set(C);
+
+ return true;
+}
+
+static void gp_vertexpaint_brush_exit(bContext *C, wmOperator *op)
+{
+ tGP_BrushVertexpaintData *gso = op->customdata;
+
+ /* Disable headerprints. */
+ ED_workspace_status_text(C, NULL);
+
+ /* Disable temp invert flag. */
+ gso->brush->flag &= ~GP_VERTEX_FLAG_TMP_INVERT;
+
+ /* Free operator data */
+ MEM_SAFE_FREE(gso->pbuffer);
+ MEM_SAFE_FREE(gso->grid);
+ MEM_SAFE_FREE(gso);
+ op->customdata = NULL;
+}
+
+/* Poll callback for stroke vertex paint operator. */
+static bool gp_vertexpaint_brush_poll(bContext *C)
+{
+ /* NOTE: this is a bit slower, but is the most accurate... */
+ return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
+}
+
+/* Helper to save the points selected by the brush. */
+static void gp_save_selected_point(tGP_BrushVertexpaintData *gso,
+ bGPDstroke *gps,
+ int index,
+ int pc[2])
+{
+ tGP_Selected *selected;
+ bGPDspoint *pt = &gps->points[index];
+
+ /* Ensure the array to save the list of selected points is big enough. */
+ gso->pbuffer = gpencil_select_buffer_ensure(
+ gso->pbuffer, &gso->pbuffer_size, &gso->pbuffer_used, false);
+
+ selected = &gso->pbuffer[gso->pbuffer_used];
+ selected->gps = gps;
+ selected->pt_index = index;
+ copy_v2_v2_int(selected->pc, pc);
+ copy_v4_v4(selected->color, pt->vert_color);
+
+ gso->pbuffer_used++;
+}
+
+/* Select points in this stroke and add to an array to be used later. */
+static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
+ bGPDstroke *gps,
+ const float diff_mat[4][4])
+{
+ GP_SpaceConversion *gsc = &gso->gsc;
+ rcti *rect = &gso->brush_rect;
+ Brush *brush = gso->brush;
+ const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
+ gso->brush->size;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ bGPDspoint *pt_active = NULL;
+
+ bGPDspoint *pt1, *pt2;
+ bGPDspoint *pt = NULL;
+ int pc1[2] = {0};
+ int pc2[2] = {0};
+ int i;
+ int index;
+ bool include_last = false;
+
+ /* Check if the stroke collide with brush. */
+ if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) {
+ return;
+ }
+
+ if (gps->totpoints == 1) {
+ bGPDspoint pt_temp;
+ pt = &gps->points[0];
+ gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
+ gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
+
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ /* do boundbox check first */
+ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
+ /* only check if point is inside */
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, gso->mval);
+ if (len_v2v2_int(mval_i, pc1) <= radius) {
+ /* apply operation to this point */
+ if (pt_active != NULL) {
+ gp_save_selected_point(gso, gps_active, 0, pc1);
+ }
+ }
+ }
+ }
+ else {
+ /* Loop over the points in the stroke, checking for intersections
+ * - an intersection means that we touched the stroke
+ */
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+ /* Get points to work with */
+ pt1 = gps->points + i;
+ pt2 = gps->points + i + 1;
+
+ /* Skip if neither one is selected
+ * (and we are only allowed to edit/consider selected points) */
+ if ((GPENCIL_ANY_VERTEX_MASK(gso->mask)) && (GPENCIL_VERTEX_MODE(gso->gpd))) {
+ if (!(pt1->flag & GP_SPOINT_SELECT) && !(pt2->flag & GP_SPOINT_SELECT)) {
+ include_last = false;
+ continue;
+ }
+ }
+
+ bGPDspoint npt;
+ gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
+
+ gp_point_to_parent_space(pt2, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]);
+
+ /* Check that point segment of the boundbox of the selection stroke */
+ if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) ||
+ ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) {
+ /* Check if point segment of stroke had anything to do with
+ * brush region (either within stroke painted, or on its lines)
+ * - this assumes that linewidth is irrelevant
+ */
+ if (gp_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
+
+ /* To each point individually... */
+ pt = &gps->points[i];
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
+ if (pt_active != NULL) {
+ gp_save_selected_point(gso, gps_active, index, pc1);
+ }
+
+ /* Only do the second point if this is the last segment,
+ * and it is unlikely that the point will get handled
+ * otherwise.
+ *
+ * NOTE: There is a small risk here that the second point wasn't really
+ * actually in-range. In that case, it only got in because
+ * the line linking the points was!
+ */
+ if (i + 1 == gps->totpoints - 1) {
+ pt = &gps->points[i + 1];
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1;
+ if (pt_active != NULL) {
+ gp_save_selected_point(gso, gps_active, index, pc2);
+ include_last = false;
+ }
+ }
+ else {
+ include_last = true;
+ }
+ }
+ else if (include_last) {
+ /* This case is for cases where for whatever reason the second vert (1st here)
+ * doesn't get included because the whole edge isn't in bounds,
+ * but it would've qualified since it did with the previous step
+ * (but wasn't added then, to avoid double-ups).
+ */
+ pt = &gps->points[i];
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
+ if (pt_active != NULL) {
+ gp_save_selected_point(gso, gps_active, index, pc1);
+
+ include_last = false;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* Apply vertex paint brushes to strokes in the given frame. */
+static bool gp_vertexpaint_brush_do_frame(bContext *C,
+ tGP_BrushVertexpaintData *gso,
+ bGPDlayer *gpl,
+ bGPDframe *gpf,
+ const float diff_mat[4][4])
+{
+ Object *ob = CTX_data_active_object(C);
+ char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool :
+ gso->brush->gpencil_tool;
+ const int radius = (gso->brush->flag & GP_BRUSH_USE_PRESSURE) ?
+ gso->brush->size * gso->pressure :
+ gso->brush->size;
+ tGP_Selected *selected = NULL;
+ int i;
+
+ /*---------------------------------------------------------------------
+ * First step: select the points affected. This step is required to have
+ * all selected points before apply the effect, because it could be
+ * required to average data.
+ *--------------------------------------------------------------------- */
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ /* Skip strokes that are invalid for current view. */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ /* Check if the color is editable. */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+
+ /* Check points below the brush. */
+ gp_vertexpaint_select_stroke(gso, gps, diff_mat);
+ }
+
+ /* For Average tool, need calculate the average resulting color from all colors
+ * under the brush. */
+ float average_color[3] = {0};
+ int totcol = 0;
+ if ((tool == GPVERTEX_TOOL_AVERAGE) && (gso->pbuffer_used > 0)) {
+ for (i = 0; i < gso->pbuffer_used; i++) {
+ selected = &gso->pbuffer[i];
+ bGPDstroke *gps = selected->gps;
+ bGPDspoint *pt = &gps->points[selected->pt_index];
+
+ /* Add stroke mix color (only if used). */
+ if (pt->vert_color[3] > 0.0f) {
+ add_v3_v3(average_color, pt->vert_color);
+ totcol++;
+ }
+
+ /* If Fill color mix, add to average. */
+ if (gps->vert_color_fill[3] > 0.0f) {
+ add_v3_v3(average_color, gps->vert_color_fill);
+ totcol++;
+ }
+ }
+
+ /* Get average. */
+ if (totcol > 0) {
+ mul_v3_fl(average_color, (1.0f / (float)totcol));
+ }
+ }
+
+ /*---------------------------------------------------------------------
+ * Second step: Apply effect.
+ *--------------------------------------------------------------------- */
+ bool changed = false;
+ for (i = 0; i < gso->pbuffer_used; i++) {
+ changed = true;
+ selected = &gso->pbuffer[i];
+
+ switch (tool) {
+ case GPAINT_TOOL_TINT:
+ case GPVERTEX_TOOL_DRAW: {
+ brush_tint_apply(gso, selected->gps, selected->pt_index, radius, selected->pc);
+ changed |= true;
+ break;
+ }
+ case GPVERTEX_TOOL_BLUR: {
+ brush_blur_apply(gso, selected->gps, selected->pt_index, radius, selected->pc);
+ changed |= true;
+ break;
+ }
+ case GPVERTEX_TOOL_AVERAGE: {
+ brush_average_apply(
+ gso, selected->gps, selected->pt_index, radius, selected->pc, average_color);
+ changed |= true;
+ break;
+ }
+ case GPVERTEX_TOOL_SMEAR: {
+ brush_smear_apply(gso, selected->gps, selected->pt_index, selected);
+ changed |= true;
+ break;
+ }
+ case GPVERTEX_TOOL_REPLACE: {
+ brush_replace_apply(gso, selected->gps, selected->pt_index);
+ changed |= true;
+ break;
+ }
+
+ default:
+ printf("ERROR: Unknown type of GPencil Vertex Paint brush\n");
+ break;
+ }
+ }
+ /* Clear the selected array, but keep the memory allocation.*/
+ gso->pbuffer = gpencil_select_buffer_ensure(
+ gso->pbuffer, &gso->pbuffer_size, &gso->pbuffer_used, true);
+
+ return changed;
+}
+
+/* Apply brush effect to all layers. */
+static bool gp_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpaintData *gso)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Object *obact = gso->object;
+ bool changed = false;
+
+ Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obact->id);
+ bGPdata *gpd = (bGPdata *)ob_eval->data;
+
+ /* Find visible strokes, and perform operations on those if hit */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ /* If locked or no active frame, don't do anything. */
+ if ((!BKE_gpencil_layer_is_editable(gpl)) || (gpl->actframe == NULL)) {
+ continue;
+ }
+
+ /* calculate difference matrix */
+ float diff_mat[4][4];
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
+
+ /* Active Frame or MultiFrame? */
+ if (gso->is_multiframe) {
+ /* init multiframe falloff options */
+ int f_init = 0;
+ int f_end = 0;
+
+ if (gso->use_multiframe_falloff) {
+ BKE_gpencil_frame_range_selected(gpl, &f_init, &f_end);
+ }
+
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ /* Always do active frame; Otherwise, only include selected frames */
+ if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
+ /* Compute multi-frame falloff factor. */
+ if (gso->use_multiframe_falloff) {
+ /* Falloff depends on distance to active frame (relative to the overall frame range) */
+ gso->mf_falloff = BKE_gpencil_multiframe_falloff_calc(
+ gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
+ }
+ else {
+ /* No falloff */
+ gso->mf_falloff = 1.0f;
+ }
+
+ /* affect strokes in this frame */
+ changed |= gp_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat);
+ }
+ }
+ }
+ else {
+ /* Apply to active frame's strokes */
+ if (gpl->actframe != NULL) {
+ gso->mf_falloff = 1.0f;
+ changed |= gp_vertexpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat);
+ }
+ }
+ }
+
+ return changed;
+}
+
+/* Calculate settings for applying brush */
+static void gp_vertexpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
+{
+ tGP_BrushVertexpaintData *gso = op->customdata;
+ Brush *brush = gso->brush;
+ const int radius = ((brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
+ gso->brush->size);
+ float mousef[2];
+ int mouse[2];
+ bool changed = false;
+
+ /* Get latest mouse coordinates */
+ RNA_float_get_array(itemptr, "mouse", mousef);
+ gso->mval[0] = mouse[0] = (int)(mousef[0]);
+ gso->mval[1] = mouse[1] = (int)(mousef[1]);
+
+ gso->pressure = RNA_float_get(itemptr, "pressure");
+
+ if (RNA_boolean_get(itemptr, "pen_flip")) {
+ gso->flag |= GP_VERTEX_FLAG_INVERT;
+ }
+ else {
+ gso->flag &= ~GP_VERTEX_FLAG_INVERT;
+ }
+
+ /* Store coordinates as reference, if operator just started running */
+ if (gso->first) {
+ gso->mval_prev[0] = gso->mval[0];
+ gso->mval_prev[1] = gso->mval[1];
+ gso->pressure_prev = gso->pressure;
+ }
+
+ /* Update brush_rect, so that it represents the bounding rectangle of brush. */
+ gso->brush_rect.xmin = mouse[0] - radius;
+ gso->brush_rect.ymin = mouse[1] - radius;
+ gso->brush_rect.xmax = mouse[0] + radius;
+ gso->brush_rect.ymax = mouse[1] + radius;
+
+ /* Calc 2D direction vector and relative angle. */
+ brush_calc_dvec_2d(gso);
+
+ /* Calc grid for smear tool. */
+ gp_grid_cells_init(gso);
+
+ changed = gp_vertexpaint_brush_apply_to_layers(C, gso);
+
+ /* Updates */
+ if (changed) {
+ DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ /* Store values for next step */
+ gso->mval_prev[0] = gso->mval[0];
+ gso->mval_prev[1] = gso->mval[1];
+ gso->pressure_prev = gso->pressure;
+ gso->first = false;
+}
+
+/* Running --------------------------------------------- */
+
+/* helper - a record stroke, and apply paint event */
+static void gp_vertexpaint_brush_apply_event(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGP_BrushVertexpaintData *gso = op->customdata;
+ PointerRNA itemptr;
+ float mouse[2];
+
+ mouse[0] = event->mval[0] + 1;
+ mouse[1] = event->mval[1] + 1;
+
+ /* fill in stroke */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ RNA_float_set_array(&itemptr, "mouse", mouse);
+ RNA_boolean_set(&itemptr, "pen_flip", event->ctrl != false);
+ RNA_boolean_set(&itemptr, "is_start", gso->first);
+
+ /* Handle pressure sensitivity (which is supplied by tablets). */
+ float pressure = event->tablet.pressure;
+ CLAMP(pressure, 0.0f, 1.0f);
+ RNA_float_set(&itemptr, "pressure", pressure);
+
+ /* apply */
+ gp_vertexpaint_brush_apply(C, op, &itemptr);
+}
+
+/* reapply */
+static int gp_vertexpaint_brush_exec(bContext *C, wmOperator *op)
+{
+ if (!gp_vertexpaint_brush_init(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_BEGIN (op->ptr, itemptr, "stroke") {
+ gp_vertexpaint_brush_apply(C, op, &itemptr);
+ }
+ RNA_END;
+
+ gp_vertexpaint_brush_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+/* start modal painting */
+static int gp_vertexpaint_brush_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGP_BrushVertexpaintData *gso = NULL;
+ const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
+ const bool is_playing = ED_screen_animation_playing(CTX_wm_manager(C)) != NULL;
+
+ /* the operator cannot work while play animation */
+ if (is_playing) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot Paint while play animation");
+
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init painting data */
+ if (!gp_vertexpaint_brush_init(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ gso = op->customdata;
+
+ /* register modal handler */
+ WM_event_add_modal_handler(C, op);
+
+ /* start drawing immediately? */
+ if (is_modal == false) {
+ ARegion *region = CTX_wm_region(C);
+
+ /* apply first dab... */
+ gso->is_painting = true;
+ gp_vertexpaint_brush_apply_event(C, op, event);
+
+ /* redraw view with feedback */
+ ED_region_tag_redraw(region);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* painting - handle events */
+static int gp_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGP_BrushVertexpaintData *gso = op->customdata;
+ const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
+ bool redraw_region = false;
+ bool redraw_toolsettings = false;
+
+ /* The operator can be in 2 states: Painting and Idling */
+ if (gso->is_painting) {
+ /* Painting */
+ switch (event->type) {
+ /* Mouse Move = Apply somewhere else */
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE:
+ /* apply brush effect at new position */
+ gp_vertexpaint_brush_apply_event(C, op, event);
+
+ /* force redraw, so that the cursor will at least be valid */
+ redraw_region = true;
+ break;
+
+ /* Painting mbut release = Stop painting (back to idle) */
+ case LEFTMOUSE:
+ if (is_modal) {
+ /* go back to idling... */
+ gso->is_painting = false;
+ }
+ else {
+ /* end painting, since we're not modal */
+ gso->is_painting = false;
+
+ gp_vertexpaint_brush_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+
+ /* Abort painting if any of the usual things are tried */
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ case EVT_ESCKEY:
+ gp_vertexpaint_brush_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ else {
+ /* Idling */
+ BLI_assert(is_modal == true);
+
+ switch (event->type) {
+ /* Painting mbut press = Start painting (switch to painting state) */
+ case LEFTMOUSE:
+ /* do initial "click" apply */
+ gso->is_painting = true;
+ gso->first = true;
+
+ gp_vertexpaint_brush_apply_event(C, op, event);
+ break;
+
+ /* Exit modal operator, based on the "standard" ops */
+ case RIGHTMOUSE:
+ case EVT_ESCKEY:
+ gp_vertexpaint_brush_exit(C, op);
+ return OPERATOR_FINISHED;
+
+ /* MMB is often used for view manipulations */
+ case MIDDLEMOUSE:
+ return OPERATOR_PASS_THROUGH;
+
+ /* Mouse movements should update the brush cursor - Just redraw the active region */
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE:
+ redraw_region = true;
+ break;
+
+ /* Change Frame - Allowed */
+ case EVT_LEFTARROWKEY:
+ case EVT_RIGHTARROWKEY:
+ case EVT_UPARROWKEY:
+ case EVT_DOWNARROWKEY:
+ return OPERATOR_PASS_THROUGH;
+
+ /* Camera/View Gizmo's - Allowed */
+ /* (See rationale in gpencil_paint.c -> gpencil_draw_modal()) */
+ case EVT_PAD0:
+ case EVT_PAD1:
+ case EVT_PAD2:
+ case EVT_PAD3:
+ case EVT_PAD4:
+ case EVT_PAD5:
+ case EVT_PAD6:
+ case EVT_PAD7:
+ case EVT_PAD8:
+ case EVT_PAD9:
+ return OPERATOR_PASS_THROUGH;
+
+ /* Unhandled event */
+ default:
+ break;
+ }
+ }
+
+ /* Redraw region? */
+ if (redraw_region) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
+
+ /* Redraw toolsettings (brush settings)? */
+ if (redraw_toolsettings) {
+ DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void GPENCIL_OT_vertex_paint(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Stroke Vertex Paint";
+ ot->idname = "GPENCIL_OT_vertex_paint";
+ ot->description = "Paint stroke points with a color";
+
+ /* api callbacks */
+ ot->exec = gp_vertexpaint_brush_exec;
+ ot->invoke = gp_vertexpaint_brush_invoke;
+ ot->modal = gp_vertexpaint_brush_modal;
+ ot->cancel = gp_vertexpaint_brush_exit;
+ ot->poll = gp_vertexpaint_brush_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c
new file mode 100644
index 00000000000..2ebf1aba353
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_weight_paint.c
@@ -0,0 +1,900 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ * This is a new part of Blender
+ * Brush based operators for editing Grease Pencil strokes
+ */
+
+/** \file
+ * \ingroup edgpencil
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_object_deform.h"
+#include "BKE_report.h"
+#include "DNA_meshdata_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "gpencil_intern.h"
+
+/* ************************************************ */
+/* General Brush Editing Context */
+#define GP_SELECT_BUFFER_CHUNK 256
+
+/* Grid of Colors for Smear. */
+typedef struct tGP_Grid {
+ /** Lower right corner of rectangle of grid cell. */
+ float bottom[2];
+ /** Upper left corner of rectangle of grid cell. */
+ float top[2];
+ /** Average Color */
+ float color[4];
+ /** Total points included. */
+ int totcol;
+
+} tGP_Grid;
+
+/* List of points affected by brush. */
+typedef struct tGP_Selected {
+ /** Referenced stroke. */
+ bGPDstroke *gps;
+ /** Point index in points array. */
+ int pt_index;
+ /** Position */
+ int pc[2];
+ /** Color */
+ float color[4];
+} tGP_Selected;
+
+/* Context for brush operators */
+typedef struct tGP_BrushWeightpaintData {
+ struct Main *bmain;
+ Scene *scene;
+ Object *object;
+
+ ARegion *region;
+
+ /* Current GPencil datablock */
+ bGPdata *gpd;
+
+ Brush *brush;
+
+ /* Space Conversion Data */
+ GP_SpaceConversion gsc;
+
+ /* Is the brush currently painting? */
+ bool is_painting;
+
+ /* Start of new paint */
+ bool first;
+
+ /* Is multi-frame editing enabled, and are we using falloff for that? */
+ bool is_multiframe;
+ bool use_multiframe_falloff;
+
+ /* active vertex group */
+ int vrgroup;
+
+ /* Brush Runtime Data: */
+ /* - position and pressure
+ * - the *_prev variants are the previous values
+ */
+ float mval[2], mval_prev[2];
+ float pressure, pressure_prev;
+
+ /* - Effect 2D vector */
+ float dvec[2];
+
+ /* - multi-frame falloff factor. */
+ float mf_falloff;
+
+ /* brush geometry (bounding box). */
+ rcti brush_rect;
+
+ /* Temp data to save selected points */
+ /** Stroke buffer. */
+ tGP_Selected *pbuffer;
+ /** Number of elements currently used in cache. */
+ int pbuffer_used;
+ /** Number of total elements available in cache. */
+ int pbuffer_size;
+} tGP_BrushWeightpaintData;
+
+/* Ensure the buffer to hold temp selected point size is enough to save all points selected. */
+static tGP_Selected *gpencil_select_buffer_ensure(tGP_Selected *buffer_array,
+ int *buffer_size,
+ int *buffer_used,
+ const bool clear)
+{
+ tGP_Selected *p = NULL;
+
+ /* By default a buffer is created with one block with a predefined number of free slots,
+ * if the size is not enough, the cache is reallocated adding a new block of free slots.
+ * This is done in order to keep cache small and improve speed. */
+ if (*buffer_used + 1 > *buffer_size) {
+ if ((*buffer_size == 0) || (buffer_array == NULL)) {
+ p = MEM_callocN(sizeof(struct tGP_Selected) * GP_SELECT_BUFFER_CHUNK, __func__);
+ *buffer_size = GP_SELECT_BUFFER_CHUNK;
+ }
+ else {
+ *buffer_size += GP_SELECT_BUFFER_CHUNK;
+ p = MEM_recallocN(buffer_array, sizeof(struct tGP_Selected) * *buffer_size);
+ }
+
+ if (p == NULL) {
+ *buffer_size = *buffer_used = 0;
+ }
+
+ buffer_array = p;
+ }
+
+ /* clear old data */
+ if (clear) {
+ *buffer_used = 0;
+ if (buffer_array != NULL) {
+ memset(buffer_array, 0, sizeof(tGP_Selected) * *buffer_size);
+ }
+ }
+
+ return buffer_array;
+}
+
+/* Brush Operations ------------------------------- */
+
+/* Compute strength of effect. */
+static float brush_influence_calc(tGP_BrushWeightpaintData *gso, const int radius, const int co[2])
+{
+ Brush *brush = gso->brush;
+
+ /* basic strength factor from brush settings */
+ float influence = brush->alpha;
+
+ /* use pressure? */
+ if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
+ influence *= gso->pressure;
+ }
+
+ /* distance fading */
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, gso->mval);
+ float distance = (float)len_v2v2_int(mval_i, co);
+ influence *= 1.0f - (distance / max_ff(radius, 1e-8));
+
+ /* Apply Brush curve. */
+ float brush_fallof = BKE_brush_curve_strength(brush, distance, (float)radius);
+ influence *= brush_fallof;
+
+ /* apply multi-frame falloff */
+ influence *= gso->mf_falloff;
+
+ /* return influence */
+ return influence;
+}
+
+/* Compute effect vector for directional brushes. */
+static void brush_calc_dvec_2d(tGP_BrushWeightpaintData *gso)
+{
+ gso->dvec[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
+ gso->dvec[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
+
+ normalize_v2(gso->dvec);
+}
+
+/* ************************************************ */
+/* Brush Callbacks
+ * This section defines the callbacks used by each brush to perform their magic.
+ * These are called on each point within the brush's radius. */
+
+/* Draw Brush */
+static bool brush_draw_apply(tGP_BrushWeightpaintData *gso,
+ bGPDstroke *gps,
+ int pt_index,
+ const int radius,
+ const int co[2])
+{
+ /* create dvert */
+ BKE_gpencil_dvert_ensure(gps);
+
+ MDeformVert *dvert = gps->dvert + pt_index;
+ float inf;
+
+ /* Compute strength of effect */
+ inf = brush_influence_calc(gso, radius, co);
+
+ /* need a vertex group */
+ if (gso->vrgroup == -1) {
+ if (gso->object) {
+ BKE_object_defgroup_add(gso->object);
+ DEG_relations_tag_update(gso->bmain);
+ gso->vrgroup = 0;
+ }
+ }
+ else {
+ bDeformGroup *defgroup = BLI_findlink(&gso->object->defbase, gso->vrgroup);
+ if (defgroup->flag & DG_LOCK_WEIGHT) {
+ return false;
+ }
+ }
+ /* Get current weight and blend. */
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert, gso->vrgroup);
+ if (dw) {
+ dw->weight = interpf(gso->brush->weight, dw->weight, inf);
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ return true;
+}
+
+/* ************************************************ */
+/* Header Info */
+static void gp_weightpaint_brush_header_set(bContext *C)
+{
+ ED_workspace_status_text(C, TIP_("GPencil Weight Paint: LMB to paint | RMB/Escape to Exit"));
+}
+
+/* ************************************************ */
+/* Grease Pencil Weight Paint Operator */
+
+/* Init/Exit ----------------------------------------------- */
+
+static bool gp_weightpaint_brush_init(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = CTX_data_active_object(C);
+ Paint *paint = &ts->gp_weightpaint->paint;
+
+ /* set the brush using the tool */
+ tGP_BrushWeightpaintData *gso;
+
+ /* setup operator data */
+ gso = MEM_callocN(sizeof(tGP_BrushWeightpaintData), "tGP_BrushWeightpaintData");
+ op->customdata = gso;
+
+ gso->bmain = CTX_data_main(C);
+
+ gso->brush = paint->brush;
+ BKE_curvemapping_initialize(gso->brush->curve);
+
+ gso->is_painting = false;
+ gso->first = true;
+
+ gso->pbuffer = NULL;
+ gso->pbuffer_size = 0;
+ gso->pbuffer_used = 0;
+
+ gso->gpd = ED_gpencil_data_get_active(C);
+ gso->scene = scene;
+ gso->object = ob;
+ if (ob) {
+ gso->vrgroup = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, gso->vrgroup)) {
+ gso->vrgroup = -1;
+ }
+ }
+ else {
+ gso->vrgroup = -1;
+ }
+
+ gso->region = CTX_wm_region(C);
+
+ /* Multiframe settings. */
+ gso->is_multiframe = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
+ gso->use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
+
+ /* Init multi-edit falloff curve data before doing anything,
+ * so we won't have to do it again later. */
+ if (gso->is_multiframe) {
+ BKE_curvemapping_initialize(ts->gp_sculpt.cur_falloff);
+ }
+
+ /* Setup space conversions. */
+ gp_point_conversion_init(C, &gso->gsc);
+
+ /* Update header. */
+ gp_weightpaint_brush_header_set(C);
+
+ return true;
+}
+
+static void gp_weightpaint_brush_exit(bContext *C, wmOperator *op)
+{
+ tGP_BrushWeightpaintData *gso = op->customdata;
+
+ /* Disable headerprints. */
+ ED_workspace_status_text(C, NULL);
+
+ /* Free operator data */
+ MEM_SAFE_FREE(gso->pbuffer);
+ MEM_SAFE_FREE(gso);
+ op->customdata = NULL;
+}
+
+/* Poll callback for stroke weight paint operator. */
+static bool gp_weightpaint_brush_poll(bContext *C)
+{
+ /* NOTE: this is a bit slower, but is the most accurate... */
+ return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
+}
+
+/* Helper to save the points selected by the brush. */
+static void gp_save_selected_point(tGP_BrushWeightpaintData *gso,
+ bGPDstroke *gps,
+ int index,
+ int pc[2])
+{
+ tGP_Selected *selected;
+ bGPDspoint *pt = &gps->points[index];
+
+ /* Ensure the array to save the list of selected points is big enough. */
+ gso->pbuffer = gpencil_select_buffer_ensure(
+ gso->pbuffer, &gso->pbuffer_size, &gso->pbuffer_used, false);
+
+ selected = &gso->pbuffer[gso->pbuffer_used];
+ selected->gps = gps;
+ selected->pt_index = index;
+ copy_v2_v2_int(selected->pc, pc);
+ copy_v4_v4(selected->color, pt->vert_color);
+
+ gso->pbuffer_used++;
+}
+
+/* Select points in this stroke and add to an array to be used later. */
+static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso,
+ bGPDstroke *gps,
+ const float diff_mat[4][4])
+{
+ GP_SpaceConversion *gsc = &gso->gsc;
+ rcti *rect = &gso->brush_rect;
+ Brush *brush = gso->brush;
+ const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
+ gso->brush->size;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ bGPDspoint *pt_active = NULL;
+
+ bGPDspoint *pt1, *pt2;
+ bGPDspoint *pt = NULL;
+ int pc1[2] = {0};
+ int pc2[2] = {0};
+ int i;
+ int index;
+ bool include_last = false;
+
+ /* Check if the stroke collide with brush. */
+ if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) {
+ return;
+ }
+
+ if (gps->totpoints == 1) {
+ bGPDspoint pt_temp;
+ pt = &gps->points[0];
+ gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
+ gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
+
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ /* do boundbox check first */
+ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
+ /* only check if point is inside */
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, gso->mval);
+ if (len_v2v2_int(mval_i, pc1) <= radius) {
+ /* apply operation to this point */
+ if (pt_active != NULL) {
+ gp_save_selected_point(gso, gps_active, 0, pc1);
+ }
+ }
+ }
+ }
+ else {
+ /* Loop over the points in the stroke, checking for intersections
+ * - an intersection means that we touched the stroke
+ */
+ for (i = 0; (i + 1) < gps->totpoints; i++) {
+ /* Get points to work with */
+ pt1 = gps->points + i;
+ pt2 = gps->points + i + 1;
+
+ bGPDspoint npt;
+ gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
+
+ gp_point_to_parent_space(pt2, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]);
+
+ /* Check that point segment of the boundbox of the selection stroke */
+ if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) ||
+ ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) {
+ /* Check if point segment of stroke had anything to do with
+ * brush region (either within stroke painted, or on its lines)
+ * - this assumes that linewidth is irrelevant
+ */
+ if (gp_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
+
+ /* To each point individually... */
+ pt = &gps->points[i];
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
+ if (pt_active != NULL) {
+ gp_save_selected_point(gso, gps_active, index, pc1);
+ }
+
+ /* Only do the second point if this is the last segment,
+ * and it is unlikely that the point will get handled
+ * otherwise.
+ *
+ * NOTE: There is a small risk here that the second point wasn't really
+ * actually in-range. In that case, it only got in because
+ * the line linking the points was!
+ */
+ if (i + 1 == gps->totpoints - 1) {
+ pt = &gps->points[i + 1];
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1;
+ if (pt_active != NULL) {
+ gp_save_selected_point(gso, gps_active, index, pc2);
+ include_last = false;
+ }
+ }
+ else {
+ include_last = true;
+ }
+ }
+ else if (include_last) {
+ /* This case is for cases where for whatever reason the second vert (1st here)
+ * doesn't get included because the whole edge isn't in bounds,
+ * but it would've qualified since it did with the previous step
+ * (but wasn't added then, to avoid double-ups).
+ */
+ pt = &gps->points[i];
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
+ if (pt_active != NULL) {
+ gp_save_selected_point(gso, gps_active, index, pc1);
+
+ include_last = false;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* Apply weight paint brushes to strokes in the given frame. */
+static bool gp_weightpaint_brush_do_frame(bContext *C,
+ tGP_BrushWeightpaintData *gso,
+ bGPDlayer *gpl,
+ bGPDframe *gpf,
+ const float diff_mat[4][4])
+{
+ Object *ob = CTX_data_active_object(C);
+ char tool = gso->brush->gpencil_weight_tool;
+ const int radius = (gso->brush->flag & GP_BRUSH_USE_PRESSURE) ?
+ gso->brush->size * gso->pressure :
+ gso->brush->size;
+ tGP_Selected *selected = NULL;
+ int i;
+
+ /*---------------------------------------------------------------------
+ * First step: select the points affected. This step is required to have
+ * all selected points before apply the effect, because it could be
+ * required to do some step. Now is not used, but the operator is ready.
+ *--------------------------------------------------------------------- */
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ /* Skip strokes that are invalid for current view. */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ /* Check if the color is editable. */
+ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+ continue;
+ }
+
+ /* Check points below the brush. */
+ gp_weightpaint_select_stroke(gso, gps, diff_mat);
+ }
+
+ /*---------------------------------------------------------------------
+ * Second step: Apply effect.
+ *--------------------------------------------------------------------- */
+ bool changed = false;
+ for (i = 0; i < gso->pbuffer_used; i++) {
+ changed = true;
+ selected = &gso->pbuffer[i];
+
+ switch (tool) {
+ case GPWEIGHT_TOOL_DRAW: {
+ brush_draw_apply(gso, selected->gps, selected->pt_index, radius, selected->pc);
+ changed |= true;
+ break;
+ }
+ default:
+ printf("ERROR: Unknown type of GPencil Weight Paint brush\n");
+ break;
+ }
+ }
+ /* Clear the selected array, but keep the memory allocation.*/
+ gso->pbuffer = gpencil_select_buffer_ensure(
+ gso->pbuffer, &gso->pbuffer_size, &gso->pbuffer_used, true);
+
+ return changed;
+}
+
+/* Apply brush effect to all layers. */
+static bool gp_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeightpaintData *gso)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Object *obact = gso->object;
+ bool changed = false;
+
+ Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obact->id);
+ bGPdata *gpd = (bGPdata *)ob_eval->data;
+
+ /* Find visible strokes, and perform operations on those if hit */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ /* If locked or no active frame, don't do anything. */
+ if ((!BKE_gpencil_layer_is_editable(gpl)) || (gpl->actframe == NULL)) {
+ continue;
+ }
+
+ /* calculate difference matrix */
+ float diff_mat[4][4];
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
+
+ /* Active Frame or MultiFrame? */
+ if (gso->is_multiframe) {
+ /* init multi-frame falloff options */
+ int f_init = 0;
+ int f_end = 0;
+
+ if (gso->use_multiframe_falloff) {
+ BKE_gpencil_frame_range_selected(gpl, &f_init, &f_end);
+ }
+
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ /* Always do active frame; Otherwise, only include selected frames */
+ if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
+ /* Compute multi-frame falloff factor. */
+ if (gso->use_multiframe_falloff) {
+ /* Falloff depends on distance to active frame
+ * (relative to the overall frame range). */
+ gso->mf_falloff = BKE_gpencil_multiframe_falloff_calc(
+ gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
+ }
+ else {
+ /* No falloff */
+ gso->mf_falloff = 1.0f;
+ }
+
+ /* affect strokes in this frame */
+ changed |= gp_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat);
+ }
+ }
+ }
+ else {
+ if (gpl->actframe != NULL) {
+ /* Apply to active frame's strokes */
+ gso->mf_falloff = 1.0f;
+ changed |= gp_weightpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat);
+ }
+ }
+ }
+
+ return changed;
+}
+
+/* Calculate settings for applying brush */
+static void gp_weightpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
+{
+ tGP_BrushWeightpaintData *gso = op->customdata;
+ Brush *brush = gso->brush;
+ const int radius = ((brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
+ gso->brush->size);
+ float mousef[2];
+ int mouse[2];
+ bool changed = false;
+
+ /* Get latest mouse coordinates */
+ RNA_float_get_array(itemptr, "mouse", mousef);
+ gso->mval[0] = mouse[0] = (int)(mousef[0]);
+ gso->mval[1] = mouse[1] = (int)(mousef[1]);
+
+ gso->pressure = RNA_float_get(itemptr, "pressure");
+
+ /* Store coordinates as reference, if operator just started running */
+ if (gso->first) {
+ gso->mval_prev[0] = gso->mval[0];
+ gso->mval_prev[1] = gso->mval[1];
+ gso->pressure_prev = gso->pressure;
+ }
+
+ /* Update brush_rect, so that it represents the bounding rectangle of brush. */
+ gso->brush_rect.xmin = mouse[0] - radius;
+ gso->brush_rect.ymin = mouse[1] - radius;
+ gso->brush_rect.xmax = mouse[0] + radius;
+ gso->brush_rect.ymax = mouse[1] + radius;
+
+ /* Calculate 2D direction vector and relative angle. */
+ brush_calc_dvec_2d(gso);
+
+ changed = gp_weightpaint_brush_apply_to_layers(C, gso);
+
+ /* Updates */
+ if (changed) {
+ DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ /* Store values for next step */
+ gso->mval_prev[0] = gso->mval[0];
+ gso->mval_prev[1] = gso->mval[1];
+ gso->pressure_prev = gso->pressure;
+ gso->first = false;
+}
+
+/* Running --------------------------------------------- */
+
+/* helper - a record stroke, and apply paint event */
+static void gp_weightpaint_brush_apply_event(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGP_BrushWeightpaintData *gso = op->customdata;
+ PointerRNA itemptr;
+ float mouse[2];
+
+ mouse[0] = event->mval[0] + 1;
+ mouse[1] = event->mval[1] + 1;
+
+ /* fill in stroke */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ RNA_float_set_array(&itemptr, "mouse", mouse);
+ RNA_boolean_set(&itemptr, "pen_flip", event->ctrl != false);
+ RNA_boolean_set(&itemptr, "is_start", gso->first);
+
+ /* Handle pressure sensitivity (which is supplied by tablets). */
+ float pressure = event->tablet.pressure;
+ CLAMP(pressure, 0.0f, 1.0f);
+ RNA_float_set(&itemptr, "pressure", pressure);
+
+ /* apply */
+ gp_weightpaint_brush_apply(C, op, &itemptr);
+}
+
+/* reapply */
+static int gp_weightpaint_brush_exec(bContext *C, wmOperator *op)
+{
+ if (!gp_weightpaint_brush_init(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_BEGIN (op->ptr, itemptr, "stroke") {
+ gp_weightpaint_brush_apply(C, op, &itemptr);
+ }
+ RNA_END;
+
+ gp_weightpaint_brush_exit(C, op);
+
+ return OPERATOR_FINISHED;
+}
+
+/* start modal painting */
+static int gp_weightpaint_brush_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGP_BrushWeightpaintData *gso = NULL;
+ const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
+ const bool is_playing = ED_screen_animation_playing(CTX_wm_manager(C)) != NULL;
+
+ /* the operator cannot work while play animation */
+ if (is_playing) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot Paint while play animation");
+
+ return OPERATOR_CANCELLED;
+ }
+
+ /* init painting data */
+ if (!gp_weightpaint_brush_init(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ gso = op->customdata;
+
+ /* register modal handler */
+ WM_event_add_modal_handler(C, op);
+
+ /* start drawing immediately? */
+ if (is_modal == false) {
+ ARegion *region = CTX_wm_region(C);
+
+ /* apply first dab... */
+ gso->is_painting = true;
+ gp_weightpaint_brush_apply_event(C, op, event);
+
+ /* redraw view with feedback */
+ ED_region_tag_redraw(region);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* painting - handle events */
+static int gp_weightpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGP_BrushWeightpaintData *gso = op->customdata;
+ const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
+ bool redraw_region = false;
+ bool redraw_toolsettings = false;
+
+ /* The operator can be in 2 states: Painting and Idling */
+ if (gso->is_painting) {
+ /* Painting */
+ switch (event->type) {
+ /* Mouse Move = Apply somewhere else */
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE:
+ /* apply brush effect at new position */
+ gp_weightpaint_brush_apply_event(C, op, event);
+
+ /* force redraw, so that the cursor will at least be valid */
+ redraw_region = true;
+ break;
+
+ /* Painting mbut release = Stop painting (back to idle) */
+ case LEFTMOUSE:
+ if (is_modal) {
+ /* go back to idling... */
+ gso->is_painting = false;
+ }
+ else {
+ /* end painting, since we're not modal */
+ gso->is_painting = false;
+
+ gp_weightpaint_brush_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+
+ /* Abort painting if any of the usual things are tried */
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ case EVT_ESCKEY:
+ gp_weightpaint_brush_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ else {
+ /* Idling */
+ BLI_assert(is_modal == true);
+
+ switch (event->type) {
+ /* Painting mbut press = Start painting (switch to painting state) */
+ case LEFTMOUSE:
+ /* do initial "click" apply */
+ gso->is_painting = true;
+ gso->first = true;
+
+ gp_weightpaint_brush_apply_event(C, op, event);
+ break;
+
+ /* Exit modal operator, based on the "standard" ops */
+ case RIGHTMOUSE:
+ case EVT_ESCKEY:
+ gp_weightpaint_brush_exit(C, op);
+ return OPERATOR_FINISHED;
+
+ /* MMB is often used for view manipulations */
+ case MIDDLEMOUSE:
+ return OPERATOR_PASS_THROUGH;
+
+ /* Mouse movements should update the brush cursor - Just redraw the active region */
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE:
+ redraw_region = true;
+ break;
+
+ /* Change Frame - Allowed */
+ case EVT_LEFTARROWKEY:
+ case EVT_RIGHTARROWKEY:
+ case EVT_UPARROWKEY:
+ case EVT_DOWNARROWKEY:
+ return OPERATOR_PASS_THROUGH;
+
+ /* Camera/View Gizmo's - Allowed */
+ /* (See rationale in gpencil_paint.c -> gpencil_draw_modal()) */
+ case EVT_PAD0:
+ case EVT_PAD1:
+ case EVT_PAD2:
+ case EVT_PAD3:
+ case EVT_PAD4:
+ case EVT_PAD5:
+ case EVT_PAD6:
+ case EVT_PAD7:
+ case EVT_PAD8:
+ case EVT_PAD9:
+ return OPERATOR_PASS_THROUGH;
+
+ /* Unhandled event */
+ default:
+ break;
+ }
+ }
+
+ /* Redraw region? */
+ if (redraw_region) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
+
+ /* Redraw toolsettings (brush settings)? */
+ if (redraw_toolsettings) {
+ DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void GPENCIL_OT_weight_paint(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Stroke Weight Paint";
+ ot->idname = "GPENCIL_OT_weight_paint";
+ ot->description = "Paint stroke points with a color";
+
+ /* api callbacks */
+ ot->exec = gp_weightpaint_brush_exec;
+ ot->invoke = gp_weightpaint_brush_invoke;
+ ot->modal = gp_weightpaint_brush_modal;
+ ot->cancel = gp_weightpaint_brush_exit;
+ ot->poll = gp_weightpaint_brush_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index a49f02d28fe..04f9edeaf3a 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -24,6 +24,10 @@
#ifndef __BIF_GLUTIL_H__
#define __BIF_GLUTIL_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct rcti;
struct ColorManagedDisplaySettings;
@@ -177,4 +181,8 @@ void bglPolygonOffset(float viewdist, float dist);
void immDrawBorderCorners(unsigned int pos, const struct rcti *border, float zoomx, float zoomy);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BIF_GLUTIL_H__ */
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index bf9b69f12e1..7d38792f332 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -24,6 +24,10 @@
#ifndef __ED_ANIM_API_H__
#define __ED_ANIM_API_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct AnimData;
struct Depsgraph;
struct ID;
@@ -70,17 +74,17 @@ typedef struct bAnimContext {
/** editor->mode */
short mode;
- /** sa->spacetype */
+ /** area->spacetype */
short spacetype;
/** active region -> type (channels or main) */
short regiontype;
/** editor host */
- struct ScrArea *sa;
+ struct ScrArea *area;
/** editor data */
struct SpaceLink *sl;
/** region within editor */
- struct ARegion *ar;
+ struct ARegion *region;
/** dopesheet data for editor (or which is being used) */
struct bDopeSheet *ads;
@@ -189,7 +193,7 @@ typedef struct bAnimListElem {
typedef enum eAnim_ChannelType {
ANIMTYPE_NONE = 0,
ANIMTYPE_ANIMDATA,
- ANIMTYPE_SPECIALDATA,
+ ANIMTYPE_SPECIALDATA__UNUSED,
ANIMTYPE_SUMMARY,
@@ -222,6 +226,10 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSSPK,
ANIMTYPE_DSGPENCIL,
ANIMTYPE_DSMCLIP,
+ ANIMTYPE_DSHAIR,
+ ANIMTYPE_DSPOINTCLOUD,
+ ANIMTYPE_DSVOLUME,
+ ANIMTYPE_DSSIMULATION,
ANIMTYPE_SHAPEKEY,
@@ -330,25 +338,30 @@ typedef enum eAnimFilter_Flags {
/* 'Object' channels */
#define SEL_OBJC(base) (CHECK_TYPE_INLINE(base, Base *), ((base->flag & SELECT)))
#define EXPANDED_OBJC(ob) \
- (CHECK_TYPE_INLINE(ob, Object *), ((ob->nlaflag & OB_ADS_COLLAPSED) == 0))
+ (CHECK_TYPE_INLINE(ob, Object *), (((ob)->nlaflag & OB_ADS_COLLAPSED) == 0))
/* 'Sub-object' channels (flags stored in Data block) */
#define FILTER_SKE_OBJD(key) (CHECK_TYPE_INLINE(key, Key *), ((key->flag & KEY_DS_EXPAND)))
#define FILTER_MAT_OBJD(ma) (CHECK_TYPE_INLINE(ma, Material *), ((ma->flag & MA_DS_EXPAND)))
#define FILTER_LAM_OBJD(la) (CHECK_TYPE_INLINE(la, Light *), ((la->flag & LA_DS_EXPAND)))
#define FILTER_CAM_OBJD(ca) (CHECK_TYPE_INLINE(ca, Camera *), ((ca->flag & CAM_DS_EXPAND)))
#define FILTER_CACHEFILE_OBJD(cf) \
- (CHECK_TYPE_INLINE(cf, CacheFile *), ((cf->flag & CACHEFILE_DS_EXPAND)))
+ (CHECK_TYPE_INLINE(cf, CacheFile *), (((cf)->flag & CACHEFILE_DS_EXPAND)))
#define FILTER_CUR_OBJD(cu) (CHECK_TYPE_INLINE(cu, Curve *), ((cu->flag & CU_DS_EXPAND)))
#define FILTER_PART_OBJD(part) \
- (CHECK_TYPE_INLINE(part, ParticleSettings *), ((part->flag & PART_DS_EXPAND)))
+ (CHECK_TYPE_INLINE(part, ParticleSettings *), (((part)->flag & PART_DS_EXPAND)))
#define FILTER_MBALL_OBJD(mb) (CHECK_TYPE_INLINE(mb, MetaBall *), ((mb->flag2 & MB_DS_EXPAND)))
#define FILTER_ARM_OBJD(arm) (CHECK_TYPE_INLINE(arm, bArmature *), ((arm->flag & ARM_DS_EXPAND)))
#define FILTER_MESH_OBJD(me) (CHECK_TYPE_INLINE(me, Mesh *), ((me->flag & ME_DS_EXPAND)))
#define FILTER_LATTICE_OBJD(lt) (CHECK_TYPE_INLINE(lt, Lattice *), ((lt->flag & LT_DS_EXPAND)))
#define FILTER_SPK_OBJD(spk) (CHECK_TYPE_INLINE(spk, Speaker *), ((spk->flag & SPK_DS_EXPAND)))
+#define FILTER_HAIR_OBJD(ha) (CHECK_TYPE_INLINE(ha, Hair *), ((ha->flag & HA_DS_EXPAND)))
+#define FILTER_POINTS_OBJD(pt) (CHECK_TYPE_INLINE(pt, PointCloud *), ((pt->flag & PT_DS_EXPAND)))
+#define FILTER_VOLUME_OBJD(vo) (CHECK_TYPE_INLINE(vo, Volume *), ((vo->flag & VO_DS_EXPAND)))
+#define FILTER_SIMULATION_OBJD(sim) \
+ (CHECK_TYPE_INLINE(sim, Simulation *), ((sim->flag & SIM_DS_EXPAND)))
/* Variable use expanders */
#define FILTER_NTREE_DATA(ntree) \
- (CHECK_TYPE_INLINE(ntree, bNodeTree *), ((ntree->flag & NTREE_DS_EXPAND)))
+ (CHECK_TYPE_INLINE(ntree, bNodeTree *), (((ntree)->flag & NTREE_DS_EXPAND)))
#define FILTER_TEX_DATA(tex) (CHECK_TYPE_INLINE(tex, Tex *), ((tex->flag & TEX_DS_EXPAND)))
/* 'Sub-object/Action' channels (flags stored in Action) */
@@ -359,11 +372,11 @@ typedef enum eAnimFilter_Flags {
/* Actions (also used for Dopesheet) */
/* Action Channel Group */
-#define EDITABLE_AGRP(agrp) ((agrp->flag & AGRP_PROTECTED) == 0)
+#define EDITABLE_AGRP(agrp) (((agrp)->flag & AGRP_PROTECTED) == 0)
#define EXPANDED_AGRP(ac, agrp) \
- (((!(ac) || ((ac)->spacetype != SPACE_GRAPH)) && (agrp->flag & AGRP_EXPANDED)) || \
- (((ac) && ((ac)->spacetype == SPACE_GRAPH)) && (agrp->flag & AGRP_EXPANDED_G)))
-#define SEL_AGRP(agrp) ((agrp->flag & AGRP_SELECTED) || (agrp->flag & AGRP_ACTIVE))
+ (((!(ac) || ((ac)->spacetype != SPACE_GRAPH)) && ((agrp)->flag & AGRP_EXPANDED)) || \
+ (((ac) && ((ac)->spacetype == SPACE_GRAPH)) && ((agrp)->flag & AGRP_EXPANDED_G)))
+#define SEL_AGRP(agrp) (((agrp)->flag & AGRP_SELECTED) || ((agrp)->flag & AGRP_ACTIVE))
/* F-Curve Channels */
#define EDITABLE_FCU(fcu) ((fcu->flag & FCURVE_PROTECTED) == 0)
#define SEL_FCU(fcu) (fcu->flag & FCURVE_SELECTED)
@@ -403,7 +416,7 @@ typedef enum eAnimFilter_Flags {
/* channel heights */
#define ACHANNEL_FIRST_TOP(ac) \
- (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_TIME_SCRUB_MARGIN_Y - ACHANNEL_SKIP)
+ (UI_view2d_scale_get_y(&(ac)->region->v2d) * -UI_TIME_SCRUB_MARGIN_Y - ACHANNEL_SKIP)
#define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit)
#define ACHANNEL_SKIP (0.1f * U.widget_unit)
#define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP)
@@ -421,9 +434,10 @@ typedef enum eAnimFilter_Flags {
/* NLA channel heights */
#define NLACHANNEL_FIRST_TOP(ac) \
- (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_TIME_SCRUB_MARGIN_Y - NLACHANNEL_SKIP)
+ (UI_view2d_scale_get_y(&(ac)->region->v2d) * -UI_TIME_SCRUB_MARGIN_Y - NLACHANNEL_SKIP)
#define NLACHANNEL_HEIGHT(snla) \
- ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.8f * U.widget_unit) : (1.2f * U.widget_unit))
+ (((snla) && ((snla)->flag & SNLA_NOSTRIPCURVES)) ? (0.8f * U.widget_unit) : \
+ (1.2f * U.widget_unit))
#define NLACHANNEL_SKIP (0.1f * U.widget_unit)
#define NLACHANNEL_STEP(snla) (NLACHANNEL_HEIGHT(snla) + NLACHANNEL_SKIP)
/* Additional offset to give some room at the end. */
@@ -474,7 +488,7 @@ typedef enum eAnimChannel_Role {
/** datablock expander - a "composite" channel type */
ACHANNEL_ROLE_EXPANDER = -1,
/** special purposes - not generally for hierarchy processing */
- ACHANNEL_ROLE_SPECIAL = 0,
+ /* ACHANNEL_ROLE_SPECIAL = 0, */ /* UNUSED */
/** data channel - a channel representing one of the actual building blocks of channels */
ACHANNEL_ROLE_CHANNEL = 1,
} eAnimChannel_Role;
@@ -628,7 +642,7 @@ bool ANIM_remove_empty_action_from_animdata(struct AnimData *adt);
/* flags for Current Frame Drawing */
enum eAnimEditDraw_CurrentFrame {
/* plain time indicator with no special indicators */
- DRAWCFRA_PLAIN = 0,
+ /* DRAWCFRA_PLAIN = 0, */ /* UNUSED */
/* time indication in seconds or frames */
DRAWCFRA_UNIT_SECONDS = (1 << 0),
/* draw indicator extra wide (for timeline) */
@@ -729,7 +743,7 @@ typedef enum eAnimUnitConv_Flags {
ANIM_UNITCONV_ONLYSEL = (1 << 2),
/* only touch selected vertices */
ANIM_UNITCONV_SELVERTS = (1 << 3),
- ANIM_UNITCONV_SKIPKNOTS = (1 << 4),
+ /* ANIM_UNITCONV_SKIPKNOTS = (1 << 4), */ /* UNUSED */
/* Scale FCurve i a way it fits to -1..1 space */
ANIM_UNITCONV_NORMALIZE = (1 << 5),
/* Only when normalization is used: use scale factor from previous run,
@@ -830,7 +844,7 @@ void ED_animedit_unlink_action(struct bContext *C,
bool force_delete);
/* Drivers Editor - Utility to set up UI correctly */
-void ED_drivers_editor_init(struct bContext *C, struct ScrArea *sa);
+void ED_drivers_editor_init(struct bContext *C, struct ScrArea *area);
/* ************************************************ */
@@ -859,4 +873,8 @@ void animviz_calc_motionpaths(struct Depsgraph *depsgraph,
void animviz_get_object_motionpaths(struct Object *ob, ListBase *targets);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_ANIM_API_H__ */
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 7ac42967dda..102c0dc0659 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -134,62 +134,51 @@ typedef struct EditBone {
(((arm)->layer & (ebone)->layer) && !((ebone)->flag & BONE_HIDDEN_A)))
#define EBONE_SELECTABLE(arm, ebone) \
- (EBONE_VISIBLE(arm, ebone) && !(ebone->flag & BONE_UNSELECTABLE))
+ (EBONE_VISIBLE(arm, ebone) && !((ebone)->flag & BONE_UNSELECTABLE))
#define EBONE_EDITABLE(ebone) \
(CHECK_TYPE_INLINE(ebone, EditBone *), \
(((ebone)->flag & BONE_SELECTED) && !((ebone)->flag & BONE_EDITMODE_LOCKED)))
-/* used in armature_select_hierarchy_exec() */
+/* used in armature_select.c and pose_select.c */
#define BONE_SELECT_PARENT 0
#define BONE_SELECT_CHILD 1
+/* armature_add.c */
+EditBone *ED_armature_ebone_add(struct bArmature *arm, const char *name);
+EditBone *ED_armature_ebone_add_primitive(struct Object *obedit_arm,
+ float length,
+ bool view_aligned);
+
+/* armature_edit.c */
+float ED_armature_ebone_roll_to_vector(const EditBone *bone,
+ const float new_up_axis[3],
+ const bool axis_only);
+void ED_armature_origin_set(
+ struct Main *bmain, struct Object *ob, const float cursor[3], int centermode, int around);
+void ED_armature_edit_transform(struct bArmature *arm, const float mat[4][4], const bool do_props);
+void ED_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props);
+
+/* armature_naming.c */
+void ED_armature_ebone_unique_name(struct ListBase *ebones, char *name, EditBone *bone);
+void ED_armature_bone_rename(struct Main *bmain,
+ struct bArmature *arm,
+ const char *oldnamep,
+ const char *newnamep);
+void ED_armature_bones_flip_names(struct Main *bmain,
+ struct bArmature *arm,
+ struct ListBase *bones_names,
+ const bool do_strip_numbers);
+
/* armature_ops.c */
void ED_operatortypes_armature(void);
void ED_operatormacros_armature(void);
void ED_keymap_armature(struct wmKeyConfig *keyconf);
-/* editarmature.c */
-void ED_armature_from_edit(struct Main *bmain, struct bArmature *arm);
-void ED_armature_to_edit(struct bArmature *arm);
-void ED_armature_edit_free(struct bArmature *arm);
-
-bool ED_armature_edit_deselect_all(struct Object *obedit);
-bool ED_armature_edit_deselect_all_visible(struct Object *obedit);
-
-bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len);
-bool ED_armature_edit_deselect_all_visible_multi_ex(struct Base **bases, uint bases_len);
-bool ED_armature_edit_deselect_all_visible_multi(struct bContext *C);
-
-bool ED_armature_pose_select_pick_with_buffer(struct ViewLayer *view_layer,
- struct View3D *v3d,
- struct Base *base,
- const unsigned int *buffer,
- short hits,
- bool extend,
- 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);
-
-bool ED_armature_edit_select_op_from_tagged(struct bArmature *arm, const int sel_op);
-
+/* armature_relations.c */
int join_armature_exec(struct bContext *C, struct wmOperator *op);
-float ED_armature_ebone_roll_to_vector(const EditBone *bone,
- const float new_up_axis[3],
- const bool axis_only);
-EditBone *ED_armature_ebone_find_name(const struct ListBase *edbo, const char *name);
-EditBone *ED_armature_ebone_get_mirrored(const struct ListBase *edbo, EditBone *ebo);
-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);
+/* armature_select.c */
struct Base *ED_armature_base_and_ebone_from_select_buffer(struct Base **bases,
uint bases_len,
int hit,
@@ -198,63 +187,63 @@ struct Object *ED_armature_object_and_ebone_from_select_buffer(struct Object **o
uint objects_len,
int hit,
struct EditBone **r_ebone);
-
+struct Base *ED_armature_base_and_pchan_from_select_buffer(struct Base **bases,
+ uint bases_len,
+ int hit,
+ struct bPoseChannel **r_pchan);
struct Base *ED_armature_base_and_bone_from_select_buffer(struct Base **bases,
uint bases_len,
int hit,
struct Bone **r_bone);
+bool ED_armature_edit_deselect_all(struct Object *obedit);
+bool ED_armature_edit_deselect_all_visible(struct Object *obedit);
+bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len);
+bool ED_armature_edit_deselect_all_visible_multi_ex(struct Base **bases, uint bases_len);
+bool ED_armature_edit_deselect_all_visible_multi(struct bContext *C);
+bool ED_armature_edit_select_pick(
+ struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+bool ED_armature_edit_select_op_from_tagged(struct bArmature *arm, const int sel_op);
-EditBone *ED_armature_ebone_add_primitive(struct Object *obedit_arm,
- float length,
- bool view_aligned);
-EditBone *ED_armature_ebone_add(struct bArmature *arm, const char *name);
+/* armature_skinning.c */
+#define ARM_GROUPS_NAME 1
+#define ARM_GROUPS_ENVELOPE 2
+#define ARM_GROUPS_AUTO 3
+void ED_object_vgroup_calc_from_armature(struct ReportList *reports,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct Object *par,
+ const int mode,
+ const bool mirror);
+
+/* editarmature_undo.c */
+void ED_armature_undosys_type(struct UndoType *ut);
+/* armature_utils.c */
+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);
void ED_armature_ebone_remove_ex(struct bArmature *arm, EditBone *exBone, bool clear_connected);
void ED_armature_ebone_remove(struct bArmature *arm, EditBone *exBone);
-
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child);
EditBone *ED_armature_ebone_find_shared_parent(EditBone *ebone_child[],
const unsigned int ebone_child_tot);
-
void ED_armature_ebone_to_mat3(EditBone *ebone, float mat[3][3]);
void ED_armature_ebone_to_mat4(EditBone *ebone, float mat[4][4]);
-
void ED_armature_ebone_from_mat3(EditBone *ebone, float mat[3][3]);
void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4]);
-
+EditBone *ED_armature_ebone_find_name(const struct ListBase *edbo, const char *name);
+EditBone *ED_armature_ebone_get_mirrored(const struct ListBase *edbo, EditBone *ebo);
void ED_armature_ebone_transform_mirror_update(struct bArmature *arm,
EditBone *ebo,
bool check_select);
void ED_armature_edit_transform_mirror_update(struct Object *obedit);
-void ED_armature_origin_set(
- struct Main *bmain, struct Object *ob, const float cursor[3], int centermode, int around);
-
-void ED_armature_edit_transform(struct bArmature *arm, const float mat[4][4], const bool do_props);
-
-void ED_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props);
-
-#define ARM_GROUPS_NAME 1
-#define ARM_GROUPS_ENVELOPE 2
-#define ARM_GROUPS_AUTO 3
-
-void ED_object_vgroup_calc_from_armature(struct ReportList *reports,
- struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct Object *ob,
- struct Object *par,
- const int mode,
- const bool mirror);
-
-/* if bone is already in list, pass it as param to ignore it */
-void ED_armature_ebone_unique_name(struct ListBase *ebones, char *name, EditBone *bone);
-void ED_armature_bone_rename(struct Main *bmain,
- struct bArmature *arm,
- const char *oldnamep,
- const char *newnamep);
-void ED_armature_bones_flip_names(struct Main *bmain,
- struct bArmature *arm,
- struct ListBase *bones_names,
- const bool do_strip_numbers);
+void ED_armature_from_edit(struct Main *bmain, struct bArmature *arm);
+void ED_armature_to_edit(struct bArmature *arm);
+void ED_armature_edit_free(struct bArmature *arm);
+void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb);
+void ED_armature_ebone_listbase_free(struct ListBase *lb);
+void ED_armature_ebone_listbase_copy(struct ListBase *lb_dst, struct ListBase *lb_src);
/* low level selection functions which handle */
int ED_armature_ebone_selectflag_get(const EditBone *ebone);
@@ -263,27 +252,12 @@ void ED_armature_ebone_select_set(EditBone *ebone, bool select);
void ED_armature_ebone_selectflag_enable(EditBone *ebone, int flag);
void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag);
-/* editarmature_undo.c */
-void ED_armature_undosys_type(struct UndoType *ut);
-
-/* armature_utils.c */
-void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb);
-void ED_armature_ebone_listbase_free(struct ListBase *lb);
-void ED_armature_ebone_listbase_copy(struct ListBase *lb_dst, struct ListBase *lb_src);
-
-/* poseobject.c */
+/* pose_edit.c */
+struct Object *ED_pose_object_from_context(struct bContext *C);
bool ED_object_posemode_exit_ex(struct Main *bmain, struct Object *ob);
bool ED_object_posemode_exit(struct bContext *C, struct Object *ob);
bool ED_object_posemode_enter_ex(struct Main *bmain, struct Object *ob);
bool ED_object_posemode_enter(struct bContext *C, struct Object *ob);
-bool ED_pose_deselect_all_multi_ex(struct Base **bases,
- uint bases_len,
- int select_mode,
- const bool ignore_visibility);
-bool ED_pose_deselect_all_multi(struct bContext *C, int select_mode, const bool ignore_visibility);
-bool ED_pose_deselect_all(struct Object *ob, int select_mode, const bool ignore_visibility);
-void ED_pose_bone_select_tag_update(struct Object *ob);
-void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select);
/* Corresponds to eAnimvizCalcRange. */
typedef enum ePosePathCalcRange {
@@ -296,7 +270,26 @@ void ED_pose_recalculate_paths(struct bContext *C,
struct Object *ob,
ePosePathCalcRange range);
-struct Object *ED_pose_object_from_context(struct bContext *C);
+/* pose_select.c */
+bool ED_armature_pose_select_pick_with_buffer(struct ViewLayer *view_layer,
+ struct View3D *v3d,
+ struct Base *base,
+ const unsigned int *buffer,
+ short hits,
+ bool extend,
+ 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_pose_deselect_all_multi_ex(struct Base **bases,
+ uint bases_len,
+ int select_mode,
+ const bool ignore_visibility);
+bool ED_pose_deselect_all_multi(struct bContext *C, int select_mode, const bool ignore_visibility);
+bool ED_pose_deselect_all(struct Object *ob, int select_mode, const bool ignore_visibility);
+void ED_pose_bone_select_tag_update(struct Object *ob);
+void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select);
/* meshlaplacian.c */
void ED_mesh_deform_bind_callback(struct MeshDeformModifierData *mmd,
diff --git a/source/blender/editors/include/ED_buttons.h b/source/blender/editors/include/ED_buttons.h
index 9ff2678b53e..2eaef5e82e0 100644
--- a/source/blender/editors/include/ED_buttons.h
+++ b/source/blender/editors/include/ED_buttons.h
@@ -23,4 +23,12 @@
#ifndef __ED_BUTTONS_H__
#define __ED_BUTTONS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_BUTTONS_H__ */
diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h
index 22bf22e04d3..f270a0324f9 100644
--- a/source/blender/editors/include/ED_clip.h
+++ b/source/blender/editors/include/ED_clip.h
@@ -24,6 +24,10 @@
#ifndef __ED_CLIP_H__
#define __ED_CLIP_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegion;
struct ImBuf;
struct Main;
@@ -46,7 +50,10 @@ bool ED_space_clip_maskedit_mask_poll(struct bContext *C);
void ED_space_clip_get_size(struct SpaceClip *sc, int *width, int *height);
void ED_space_clip_get_size_fl(struct SpaceClip *sc, float size[2]);
-void ED_space_clip_get_zoom(struct SpaceClip *sc, struct ARegion *ar, float *zoomx, float *zoomy);
+void ED_space_clip_get_zoom(struct SpaceClip *sc,
+ struct ARegion *region,
+ float *zoomx,
+ float *zoomy);
void ED_space_clip_get_aspect(struct SpaceClip *sc, float *aspx, float *aspy);
void ED_space_clip_get_aspect_dimension_aware(struct SpaceClip *sc, float *aspx, float *aspy);
@@ -59,24 +66,27 @@ struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc,
float *angle);
bool ED_space_clip_color_sample(struct SpaceClip *sc,
- struct ARegion *ar,
+ struct ARegion *region,
int mval[2],
float r_col[3]);
void ED_clip_update_frame(const struct Main *mainp, int cfra);
-bool ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, bool fit);
+bool ED_clip_view_selection(const struct bContext *C, struct ARegion *region, bool fit);
void ED_clip_select_all(struct SpaceClip *sc, int action, bool *r_has_selection);
bool ED_clip_can_select(struct bContext *C);
void ED_clip_point_undistorted_pos(struct SpaceClip *sc, const float co[2], float r_co[2]);
void ED_clip_point_stable_pos(
- struct SpaceClip *sc, struct ARegion *ar, float x, float y, float *xr, float *yr);
+ struct SpaceClip *sc, struct ARegion *region, float x, float y, float *xr, float *yr);
void ED_clip_point_stable_pos__reverse(struct SpaceClip *sc,
- struct ARegion *ar,
+ struct ARegion *region,
const float co[2],
float r_co[2]);
-void ED_clip_mouse_pos(struct SpaceClip *sc, struct ARegion *ar, const int mval[2], float co[2]);
+void ED_clip_mouse_pos(struct SpaceClip *sc,
+ struct ARegion *region,
+ const int mval[2],
+ float co[2]);
bool ED_space_clip_check_show_trackedit(struct SpaceClip *sc);
bool ED_space_clip_check_show_maskedit(struct SpaceClip *sc);
@@ -93,4 +103,8 @@ void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mas
/* ** clip_ops.c ** */
void ED_operatormacros_clip(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_CLIP_H__ */
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index d6d5ae299b7..95c454043da 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -24,6 +24,10 @@
#ifndef __ED_CURVE_H__
#define __ED_CURVE_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct BPoint;
struct Base;
struct BezTriple;
@@ -104,4 +108,8 @@ void ED_font_undosys_type(struct UndoType *ut);
void printknots(struct Object *obedit);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_CURVE_H__ */
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
index ada90205b4a..ad1cde5406d 100644
--- a/source/blender/editors/include/ED_datafiles.h
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -24,6 +24,10 @@
#ifndef __ED_DATAFILES_H__
#define __ED_DATAFILES_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Datafiles embedded in Blender */
extern int datatoc_startup_blend_size;
@@ -44,21 +48,15 @@ extern char datatoc_blender_icons32_png[];
extern int datatoc_prvicons_png_size;
extern char datatoc_prvicons_png[];
+extern int datatoc_alert_icons_png_size;
+extern char datatoc_alert_icons_png[];
+
extern int datatoc_splash_png_size;
extern char datatoc_splash_png[];
-extern int datatoc_splash_2x_png_size;
-extern char datatoc_splash_2x_png[];
-
extern int datatoc_bfont_pfb_size;
extern char datatoc_bfont_pfb[];
-extern int datatoc_bfont_ttf_size;
-extern char datatoc_bfont_ttf[];
-
-extern int datatoc_bmonofont_ttf_size;
-extern char datatoc_bmonofont_ttf[];
-
/* Brush icon datafiles */
/* TODO: this could be simplified by putting all
* the brush icons in one file */
@@ -300,4 +298,8 @@ extern char datatoc_gp_brush_erase_hard_png[];
extern int datatoc_gp_brush_erase_stroke_png_size;
extern char datatoc_gp_brush_erase_stroke_png[];
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_DATAFILES_H__ */
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 98e1e99116f..a523e924e54 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -24,8 +24,13 @@
#ifndef __ED_FILESELECT_H__
#define __ED_FILESELECT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegion;
struct FileSelectParams;
+struct Scene;
struct ScrArea;
struct SpaceFile;
struct bContext;
@@ -106,11 +111,11 @@ void ED_fileselect_params_to_userdef(struct SpaceFile *sfile,
void ED_fileselect_reset_params(struct SpaceFile *sfile);
-void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar);
+void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *region);
-FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *ar);
+FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *region);
-int ED_fileselect_layout_numfiles(FileLayout *layout, struct ARegion *ar);
+int ED_fileselect_layout_numfiles(FileLayout *layout, struct ARegion *region);
int ED_fileselect_layout_offset(FileLayout *layout, int x, int y);
FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const struct rcti *rect);
@@ -129,9 +134,13 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y);
void ED_operatormacros_file(void);
-void ED_fileselect_clear(struct wmWindowManager *wm, struct ScrArea *sa, struct SpaceFile *sfile);
+void ED_fileselect_clear(struct wmWindowManager *wm,
+ struct Scene *owner_scene,
+ struct SpaceFile *sfile);
-void ED_fileselect_exit(struct wmWindowManager *wm, struct ScrArea *sa, struct SpaceFile *sfile);
+void ED_fileselect_exit(struct wmWindowManager *wm,
+ struct Scene *owner_scene,
+ struct SpaceFile *sfile);
void ED_fileselect_window_params_get(const struct wmWindow *win,
int win_size[2],
@@ -167,6 +176,8 @@ typedef enum FSMenuCategory {
FS_CATEGORY_SYSTEM_BOOKMARKS,
FS_CATEGORY_BOOKMARKS,
FS_CATEGORY_RECENT,
+ /* For internal use, a list of known paths that are used to match paths to icons and names. */
+ FS_CATEGORY_OTHER,
} FSMenuCategory;
typedef enum FSMenuInsert {
@@ -200,4 +211,8 @@ void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name);
int ED_fsmenu_entry_get_icon(struct FSMenuEntry *fsentry);
void ED_fsmenu_entry_set_icon(struct FSMenuEntry *fsentry, const int icon);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_FILESELECT_H__ */
diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h
index e09f101af73..07eade23506 100644
--- a/source/blender/editors/include/ED_gizmo_library.h
+++ b/source/blender/editors/include/ED_gizmo_library.h
@@ -25,6 +25,10 @@
#ifndef __ED_GIZMO_LIBRARY_H__
#define __ED_GIZMO_LIBRARY_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* initialize gizmos */
void ED_gizmotypes_arrow_3d(void);
void ED_gizmotypes_button_2d(void);
@@ -237,4 +241,8 @@ void ED_gizmotypes_dial_3d_draw_util(const float matrix_basis[4][4],
const bool select,
struct Dial3dParams *params);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_GIZMO_LIBRARY_H__ */
diff --git a/source/blender/editors/include/ED_gizmo_utils.h b/source/blender/editors/include/ED_gizmo_utils.h
index 8c494bdf18c..70ff8a8d32f 100644
--- a/source/blender/editors/include/ED_gizmo_utils.h
+++ b/source/blender/editors/include/ED_gizmo_utils.h
@@ -23,6 +23,10 @@
#ifndef __ED_GIZMO_UTILS_H__
#define __ED_GIZMO_UTILS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct bContext;
struct wmGizmoGroupType;
@@ -39,4 +43,8 @@ bool ED_gizmo_poll_or_unlink_delayed_from_tool_ex(const struct bContext *C,
bool ED_gizmo_poll_or_unlink_delayed_from_tool(const struct bContext *C,
struct wmGizmoGroupType *gzgt);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_GIZMO_UTILS_H__ */
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 23dbf24ed7b..2dbd979564e 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -24,17 +24,23 @@
#ifndef __ED_GPENCIL_H__
#define __ED_GPENCIL_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ID;
struct ListBase;
struct PointerRNA;
struct Brush;
+struct GP_SpaceConversion;
struct bGPDframe;
struct bGPDlayer;
struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
struct tGPspoint;
+struct GpRandomSettings;
struct ARegion;
struct Depsgraph;
@@ -43,6 +49,8 @@ struct RegionView3D;
struct ReportList;
struct Scene;
struct ScrArea;
+struct SnapObjectContext;
+struct ToolSettings;
struct View3D;
struct ViewLayer;
struct bContext;
@@ -63,31 +71,17 @@ struct wmOperator;
* Used as part of the 'stroke cache' used during drawing of new strokes
*/
typedef struct tGPspoint {
- float x, y; /* x and y coordinates of cursor (in relative to area) */
- float pressure; /* pressure of tablet at this point */
- float strength; /* pressure of tablet at this point for alpha factor */
- float time; /* Time relative to stroke start (used when converting to path) */
- float uv_fac; /* factor of uv along the stroke */
- float uv_rot; /* uv rotation for dor mode */
- float rnd[3]; /* rnd value */
- bool rnd_dirty; /* rnd flag */
- short tflag; /* Internal flag */
+ float x, y; /* x and y coordinates of cursor (in relative to area) */
+ float pressure; /* pressure of tablet at this point */
+ float strength; /* pressure of tablet at this point for alpha factor */
+ float time; /* Time relative to stroke start (used when converting to path) */
+ float uv_fac; /* factor of uv along the stroke */
+ float uv_rot; /* uv rotation for dor mode */
+ float rnd[3]; /* rnd value */
+ bool rnd_dirty; /* rnd flag */
+ float vert_color[4]; /* Point vertex color. */
} tGPspoint;
-/* tGPspoint->flag */
-typedef enum etGPspoint_tFlag {
- /* Created by Fake event (used when mouse/pen move very fast while drawing). */
- GP_TPOINT_FAKE = (1 << 0),
-} etGPspoint_tFlag;
-
-/* used to sort by zdepth gpencil objects in viewport */
-/* TODO: this could be a system parameter in userprefs screen */
-#define GP_CACHE_BLOCK_SIZE 16
-typedef struct tGPencilSort {
- struct Base *base;
- float zdepth;
-} tGPencilSort;
-
/* ----------- Grease Pencil Tools/Context ------------- */
/* Context-dependent */
@@ -97,32 +91,30 @@ struct bGPdata *ED_gpencil_data_get_active(const struct bContext *C);
struct bGPdata *ED_gpencil_data_get_active_evaluated(const struct bContext *C);
/* Context independent (i.e. each required part is passed in instead) */
-struct bGPdata **ED_gpencil_data_get_pointers_direct(struct ScrArea *sa,
+struct bGPdata **ED_gpencil_data_get_pointers_direct(struct ScrArea *area,
struct Object *ob,
struct PointerRNA *r_ptr);
-struct bGPdata *ED_gpencil_data_get_active_direct(struct ScrArea *sa, struct Object *ob);
+struct bGPdata *ED_gpencil_data_get_active_direct(struct ScrArea *area, struct Object *ob);
struct bGPdata *ED_annotation_data_get_active(const struct bContext *C);
struct bGPdata **ED_annotation_data_get_pointers(const struct bContext *C,
struct PointerRNA *r_ptr);
struct bGPdata **ED_annotation_data_get_pointers_direct(struct ID *screen_id,
- struct ScrArea *sa,
+ struct ScrArea *area,
struct Scene *scene,
struct PointerRNA *r_ptr);
struct bGPdata *ED_annotation_data_get_active_direct(struct ID *screen_id,
- struct ScrArea *sa,
+ struct ScrArea *area,
struct Scene *scene);
bool ED_gpencil_data_owner_is_annotation(struct PointerRNA *owner_ptr);
/* 3D View */
-struct bGPdata *ED_gpencil_data_get_active_v3d(struct ViewLayer *view_layer, struct View3D *v3d);
-
bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfra);
/* ----------- Stroke Editing Utilities ---------------- */
-bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *sa, const struct bGPDstroke *gps);
+bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *area, const struct bGPDstroke *gps);
bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps);
bool ED_gpencil_stroke_color_use(struct Object *ob,
const struct bGPDlayer *gpl,
@@ -148,7 +140,7 @@ void ED_annotation_draw_view2d(const struct bContext *C, bool onlyv2d);
void ED_annotation_draw_view3d(struct Scene *scene,
struct Depsgraph *depsgraph,
struct View3D *v3d,
- struct ARegion *ar,
+ struct ARegion *region,
bool only3d);
void ED_annotation_draw_ex(struct Scene *scene,
struct bGPdata *gpd,
@@ -189,7 +181,11 @@ bool ED_gpencil_anim_copybuf_paste(struct bAnimContext *ac, const short copy_mod
int ED_gpencil_session_active(void);
int ED_undo_gpencil_step(struct bContext *C, int step, const char *name);
-/* ------------ Grease-Pencil Armature weights ------------------ */
+/* ------------ Grease-Pencil Armature ------------------ */
+bool ED_gpencil_add_armature(const struct bContext *C,
+ struct ReportList *reports,
+ struct Object *ob,
+ struct Object *ob_arm);
bool ED_gpencil_add_armature_weights(const struct bContext *C,
struct ReportList *reports,
struct Object *ob,
@@ -208,12 +204,6 @@ bool ED_gpencil_add_lattice_modifier(const struct bContext *C,
/* ------------ Transformation Utilities ------------ */
-/* get difference matrix */
-void ED_gpencil_parent_location(const struct Depsgraph *depsgraph,
- struct Object *obact,
- struct bGPdata *gpd,
- struct bGPDlayer *gpl,
- float diff_mat[4][4]);
/* reset parent matrix for all layers */
void ED_gpencil_reset_layers_parent(struct Depsgraph *depsgraph,
struct Object *obact,
@@ -229,7 +219,6 @@ void ED_gpencil_create_stroke(struct bContext *C, struct Object *ob, float mat[4
/* ------------ Object Utilities ------------ */
struct Object *ED_gpencil_add_object(struct bContext *C,
- struct Scene *scene,
const float loc[3],
unsigned short local_view_bits);
void ED_gpencil_add_defaults(struct bContext *C, struct Object *ob);
@@ -249,11 +238,10 @@ void ED_gp_project_point_to_plane(const struct Scene *scene,
const float origin[3],
const int axis,
struct bGPDspoint *pt);
-void ED_gp_get_drawing_reference(const struct Scene *scene,
- const struct Object *ob,
- struct bGPDlayer *gpl,
- char align_flag,
- float vec[3]);
+void ED_gpencil_drawing_reference_get(const struct Scene *scene,
+ const struct Object *ob,
+ char align_flag,
+ float vec[3]);
void ED_gpencil_project_stroke_to_view(struct bContext *C,
struct bGPDlayer *gpl,
struct bGPDstroke *gps);
@@ -271,11 +259,10 @@ void ED_gpencil_vgroup_deselect(struct bContext *C, struct Object *ob);
int ED_gpencil_join_objects_exec(struct bContext *C, struct wmOperator *op);
/* texture coordinate utilities */
-void ED_gpencil_tpoint_to_point(struct ARegion *ar,
+void ED_gpencil_tpoint_to_point(struct ARegion *region,
float origin[3],
const struct tGPspoint *tpt,
struct bGPDspoint *pt);
-void ED_gpencil_calc_stroke_uv(struct Object *ob, struct bGPDstroke *gps);
void ED_gpencil_update_color_uv(struct Main *bmain, struct Material *mat);
/* extend selection to stroke intersections
@@ -301,7 +288,38 @@ struct tGPspoint *ED_gpencil_sbuffer_ensure(struct tGPspoint *buffer_array,
int *buffer_size,
int *buffer_used,
const bool clear);
+void ED_gpencil_sbuffer_update_eval(struct bGPdata *gpd, struct Object *ob_eval);
+
/* Tag all scene grease pencil object to update. */
void ED_gpencil_tag_scene_gpencil(struct Scene *scene);
+/* Vertex color set. */
+void ED_gpencil_fill_vertex_color_set(struct ToolSettings *ts,
+ struct Brush *brush,
+ struct bGPDstroke *gps);
+void ED_gpencil_point_vertex_color_set(struct ToolSettings *ts,
+ struct Brush *brush,
+ struct bGPDspoint *pt,
+ struct tGPspoint *tpt);
+void ED_gpencil_sbuffer_vertex_color_set(struct Depsgraph *depsgraph,
+ struct Object *ob,
+ struct ToolSettings *ts,
+ struct Brush *brush,
+ struct Material *material,
+ float random_color[3],
+ float pen_pressure);
+void ED_gpencil_init_random_settings(struct Brush *brush,
+ const int mval[2],
+ struct GpRandomSettings *random_settings);
+
+bool ED_gpencil_stroke_check_collision(struct GP_SpaceConversion *gsc,
+ struct bGPDstroke *gps,
+ float mouse[2],
+ const int radius,
+ const float diff_mat[4][4]);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_GPENCIL_H__ */
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index e6d8684a8b2..a8476e3d1ca 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -24,15 +24,25 @@
#ifndef __ED_IMAGE_H__
#define __ED_IMAGE_H__
+#include "DNA_listBase.h"
+#include "DNA_space_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegion;
struct ImBuf;
struct Image;
struct ImageUser;
+struct LinkNodePair;
+struct Main;
struct ReportList;
struct Scene;
struct SpaceImage;
struct ViewLayer;
struct bContext;
+struct wmOperator;
struct wmWindowManager;
/* image_edit.c, exported for transform */
@@ -47,21 +57,22 @@ struct Mask *ED_space_image_get_mask(struct SpaceImage *sima);
void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sima, struct Mask *mask);
bool ED_space_image_color_sample(struct SpaceImage *sima,
- struct ARegion *ar,
+ struct ARegion *region,
int mval[2],
float r_col[3]);
struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock, int tile);
+int ED_space_image_get_display_channel_mask(struct ImBuf *ibuf);
void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock);
bool ED_space_image_has_buffer(struct SpaceImage *sima);
-void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height);
-void ED_space_image_get_size_fl(struct SpaceImage *sima, float size[2]);
-void ED_space_image_get_aspect(struct SpaceImage *sima, float *aspx, float *aspy);
+void ED_space_image_get_size(struct SpaceImage *sima, int *r_width, int *r_height);
+void ED_space_image_get_size_fl(struct SpaceImage *sima, float r_size[2]);
+void ED_space_image_get_aspect(struct SpaceImage *sima, float *r_aspx, float *r_aspy);
void ED_space_image_get_zoom(struct SpaceImage *sima,
- struct ARegion *ar,
- float *zoomx,
- float *zoomy);
-void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *aspx, float *aspy);
+ const struct ARegion *region,
+ float *r_zoomx,
+ float *r_zoomy);
+void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *r_aspx, float *r_aspy);
void ED_space_image_scopes_update(const struct bContext *C,
struct SpaceImage *sima,
@@ -72,16 +83,23 @@ void ED_space_image_paint_update(struct Main *bmain,
struct wmWindowManager *wm,
struct Scene *scene);
-void ED_image_get_uv_aspect(struct Image *ima, struct ImageUser *iuser, float *aspx, float *aspy);
+void ED_image_get_uv_aspect(struct Image *ima,
+ struct ImageUser *iuser,
+ float *r_aspx,
+ float *r_aspy);
void ED_image_mouse_pos(struct SpaceImage *sima,
- struct ARegion *ar,
+ const struct ARegion *region,
const int mval[2],
float co[2]);
void ED_image_view_center_to_point(struct SpaceImage *sima, float x, float y);
-void ED_image_point_pos(
- struct SpaceImage *sima, struct ARegion *ar, float x, float y, float *xr, float *yr);
+void ED_image_point_pos(struct SpaceImage *sima,
+ const struct ARegion *region,
+ float x,
+ float y,
+ float *r_x,
+ float *r_y);
void ED_image_point_pos__reverse(struct SpaceImage *sima,
- struct ARegion *ar,
+ const struct ARegion *region,
const float co[2],
float r_co[2]);
bool ED_image_slot_cycle(struct Image *image, int direction);
@@ -98,7 +116,7 @@ bool ED_space_image_maskedit_mask_poll(struct bContext *C);
bool ED_space_image_cursor_poll(struct bContext *C);
void ED_image_draw_info(struct Scene *scene,
- struct ARegion *ar,
+ struct ARegion *region,
bool color_manage,
bool use_default_view,
int channels,
@@ -112,8 +130,32 @@ void ED_image_draw_info(struct Scene *scene,
bool ED_space_image_show_cache(struct SpaceImage *sima);
-bool ED_image_should_save_modified(const struct bContext *C);
-int ED_image_save_all_modified_info(const struct bContext *C, struct ReportList *reports);
+bool ED_image_should_save_modified(const struct Main *bmain);
+int ED_image_save_all_modified_info(const struct Main *bmain, struct ReportList *reports);
bool ED_image_save_all_modified(const struct bContext *C, struct ReportList *reports);
+/* image_sequence.c */
+typedef struct ImageFrameRange {
+ struct ImageFrameRange *next, *prev;
+
+ /** Absolute file path of the first file in the range. */
+ char filepath[FILE_MAX];
+ /* Sequence parameters. */
+ int length;
+ int offset;
+ /* UDIM tiles. */
+ ListBase udim_tiles;
+
+ /* Temporary data. */
+ ListBase frames;
+} ImageFrameRange;
+
+ListBase ED_image_filesel_detect_sequences(struct Main *bmain,
+ struct wmOperator *op,
+ const bool detect_udim);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_IMAGE_H__ */
diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h
index 8a84d3646f8..1146c49bef2 100644
--- a/source/blender/editors/include/ED_info.h
+++ b/source/blender/editors/include/ED_info.h
@@ -23,12 +23,20 @@
#ifndef __ED_INFO_H__
#define __ED_INFO_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Main;
/* info_stats.c */
void ED_info_stats_clear(struct ViewLayer *view_layer);
-const char *ED_info_stats_string(struct Main *bmain,
- struct Scene *scene,
- struct ViewLayer *view_layer);
+const char *ED_info_footer_string(struct ViewLayer *view_layer);
+void ED_info_draw_stats(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* __ED_INFO_H__ */
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index 2630feaa9d3..7000075d4b5 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -24,6 +24,10 @@
#ifndef __ED_KEYFRAMES_DRAW_H__
#define __ED_KEYFRAMES_DRAW_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct AnimData;
struct CacheFile;
struct DLRBT_Tree;
@@ -266,4 +270,8 @@ bool actkeyblock_is_valid(ActKeyColumn *ab);
/* Checks if ActKeyColumn can be used as a block (i.e. drawn/used to detect "holds") */
int actkeyblock_get_valid_hold(ActKeyColumn *ab);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_KEYFRAMES_DRAW_H__ */
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index c347d75fa66..28bc0b22790 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -24,6 +24,12 @@
#ifndef __ED_KEYFRAMES_EDIT_H__
#define __ED_KEYFRAMES_EDIT_H__
+#include "ED_anim_api.h" /* for enum eAnimFilter_Flags */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct BezTriple;
struct FCurve;
struct Scene;
@@ -100,8 +106,8 @@ typedef enum eEditKeyframes_Mirror {
typedef struct KeyframeEdit_LassoData {
rctf *rectf_scaled;
const rctf *rectf_view;
- const int (*mcords)[2];
- int mcords_tot;
+ const int (*mcoords)[2];
+ int mcoords_len;
} KeyframeEdit_LassoData;
/* use with BEZT_OK_REGION_CIRCLE */
@@ -247,6 +253,12 @@ short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked,
KeyframeEditFunc key_cb,
FcuEditFunc fcu_cb);
+/* Calls callback_fn() for each keyframe in each fcurve in the filtered animation context.
+ * Assumes the callback updates keys. */
+void ANIM_animdata_keyframe_callback(struct bAnimContext *ac,
+ eAnimFilter_Flags filter,
+ KeyframeEditFunc callback_fn);
+
/* functions for making sure all keyframes are in good order */
void ANIM_editkeyframes_refresh(struct bAnimContext *ac);
@@ -325,4 +337,8 @@ short paste_animedit_keys(struct bAnimContext *ac,
/* ************************************************ */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_KEYFRAMES_EDIT_H__ */
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index ac3007afe5d..5635ef2800a 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -24,6 +24,9 @@
#ifndef __ED_KEYFRAMING_H__
#define __ED_KEYFRAMING_H__
+#include "DNA_anim_types.h"
+#include "RNA_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -50,33 +53,33 @@ struct PropertyRNA;
struct NlaKeyframingContext;
-#include "DNA_anim_types.h"
-#include "RNA_types.h"
-
/* ************ Keyframing Management **************** */
/* Get the active settings for keyframing settings from context (specifically the given scene)
- * - incl_mode: include settings from keyframing mode in the result (i.e. replace only)
+ * - use_autokey_mode: include settings from keyframing mode in the result (i.e. replace only).
*/
-short ANIM_get_keyframing_flags(struct Scene *scene, short incl_mode);
+eInsertKeyFlags ANIM_get_keyframing_flags(struct Scene *scene, const bool use_autokey_mode);
/* -------- */
/* Get (or add relevant data to be able to do so) the Active Action for the given
* Animation Data block, given an ID block where the Animation Data should reside.
*/
-struct bAction *verify_adt_action(struct Main *bmain, struct ID *id, short add);
+struct bAction *ED_id_action_ensure(struct Main *bmain, struct ID *id);
/* Get (or add relevant data to be able to do so) F-Curve from the given Action.
* This assumes that all the destinations are valid.
*/
-struct FCurve *verify_fcurve(struct Main *bmain,
- struct bAction *act,
- const char group[],
- struct PointerRNA *ptr,
- const char rna_path[],
- const int array_index,
- short add);
+struct FCurve *ED_action_fcurve_ensure(struct Main *bmain,
+ struct bAction *act,
+ const char group[],
+ struct PointerRNA *ptr,
+ const char rna_path[],
+ const int array_index);
+
+struct FCurve *ED_action_fcurve_find(struct bAction *act,
+ const char rna_path[],
+ const int array_index);
/* -------- */
@@ -126,30 +129,28 @@ bool insert_keyframe_direct(struct ReportList *reports,
* Use this to create any necessary animation data, and then insert a keyframe
* using the current value being keyframed, in the relevant place. Returns success.
*/
-short insert_keyframe(struct Main *bmain,
- struct ReportList *reports,
- struct ID *id,
- struct bAction *act,
- const char group[],
- const char rna_path[],
- int array_index,
- float cfra,
- eBezTriple_KeyframeType keytype,
- struct ListBase *nla_cache,
- eInsertKeyFlags flag);
+int insert_keyframe(struct Main *bmain,
+ struct ReportList *reports,
+ struct ID *id,
+ struct bAction *act,
+ const char group[],
+ const char rna_path[],
+ int array_index,
+ float cfra,
+ eBezTriple_KeyframeType keytype,
+ struct ListBase *nla_cache,
+ eInsertKeyFlags flag);
/* Main Keyframing API call:
* Use this to delete keyframe on current frame for relevant channel.
* Will perform checks just in case. */
-short delete_keyframe(struct Main *bmain,
- struct ReportList *reports,
- struct ID *id,
- struct bAction *act,
- const char group[],
- const char rna_path[],
- int array_index,
- float cfra,
- eInsertKeyFlags flag);
+int delete_keyframe(struct Main *bmain,
+ struct ReportList *reports,
+ struct ID *id,
+ struct bAction *act,
+ const char rna_path[],
+ int array_index,
+ float cfra);
/* ************ Keying Sets ********************** */
@@ -197,7 +198,7 @@ typedef struct KeyingSetInfo {
cbKeyingSet_Generate generate;
/* RNA integration */
- struct ExtensionRNA ext;
+ struct ExtensionRNA rna_ext;
} KeyingSetInfo;
/* -------- */
@@ -224,7 +225,9 @@ typedef enum eModifyKey_Returns {
/* poll the current KeyingSet, updating it's set of paths
* (if "builtin"/"relative") for context changes */
-short ANIM_validate_keyingset(struct bContext *C, ListBase *dsources, struct KeyingSet *ks);
+eModifyKey_Returns ANIM_validate_keyingset(struct bContext *C,
+ ListBase *dsources,
+ struct KeyingSet *ks);
/* use the specified KeyingSet to add/remove various Keyframes on the specified frame */
int ANIM_apply_keyingset(struct bContext *C,
@@ -256,13 +259,13 @@ void ANIM_keyingset_infos_exit(void);
/* -------- */
/* Get the active KeyingSet for the given scene */
-struct KeyingSet *ANIM_scene_get_active_keyingset(struct Scene *scene);
+struct KeyingSet *ANIM_scene_get_active_keyingset(const struct Scene *scene);
/* Get the index of the Keying Set provided, for the given Scene */
int ANIM_scene_get_keyingset_index(struct Scene *scene, struct KeyingSet *ks);
/* Get Keying Set to use for Auto-Keyframing some transforms */
-struct KeyingSet *ANIM_get_keyingset_for_autokeying(struct Scene *scene,
+struct KeyingSet *ANIM_get_keyingset_for_autokeying(const struct Scene *scene,
const char *tranformKSName);
/* Dynamically populate an enum of Keying Sets */
@@ -427,19 +430,19 @@ void ANIM_copy_as_driver(struct ID *target_id, const char *target_path, const ch
/* Auto-Keying macros for use by various tools */
/* check if auto-keyframing is enabled (per scene takes precedence) */
#define IS_AUTOKEY_ON(scene) \
- ((scene) ? (scene->toolsettings->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
+ ((scene) ? ((scene)->toolsettings->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
/* check the mode for auto-keyframing (per scene takes precedence) */
#define IS_AUTOKEY_MODE(scene, mode) \
- ((scene) ? (scene->toolsettings->autokey_mode == AUTOKEY_MODE_##mode) : \
+ ((scene) ? ((scene)->toolsettings->autokey_mode == AUTOKEY_MODE_##mode) : \
(U.autokey_mode == AUTOKEY_MODE_##mode))
/* check if a flag is set for auto-keyframing (per scene takes precedence) */
#define IS_AUTOKEY_FLAG(scene, flag) \
- ((scene) ? ((scene->toolsettings->autokey_flag & AUTOKEY_FLAG_##flag) || \
+ ((scene) ? (((scene)->toolsettings->autokey_flag & AUTOKEY_FLAG_##flag) || \
(U.autokey_flag & AUTOKEY_FLAG_##flag)) : \
(U.autokey_flag & AUTOKEY_FLAG_##flag))
/* auto-keyframing feature - checks for whether anything should be done for the current frame */
-bool autokeyframe_cfra_can_key(struct Scene *scene, struct ID *id);
+bool autokeyframe_cfra_can_key(const struct Scene *scene, struct ID *id);
/* ************ Keyframe Checking ******************** */
diff --git a/source/blender/editors/include/ED_lattice.h b/source/blender/editors/include/ED_lattice.h
index 5c3c3555d56..2e4b9472ce7 100644
--- a/source/blender/editors/include/ED_lattice.h
+++ b/source/blender/editors/include/ED_lattice.h
@@ -24,6 +24,10 @@
#ifndef __ED_LATTICE_H__
#define __ED_LATTICE_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Base;
struct Object;
struct UndoType;
@@ -44,4 +48,8 @@ bool ED_lattice_deselect_all_multi(struct bContext *C);
/* editlattice_undo.c */
void ED_lattice_undosys_type(struct UndoType *ut);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_LATTICE_H__ */
diff --git a/source/blender/editors/include/ED_logic.h b/source/blender/editors/include/ED_logic.h
index 8158bee15f3..ae2d5038321 100644
--- a/source/blender/editors/include/ED_logic.h
+++ b/source/blender/editors/include/ED_logic.h
@@ -24,7 +24,15 @@
#ifndef __ED_LOGIC_H__
#define __ED_LOGIC_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* logic_ops.c */
void ED_operatortypes_logic(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_LOGIC_H__ */
diff --git a/source/blender/editors/include/ED_markers.h b/source/blender/editors/include/ED_markers.h
index a9e57ecc13d..54a5d0cb0e1 100644
--- a/source/blender/editors/include/ED_markers.h
+++ b/source/blender/editors/include/ED_markers.h
@@ -24,6 +24,10 @@
#ifndef __ED_MARKERS_H__
#define __ED_MARKERS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Scene;
struct TimeMarker;
struct bAnimContext;
@@ -70,4 +74,8 @@ void ED_keymap_marker(struct wmKeyConfig *keyconf);
/* debugging only */
void debug_markers_print_list(struct ListBase *markers);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_MARKERS_H__ */
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index f4725fea039..5aafc0702da 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -24,6 +24,10 @@
#ifndef __ED_MASK_H__
#define __ED_MASK_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Depsgraph;
struct KeyframeEditData;
struct MaskLayer;
@@ -32,35 +36,39 @@ struct bContext;
struct wmKeyConfig;
/* mask_edit.c */
-void ED_mask_get_size(struct ScrArea *sa, int *width, int *height);
-void ED_mask_zoom(struct ScrArea *sa, struct ARegion *ar, float *zoomx, float *zoomy);
-void ED_mask_get_aspect(struct ScrArea *sa, struct ARegion *ar, float *aspx, float *aspy);
+void ED_mask_deselect_all(const struct bContext *C);
+
+void ED_operatortypes_mask(void);
+void ED_keymap_mask(struct wmKeyConfig *keyconf);
+void ED_operatormacros_mask(void);
+
+/* mask_query.c */
+void ED_mask_get_size(struct ScrArea *area, int *width, int *height);
+void ED_mask_zoom(struct ScrArea *area, struct ARegion *region, float *zoomx, float *zoomy);
+void ED_mask_get_aspect(struct ScrArea *area, struct ARegion *region, float *aspx, float *aspy);
-void ED_mask_pixelspace_factor(struct ScrArea *sa,
- struct ARegion *ar,
+void ED_mask_pixelspace_factor(struct ScrArea *area,
+ struct ARegion *region,
float *scalex,
float *scaley);
-void ED_mask_mouse_pos(struct ScrArea *sa, struct ARegion *ar, const int mval[2], float co[2]);
+void ED_mask_mouse_pos(struct ScrArea *area,
+ struct ARegion *region,
+ const int mval[2],
+ float co[2]);
void ED_mask_point_pos(
- struct ScrArea *sa, struct ARegion *ar, float x, float y, float *xr, float *yr);
+ struct ScrArea *area, struct ARegion *region, float x, float y, float *xr, float *yr);
void ED_mask_point_pos__reverse(
- struct ScrArea *sa, struct ARegion *ar, float x, float y, float *xr, float *yr);
+ struct ScrArea *area, struct ARegion *region, float x, float y, float *xr, float *yr);
-void ED_mask_cursor_location_get(struct ScrArea *sa, float cursor[2]);
+void ED_mask_cursor_location_get(struct ScrArea *area, float cursor[2]);
bool ED_mask_selected_minmax(const struct bContext *C, float min[2], float max[2]);
-void ED_mask_deselect_all(const struct bContext *C);
-
-void ED_operatortypes_mask(void);
-void ED_keymap_mask(struct wmKeyConfig *keyconf);
-void ED_operatormacros_mask(void);
-
/* mask_draw.c */
void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type);
void ED_mask_draw_region(struct Depsgraph *depsgraph,
struct Mask *mask,
- struct ARegion *ar,
+ struct ARegion *region,
const char draw_flag,
const char draw_type,
const char overlay_mode,
@@ -74,7 +82,7 @@ void ED_mask_draw_region(struct Depsgraph *depsgraph,
const struct bContext *C);
void ED_mask_draw_frames(
- struct Mask *mask, struct ARegion *ar, const int cfra, const int sfra, const int efra);
+ struct Mask *mask, struct ARegion *region, const int cfra, const int sfra, const int efra);
/* mask_shapekey.c */
void ED_mask_layer_shape_auto_key(struct MaskLayer *mask_layer, const int frame);
@@ -114,4 +122,8 @@ void paste_gpdata(void);
void mirror_masklayer_frames(struct MaskLayer *mask_layer, short mode);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_MASK_H__ */
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index 8ffae0f2b66..4ecf97108e8 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -24,6 +24,10 @@
#ifndef __ED_MBALL_H__
#define __ED_MBALL_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Base;
struct Object;
struct UndoType;
@@ -56,4 +60,8 @@ void ED_mball_undosys_type(struct UndoType *ut);
#define MBALL_NOSEL (1u << 31u)
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_MBALL_H__ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 95d6d5cab3b..20e54df1ccb 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -135,10 +135,16 @@ void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag);
bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
struct BMEdge *e,
struct Depsgraph *depsgraph,
- struct ARegion *ar,
+ struct ARegion *region,
struct View3D *v3d,
struct Object *obedit);
+void EDBM_project_snap_verts(struct bContext *C,
+ struct Depsgraph *depsgraph,
+ struct ARegion *region,
+ struct Object *obedit,
+ struct BMEditMesh *em);
+
/* editmesh_automerge.c */
void EDBM_automerge(struct Object *ob, bool update, const char hflag, const float dist);
void EDBM_automerge_and_split(struct Object *ob,
@@ -293,13 +299,6 @@ void ED_operatortypes_mesh(void);
void ED_operatormacros_mesh(void);
void ED_keymap_mesh(struct wmKeyConfig *keyconf);
-/* editmesh_tools.c (could be moved) */
-void EDBM_project_snap_verts(struct bContext *C,
- struct Depsgraph *depsgraph,
- struct ARegion *ar,
- struct Object *obedit,
- struct BMEditMesh *em);
-
/* editface.c */
void paintface_flush_flags(struct bContext *C, struct Object *ob, short flag);
bool paintface_mouse_select(struct bContext *C,
@@ -450,9 +449,19 @@ int join_mesh_exec(struct bContext *C, struct wmOperator *op);
int join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op);
/* mirror lookup api */
-int ED_mesh_mirror_spatial_table(
- struct Object *ob, struct BMEditMesh *em, struct Mesh *me_eval, const float co[3], char mode);
-int ED_mesh_mirror_topo_table(struct Object *ob, struct Mesh *me_eval, char mode);
+/* Spatial Mirror */
+void ED_mesh_mirror_spatial_table_begin(struct Object *ob,
+ struct BMEditMesh *em,
+ struct Mesh *me_eval);
+void ED_mesh_mirror_spatial_table_end(struct Object *ob);
+int ED_mesh_mirror_spatial_table_lookup(struct Object *ob,
+ struct BMEditMesh *em,
+ struct Mesh *me_eval,
+ const float co[3]);
+
+/* Topology Mirror */
+void ED_mesh_mirror_topo_table_begin(struct Object *ob, struct Mesh *me_eval);
+void ED_mesh_mirror_topo_table_end(struct Object *ob);
/* retrieves mirrored cache vert, or NULL if there isn't one.
* note: calling this without ensuring the mirror cache state
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index d2d8972c245..1dc98cfee2f 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -24,6 +24,10 @@
#ifndef __ED_NODE_H__
#define __ED_NODE_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ID;
struct Main;
struct Scene;
@@ -33,6 +37,7 @@ struct Tex;
struct View2D;
struct bContext;
struct bNode;
+struct bNodeSocket;
struct bNodeSocketType;
struct bNodeTree;
struct bNodeTree;
@@ -72,9 +77,13 @@ void ED_init_standard_node_socket_type(struct bNodeSocketType *stype);
void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype);
void ED_node_sample_set(const float col[4]);
void ED_node_draw_snap(
- struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos);
+ struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned int pos);
/* node_draw.c */
+void ED_node_socket_draw(struct bNodeSocket *sock,
+ const struct rcti *rect,
+ const float color[4],
+ float scale);
void ED_node_tree_update(const struct bContext *C);
void ED_node_tag_update_id(struct ID *id);
void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
@@ -82,14 +91,15 @@ void ED_node_sort(struct bNodeTree *ntree);
float ED_node_grid_size(void);
/* node_relationships.c */
-void ED_node_link_intersect_test(struct ScrArea *sa, int test);
-void ED_node_link_insert(struct Main *bmain, struct ScrArea *sa);
+void ED_node_link_intersect_test(struct ScrArea *area, int test);
+void ED_node_link_insert(struct Main *bmain, struct ScrArea *area);
/* node_edit.c */
void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo);
bool ED_node_is_compositor(struct SpaceNode *snode);
bool ED_node_is_shader(struct SpaceNode *snode);
bool ED_node_is_texture(struct SpaceNode *snode);
+bool ED_node_is_simulation(struct SpaceNode *snode);
void ED_node_shader_default(const struct bContext *C, struct ID *id);
void ED_node_composit_default(const struct bContext *C, struct Scene *scene);
@@ -107,7 +117,14 @@ void ED_node_composite_job(const struct bContext *C,
void ED_operatormacros_node(void);
/* node_view.c */
-bool ED_space_node_color_sample(
- struct Main *bmain, struct SpaceNode *snode, struct ARegion *ar, int mval[2], float r_col[3]);
+bool ED_space_node_color_sample(struct Main *bmain,
+ struct SpaceNode *snode,
+ struct ARegion *region,
+ int mval[2],
+ float r_col[3]);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* __ED_NODE_H__ */
diff --git a/source/blender/editors/include/ED_numinput.h b/source/blender/editors/include/ED_numinput.h
index b13f228b1ec..8c8f3e6f4a3 100644
--- a/source/blender/editors/include/ED_numinput.h
+++ b/source/blender/editors/include/ED_numinput.h
@@ -21,6 +21,10 @@
#ifndef __ED_NUMINPUT_H__
#define __ED_NUMINPUT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define NUM_STR_REP_LEN 64
#define NUM_MAX_ELEMENTS 3
@@ -104,4 +108,8 @@ bool user_string_to_number(
/** \} */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_NUMINPUT_H__ */
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index d27eeb270ac..32e62a6436c 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -24,6 +24,9 @@
#ifndef __ED_OBJECT_H__
#define __ED_OBJECT_H__
+#include "BLI_compiler_attrs.h"
+#include "DNA_object_enums.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -54,9 +57,6 @@ struct wmOperator;
struct wmOperatorType;
struct wmWindowManager;
-#include "DNA_object_enums.h"
-#include "BLI_compiler_attrs.h"
-
/* object_edit.c */
/* context.object */
struct Object *ED_object_context(struct bContext *C);
@@ -73,6 +73,51 @@ bool ED_object_calc_active_center_for_posemode(struct Object *ob,
float r_center[3]);
bool ED_object_calc_active_center(struct Object *ob, const bool select_only, float r_center[3]);
+/* Object Data Container helper API. */
+struct XFormObjectData_Container;
+struct XFormObjectData_Container *ED_object_data_xform_container_create(void);
+void ED_object_data_xform_container_destroy(struct XFormObjectData_Container *xds);
+void ED_object_data_xform_container_update_all(struct XFormObjectData_Container *xds,
+ struct Main *bmain,
+ struct Depsgraph *depsgraph);
+void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container *xds,
+ struct Object *ob);
+
+/* Object Skip-Child Container helper API. */
+enum {
+ /**
+ * The parent is transformed, this is held in place.
+ */
+ XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM = 1,
+ /**
+ * The same as #XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM,
+ * however this objects parent isn't transformed directly.
+ */
+ XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT = 3,
+ /**
+ * Use the parent invert matrix to apply transformation,
+ * this is needed, because breaks in the selection chain prevents this from being transformed.
+ * This is used to add the transform which would have been added
+ * if there weren't breaks in the parent/child chain.
+ */
+ XFORM_OB_SKIP_CHILD_PARENT_APPLY = 2,
+};
+struct XFormObjectSkipChild_Container;
+struct XFormObjectSkipChild_Container *ED_object_xform_skip_child_container_create(void);
+void ED_object_xform_skip_child_container_item_ensure_from_array(
+ struct XFormObjectSkipChild_Container *xcs,
+ struct ViewLayer *view_layer,
+ struct Object **objects,
+ uint objects_len);
+void ED_object_xform_skip_child_container_destroy(struct XFormObjectSkipChild_Container *xcs);
+void ED_object_xform_skip_child_container_update_all(struct XFormObjectSkipChild_Container *xcs,
+ struct Main *bmain,
+ struct Depsgraph *depsgraph);
+void ED_object_xform_skip_child_container_item_ensure(struct XFormObjectSkipChild_Container *xcs,
+ struct Object *ob,
+ struct Object *ob_parent_recurse,
+ int mode);
+
/* object_ops.c */
void ED_operatortypes_object(void);
void ED_operatormacros_object(void);
@@ -101,6 +146,12 @@ typedef enum eObjectSelect_Mode {
BA_INVERT = 2,
} eObjectSelect_Mode;
+typedef enum eObClearParentTypes {
+ CLEAR_PARENT_ALL = 0,
+ CLEAR_PARENT_KEEP_TRANSFORM,
+ CLEAR_PARENT_INVERSE,
+} eObClearParentTypes;
+
#ifdef __RNA_TYPES_H__
extern struct EnumPropertyItem prop_clear_parent_types[];
extern struct EnumPropertyItem prop_make_parent_types[];
@@ -195,7 +246,7 @@ void ED_object_sculptmode_exit(struct bContext *C, struct Depsgraph *depsgraph);
void ED_object_location_from_view(struct bContext *C, float loc[3]);
void ED_object_rotation_from_quat(float rot[3], const float quat[4], const char align_axis);
void ED_object_rotation_from_view(struct bContext *C, float rot[3], const char align_axis);
-void ED_object_base_init_transform_on_add(struct Object *obejct,
+void ED_object_base_init_transform_on_add(struct Object *object,
const float loc[3],
const float rot[3]);
float ED_object_new_primitive_matrix(struct bContext *C,
@@ -317,13 +368,13 @@ int ED_object_modifier_convert(struct ReportList *reports,
struct ViewLayer *view_layer,
struct Object *ob,
struct ModifierData *md);
-int ED_object_modifier_apply(struct Main *bmain,
- struct ReportList *reports,
- struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct Object *ob,
- struct ModifierData *md,
- int mode);
+bool ED_object_modifier_apply(struct Main *bmain,
+ struct ReportList *reports,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct ModifierData *md,
+ int mode);
int ED_object_modifier_copy(struct ReportList *reports,
struct Object *ob,
struct ModifierData *md);
@@ -421,16 +472,6 @@ void ED_object_data_xform_by_mat4(struct XFormObjectData *xod, const float mat[4
void ED_object_data_xform_restore(struct XFormObjectData *xod);
void ED_object_data_xform_tag_update(struct XFormObjectData *xod);
-/* Container helper API. */
-struct XFormObjectData_Container;
-struct XFormObjectData_Container *ED_object_data_xform_container_create(void);
-void ED_object_data_xform_container_destroy(struct XFormObjectData_Container *xds);
-void ED_object_data_xform_container_update_all(struct XFormObjectData_Container *xds,
- struct Main *bmain,
- struct Depsgraph *depsgraph);
-void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container *xds,
- struct Object *ob);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h
index 3015d8d9cdc..d3fc5174dd9 100644
--- a/source/blender/editors/include/ED_outliner.h
+++ b/source/blender/editors/include/ED_outliner.h
@@ -23,6 +23,11 @@
#ifndef __ED_OUTLINER_H__
#define __ED_OUTLINER_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Base;
struct ListBase;
struct bContext;
@@ -30,7 +35,7 @@ bool ED_outliner_collections_editor_poll(struct bContext *C);
void ED_outliner_selected_objects_get(const struct bContext *C, struct ListBase *objects);
-Base *ED_outliner_give_base_under_cursor(struct bContext *C, const int mval[2]);
+struct Base *ED_outliner_give_base_under_cursor(struct bContext *C, const int mval[2]);
void ED_outliner_select_sync_from_object_tag(struct bContext *C);
void ED_outliner_select_sync_from_edit_bone_tag(struct bContext *C);
@@ -44,4 +49,8 @@ void ED_outliner_select_sync_from_outliner(struct bContext *C, struct SpaceOutli
void ED_outliner_select_sync_flag_outliners(const struct bContext *C);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_OUTLINER_H__ */
diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h
index e15e4c45c4a..4159f22703f 100644
--- a/source/blender/editors/include/ED_paint.h
+++ b/source/blender/editors/include/ED_paint.h
@@ -21,8 +21,13 @@
#ifndef __ED_PAINT_H__
#define __ED_PAINT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ImBuf;
struct Image;
+struct ImageUser;
struct UndoStep;
struct UndoType;
struct bContext;
@@ -38,7 +43,7 @@ void ED_keymap_paint(struct wmKeyConfig *keyconf);
void ED_imapaint_clear_partial_redraw(void);
void ED_imapaint_dirty_region(struct Image *ima,
struct ImBuf *ibuf,
- int tile_number,
+ struct ImageUser *iuser,
int x,
int y,
int w,
@@ -54,7 +59,7 @@ void ED_image_undo_push_begin(const char *name, int paint_mode);
void ED_image_undo_push_begin_with_image(const char *name,
struct Image *image,
struct ImBuf *ibuf,
- int tile_number);
+ struct ImageUser *iuser);
void ED_image_undo_push_end(void);
void ED_image_undo_restore(struct UndoStep *us);
@@ -64,7 +69,7 @@ void ED_image_undosys_type(struct UndoType *ut);
void *ED_image_paint_tile_find(struct ListBase *undo_tiles,
struct Image *ima,
struct ImBuf *ibuf,
- int tile_number,
+ struct ImageUser *iuser,
int x_tile,
int y_tile,
unsigned short **r_mask,
@@ -73,7 +78,7 @@ void *ED_image_paint_tile_push(struct ListBase *undo_tiles,
struct Image *ima,
struct ImBuf *ibuf,
struct ImBuf **tmpibuf,
- int tile_number,
+ struct ImageUser *iuser,
int x_tile,
int y_tile,
unsigned short **r_mask,
@@ -96,4 +101,8 @@ void ED_paintcurve_undo_push_end(void);
void ED_paintcurve_undosys_type(struct UndoType *ut);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_PAINT_H__ */
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index 0c973f4ca88..789db5ae56e 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -24,6 +24,10 @@
#ifndef __ED_PARTICLE_H__
#define __ED_PARTICLE_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Object;
struct PTCacheEdit;
struct ParticleEditSettings;
@@ -67,8 +71,8 @@ bool PE_mouse_particles(
bool PE_box_select(struct bContext *C, const struct rcti *rect, const int sel_op);
bool PE_circle_select(struct bContext *C, const int sel_op, const int mval[2], float rad);
int PE_lasso_select(struct bContext *C,
- const int mcords[][2],
- const short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const int sel_op);
bool PE_deselect_all_visible_ex(struct PTCacheEdit *edit);
bool PE_deselect_all_visible(struct bContext *C);
@@ -76,4 +80,8 @@ bool PE_deselect_all_visible(struct bContext *C);
/* particle_edit_undo.c */
void ED_particle_undosys_type(struct UndoType *ut);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_PARTICLE_H__ */
diff --git a/source/blender/editors/include/ED_physics.h b/source/blender/editors/include/ED_physics.h
index 1006a9d4f47..ebd7e387c83 100644
--- a/source/blender/editors/include/ED_physics.h
+++ b/source/blender/editors/include/ED_physics.h
@@ -24,6 +24,10 @@
#ifndef __ED_PHYSICS_H__
#define __ED_PHYSICS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ReportList;
struct bContext;
struct wmKeyConfig;
@@ -56,4 +60,8 @@ void ED_rigidbody_constraint_remove(struct Main *bmain, struct Scene *scene, str
void ED_operatortypes_physics(void);
void ED_keymap_physics(struct wmKeyConfig *keyconf);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_PHYSICS_H__ */
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index d36d2559f26..f03739c74c4 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -26,6 +26,10 @@
#include "DNA_vec_types.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct DEGEditorUpdateContext;
struct ID;
struct MTex;
@@ -44,8 +48,8 @@ void ED_operatortypes_render(void);
/* render_update.c */
void ED_render_engine_changed(struct Main *bmain);
-void ED_render_engine_area_exit(struct Main *bmain, struct ScrArea *sa);
-void ED_render_view_layer_changed(struct Main *bmain, struct bScreen *sc);
+void ED_render_engine_area_exit(struct Main *bmain, struct ScrArea *area);
+void ED_render_view_layer_changed(struct Main *bmain, struct bScreen *screen);
/* Callbacks handling data update events coming from depsgraph. */
@@ -103,4 +107,8 @@ void ED_render_clear_mtex_copybuf(void);
void ED_render_internal_init(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/source/blender/editors/include/ED_scene.h b/source/blender/editors/include/ED_scene.h
index 832f40d22aa..27c2e9d0df8 100644
--- a/source/blender/editors/include/ED_scene.h
+++ b/source/blender/editors/include/ED_scene.h
@@ -23,6 +23,10 @@
#include "BLI_compiler_attrs.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
enum eSceneCopyMethod;
struct Scene *ED_scene_add(struct Main *bmain,
@@ -39,4 +43,8 @@ bool ED_scene_view_layer_delete(struct Main *bmain,
void ED_operatortypes_scene(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_SCENE_H__ */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 9e0272d1402..43f3a578bfe 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -34,6 +34,10 @@
#include "BLI_compiler_attrs.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegion;
struct Depsgraph;
struct IDProperty;
@@ -59,75 +63,76 @@ struct wmWindowManager;
/* regions */
void ED_region_do_listen(struct wmWindow *win,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmNotifier *note,
const Scene *scene);
-void ED_region_do_layout(struct bContext *C, struct ARegion *ar);
-void ED_region_do_draw(struct bContext *C, struct ARegion *ar);
-void ED_region_exit(struct bContext *C, struct ARegion *ar);
-void ED_region_remove(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
-void ED_region_pixelspace(struct ARegion *ar);
-void ED_region_update_rect(struct ARegion *ar);
-void ED_region_floating_initialize(struct ARegion *ar);
-void ED_region_tag_redraw(struct ARegion *ar);
-void ED_region_tag_redraw_partial(struct ARegion *ar, const struct rcti *rct, bool rebuild);
-void ED_region_tag_redraw_overlay(struct ARegion *ar);
-void ED_region_tag_redraw_no_rebuild(struct ARegion *ar);
-void ED_region_tag_refresh_ui(struct ARegion *ar);
-
-void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar);
+void ED_region_do_layout(struct bContext *C, struct ARegion *region);
+void ED_region_do_draw(struct bContext *C, struct ARegion *region);
+void ED_region_exit(struct bContext *C, struct ARegion *region);
+void ED_region_remove(struct bContext *C, struct ScrArea *area, struct ARegion *region);
+void ED_region_pixelspace(struct ARegion *region);
+void ED_region_update_rect(struct ARegion *region);
+void ED_region_floating_initialize(struct ARegion *region);
+void ED_region_tag_redraw(struct ARegion *region);
+void ED_region_tag_redraw_partial(struct ARegion *region, const struct rcti *rct, bool rebuild);
+void ED_region_tag_redraw_cursor(struct ARegion *region);
+void ED_region_tag_redraw_no_rebuild(struct ARegion *region);
+void ED_region_tag_refresh_ui(struct ARegion *region);
+void ED_region_tag_redraw_editor_overlays(struct ARegion *region);
+
+void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *region);
void ED_region_panels_ex(const struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
const char *contexts[],
int contextnr,
const bool vertical);
-void ED_region_panels(const struct bContext *C, struct ARegion *ar);
+void ED_region_panels(const struct bContext *C, struct ARegion *region);
void ED_region_panels_layout_ex(const struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
struct ListBase *paneltypes,
const char *contexts[],
int contextnr,
const bool vertical,
const char *category_override);
-void ED_region_panels_layout(const struct bContext *C, struct ARegion *ar);
-void ED_region_panels_draw(const struct bContext *C, struct ARegion *ar);
+void ED_region_panels_layout(const struct bContext *C, struct ARegion *region);
+void ED_region_panels_draw(const struct bContext *C, struct ARegion *region);
-void ED_region_header_init(struct ARegion *ar);
-void ED_region_header(const struct bContext *C, struct ARegion *ar);
-void ED_region_header_layout(const struct bContext *C, struct ARegion *ar);
-void ED_region_header_draw(const struct bContext *C, struct ARegion *ar);
+void ED_region_header_init(struct ARegion *region);
+void ED_region_header(const struct bContext *C, struct ARegion *region);
+void ED_region_header_layout(const struct bContext *C, struct ARegion *region);
+void ED_region_header_draw(const struct bContext *C, struct ARegion *region);
-void ED_region_cursor_set(struct wmWindow *win, struct ScrArea *sa, struct ARegion *ar);
-void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar);
+void ED_region_cursor_set(struct wmWindow *win, struct ScrArea *area, struct ARegion *region);
+void ED_region_toggle_hidden(struct bContext *C, struct ARegion *region);
void ED_region_visibility_change_update(struct bContext *C,
- struct ScrArea *sa,
- struct ARegion *ar);
+ struct ScrArea *area,
+ struct ARegion *region);
/* screen_ops.c */
void ED_region_visibility_change_update_animated(struct bContext *C,
- struct ScrArea *sa,
- struct ARegion *ar);
+ struct ScrArea *area,
+ struct ARegion *region);
-void ED_region_info_draw(struct ARegion *ar,
+void ED_region_info_draw(struct ARegion *region,
const char *text,
float fill_color[4],
const bool full_redraw);
-void ED_region_info_draw_multiline(ARegion *ar,
+void ED_region_info_draw_multiline(ARegion *region,
const char *text_array[],
float fill_color[4],
const bool full_redraw);
void ED_region_image_metadata_draw(
int x, int y, struct ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy);
void ED_region_image_metadata_panel_draw(struct ImBuf *ibuf, struct uiLayout *layout);
-void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy, float x0, float y0);
-float ED_region_blend_alpha(struct ARegion *ar);
-void ED_region_visible_rect_calc(struct ARegion *ar, struct rcti *rect);
-const rcti *ED_region_visible_rect(ARegion *ar);
+void ED_region_grid_draw(struct ARegion *region, float zoomx, float zoomy, float x0, float y0);
+float ED_region_blend_alpha(struct ARegion *region);
+void ED_region_visible_rect_calc(struct ARegion *region, struct rcti *rect);
+const rcti *ED_region_visible_rect(ARegion *region);
bool ED_region_is_overlap(int spacetype, int regiontype);
-int ED_region_snap_size_test(const struct ARegion *ar);
-bool ED_region_snap_size_apply(struct ARegion *ar, int snap_flag);
+int ED_region_snap_size_test(const struct ARegion *region);
+bool ED_region_snap_size_apply(struct ARegion *region, int snap_flag);
/* message_bus callbacks */
void ED_region_do_msg_notify_tag_redraw(struct bContext *C,
@@ -141,15 +146,15 @@ void ED_area_do_mgs_subscribe_for_tool_header(const struct bContext *C,
struct WorkSpace *workspace,
struct Scene *scene,
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus);
void ED_area_do_mgs_subscribe_for_tool_ui(const struct bContext *C,
struct WorkSpace *workspace,
struct Scene *scene,
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus);
/* message bus */
@@ -157,8 +162,8 @@ void ED_region_message_subscribe(struct bContext *C,
struct WorkSpace *workspace,
struct Scene *scene,
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus);
/* spaces */
@@ -166,21 +171,21 @@ void ED_spacetypes_keymap(struct wmKeyConfig *keyconf);
int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco);
/* areas */
-void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa);
-void ED_area_exit(struct bContext *C, struct ScrArea *sa);
+void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *area);
+void ED_area_exit(struct bContext *C, struct ScrArea *area);
int ED_screen_area_active(const struct bContext *C);
void ED_screen_global_areas_refresh(struct wmWindow *win);
void ED_screen_global_areas_sync(struct wmWindow *win);
-void ED_area_do_listen(struct wmWindow *win, ScrArea *sa, struct wmNotifier *note, Scene *scene);
-void ED_area_tag_redraw(ScrArea *sa);
-void ED_area_tag_redraw_no_rebuild(ScrArea *sa);
-void ED_area_tag_redraw_regiontype(ScrArea *sa, int type);
-void ED_area_tag_refresh(ScrArea *sa);
-void ED_area_do_refresh(struct bContext *C, ScrArea *sa);
-struct AZone *ED_area_azones_update(ScrArea *sa, const int mouse_xy[]);
-void ED_area_status_text(ScrArea *sa, const char *str);
-void ED_area_newspace(struct bContext *C, ScrArea *sa, int type, const bool skip_ar_exit);
-void ED_area_prevspace(struct bContext *C, ScrArea *sa);
+void ED_area_do_listen(struct wmWindow *win, ScrArea *area, struct wmNotifier *note, Scene *scene);
+void ED_area_tag_redraw(ScrArea *area);
+void ED_area_tag_redraw_no_rebuild(ScrArea *area);
+void ED_area_tag_redraw_regiontype(ScrArea *area, int type);
+void ED_area_tag_refresh(ScrArea *area);
+void ED_area_do_refresh(struct bContext *C, ScrArea *area);
+struct AZone *ED_area_azones_update(ScrArea *area, const int mouse_xy[]);
+void ED_area_status_text(ScrArea *area, const char *str);
+void ED_area_newspace(struct bContext *C, ScrArea *area, int type, const bool skip_region_exit);
+void ED_area_prevspace(struct bContext *C, ScrArea *area);
void ED_area_swapspace(struct bContext *C, ScrArea *sa1, ScrArea *sa2);
int ED_area_headersize(void);
int ED_area_header_alignment_or_fallback(const ScrArea *area, int fallback);
@@ -210,7 +215,7 @@ ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area);
#define ED_screen_verts_iter(win, screen, vert_name) \
for (ScrVert *vert_name = (win)->global_areas.vertbase.first ? \
(win)->global_areas.vertbase.first : \
- screen->vertbase.first; \
+ (screen)->vertbase.first; \
vert_name != NULL; \
vert_name = (vert_name == (win)->global_areas.vertbase.last) ? (screen)->vertbase.first : \
vert_name->next)
@@ -219,25 +224,25 @@ ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area);
void ED_screens_initialize(struct Main *bmain, struct wmWindowManager *wm);
void ED_screen_draw_edges(struct wmWindow *win);
void ED_screen_draw_join_shape(struct ScrArea *sa1, struct ScrArea *sa2);
-void ED_screen_draw_split_preview(struct ScrArea *sa, const int dir, const float fac);
+void ED_screen_draw_split_preview(struct ScrArea *area, const int dir, const float fac);
void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win);
void ED_screen_ensure_updated(struct wmWindowManager *wm,
struct wmWindow *win,
struct bScreen *screen);
void ED_screen_do_listen(struct bContext *C, struct wmNotifier *note);
-bool ED_screen_change(struct bContext *C, struct bScreen *sc);
+bool ED_screen_change(struct bContext *C, struct bScreen *screen);
void ED_screen_scene_change(struct bContext *C, struct wmWindow *win, struct Scene *scene);
void ED_screen_set_active_region(struct bContext *C, struct wmWindow *win, const int xy[2]);
void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
-void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
-void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh);
-void ED_screen_restore_temp_type(struct bContext *C, ScrArea *sa);
-ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type);
-void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
-void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
+void ED_screen_animation_timer(struct bContext *C, int redraws, int sync, int enable);
+void ED_screen_animation_timer_update(struct bScreen *screen, int redraws);
+void ED_screen_restore_temp_type(struct bContext *C, ScrArea *area);
+ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *area, int type);
+void ED_screen_full_prevspace(struct bContext *C, ScrArea *area);
+void ED_screen_full_restore(struct bContext *C, ScrArea *area);
struct ScrArea *ED_screen_state_toggle(struct bContext *C,
struct wmWindow *win,
- struct ScrArea *sa,
+ struct ScrArea *area,
const short state);
ScrArea *ED_screen_temp_space_open(struct bContext *C,
const char *title,
@@ -404,40 +409,48 @@ void ED_screen_user_menu_register(void);
/* Cache display helpers */
-void ED_region_cache_draw_background(struct ARegion *ar);
+void ED_region_cache_draw_background(struct ARegion *region);
void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y);
-void ED_region_cache_draw_cached_segments(
- struct ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra);
+void ED_region_cache_draw_cached_segments(struct ARegion *region,
+ const int num_segments,
+ const int *points,
+ const int sfra,
+ const int efra);
/* area_utils.c */
void ED_region_generic_tools_region_message_subscribe(const struct bContext *C,
struct WorkSpace *workspace,
struct Scene *scene,
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus);
-int ED_region_generic_tools_region_snap_size(const struct ARegion *ar, int size, int axis);
+int ED_region_generic_tools_region_snap_size(const struct ARegion *region, int size, int axis);
/* area_query.c */
-bool ED_region_overlap_isect_x(const ARegion *ar, const int event_x);
-bool ED_region_overlap_isect_y(const ARegion *ar, const int event_y);
-bool ED_region_overlap_isect_xy(const ARegion *ar, const int event_xy[2]);
-bool ED_region_overlap_isect_x_with_margin(const ARegion *ar, const int event_x, const int margin);
-bool ED_region_overlap_isect_y_with_margin(const ARegion *ar, const int event_y, const int margin);
-bool ED_region_overlap_isect_xy_with_margin(const ARegion *ar,
+bool ED_region_overlap_isect_x(const ARegion *region, const int event_x);
+bool ED_region_overlap_isect_y(const ARegion *region, const int event_y);
+bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2]);
+bool ED_region_overlap_isect_any_xy(const ScrArea *area, const int event_xy[2]);
+bool ED_region_overlap_isect_x_with_margin(const ARegion *region,
+ const int event_x,
+ const int margin);
+bool ED_region_overlap_isect_y_with_margin(const ARegion *region,
+ const int event_y,
+ const int margin);
+bool ED_region_overlap_isect_xy_with_margin(const ARegion *region,
const int event_xy[2],
const int margin);
-bool ED_region_panel_category_gutter_calc_rect(const ARegion *ar, rcti *r_ar_gutter);
-bool ED_region_panel_category_gutter_isect_xy(const ARegion *ar, const int event_xy[2]);
+bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_region_gutter);
+bool ED_region_panel_category_gutter_isect_xy(const ARegion *region, const int event_xy[2]);
-bool ED_region_contains_xy(const struct ARegion *ar, const int event_xy[2]);
+bool ED_region_contains_xy(const struct ARegion *region, const int event_xy[2]);
/* interface_region_hud.c */
struct ARegionType *ED_area_type_hud(int space_type);
-void ED_area_type_hud_clear(struct wmWindowManager *wm, ScrArea *sa_keep);
-void ED_area_type_hud_ensure(struct bContext *C, struct ScrArea *sa);
+void ED_area_type_hud_clear(struct wmWindowManager *wm, ScrArea *area_keep);
+void ED_area_type_hud_ensure(struct bContext *C, struct ScrArea *area);
/* default keymaps, bitflags (matches order of evaluation). */
enum {
@@ -445,7 +458,6 @@ enum {
ED_KEYMAP_GIZMO = (1 << 2),
ED_KEYMAP_TOOL = (1 << 3),
ED_KEYMAP_VIEW2D = (1 << 4),
- ED_KEYMAP_MARKERS = (1 << 5),
ED_KEYMAP_ANIMATION = (1 << 6),
ED_KEYMAP_FRAMES = (1 << 7),
ED_KEYMAP_HEADER = (1 << 8),
@@ -460,4 +472,8 @@ enum {
SPACE_CONTEXT_CYCLE_NEXT,
};
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_SCREEN_H__ */
diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h
index c515d501a8d..51f3eea74fa 100644
--- a/source/blender/editors/include/ED_screen_types.h
+++ b/source/blender/editors/include/ED_screen_types.h
@@ -24,18 +24,21 @@
#ifndef __ED_SCREEN_TYPES_H__
#define __ED_SCREEN_TYPES_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* ----------------------------------------------------- */
/* for animplayer */
typedef struct ScreenAnimData {
- ARegion *ar; /* do not read from this, only for comparing if region exists */
+ ARegion *region; /* do not read from this, only for comparing if region exists */
short redraws;
- short refresh;
- short flag; /* flags for playback */
- int sfra; /* frame that playback was started from */
- int nextfra; /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */
- double last_duration; /* used for frame dropping */
- bool from_anim_edit; /* playback was invoked from animation editor */
+ short flag; /* flags for playback */
+ int sfra; /* frame that playback was started from */
+ int nextfra; /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */
+ double lagging_frame_count; /* used for frame dropping */
+ bool from_anim_edit; /* playback was invoked from animation editor */
} ScreenAnimData;
/* for animplayer */
@@ -92,7 +95,7 @@ typedef enum {
/* for editing areas/regions */
typedef struct AZone {
struct AZone *next, *prev;
- ARegion *ar;
+ ARegion *region;
int type;
union {
@@ -134,4 +137,8 @@ enum {
AZONE_REGION_SCROLL,
};
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_SCREEN_TYPES_H__ */
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 4a0ce7b0078..e61c7be5216 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -24,6 +24,10 @@
#ifndef __ED_SCULPT_H__
#define __ED_SCULPT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegion;
struct Object;
struct UndoType;
@@ -33,7 +37,7 @@ struct rcti;
/* sculpt.c */
void ED_operatortypes_sculpt(void);
-void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar, struct Object *ob);
+void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *region, struct Object *ob);
bool ED_sculpt_mask_box_select(struct bContext *C,
struct ViewContext *vc,
const struct rcti *rect,
@@ -50,4 +54,13 @@ void ED_sculpt_undosys_type(struct UndoType *ut);
void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name);
void ED_sculpt_undo_geometry_end(struct Object *ob);
+/* Undo for changes happening on a base mesh for multires sculpting.
+ * if there is no multires sculpt active regular undo is used. */
+void ED_sculpt_undo_push_multires_mesh_begin(struct bContext *C, const char *str);
+void ED_sculpt_undo_push_multires_mesh_end(struct bContext *C, const char *str);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_SCULPT_H__ */
diff --git a/source/blender/editors/include/ED_select_utils.h b/source/blender/editors/include/ED_select_utils.h
index 954e4335608..9c7cc0ef7a2 100644
--- a/source/blender/editors/include/ED_select_utils.h
+++ b/source/blender/editors/include/ED_select_utils.h
@@ -21,6 +21,10 @@
#ifndef __ED_SELECT_UTILS_H__
#define __ED_SELECT_UTILS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct KDTree_1d;
enum {
@@ -30,6 +34,13 @@ enum {
SEL_INVERT = 3,
};
+typedef enum WalkSelectDirection {
+ UI_SELECT_WALK_UP,
+ UI_SELECT_WALK_DOWN,
+ UI_SELECT_WALK_LEFT,
+ UI_SELECT_WALK_RIGHT,
+} WalkSelectDirections;
+
/** See #WM_operator_properties_select_operation */
typedef enum {
SEL_OP_ADD = 1,
@@ -64,4 +75,8 @@ bool ED_select_similar_compare_float_tree(const struct KDTree_1d *tree,
eSelectOp ED_select_op_modal(const eSelectOp sel_op, const bool is_first);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_SELECT_UTILS_H__ */
diff --git a/source/blender/editors/include/ED_sequencer.h b/source/blender/editors/include/ED_sequencer.h
index 2e89af4bb3f..f35ed12cdb9 100644
--- a/source/blender/editors/include/ED_sequencer.h
+++ b/source/blender/editors/include/ED_sequencer.h
@@ -23,6 +23,10 @@
#ifndef __ED_SEQUENCER_H__
#define __ED_SEQUENCER_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Scene;
struct Sequence;
struct SpaceSeq;
@@ -46,4 +50,8 @@ Sequence *ED_sequencer_special_preview_get(void);
void ED_sequencer_special_preview_set(struct bContext *C, const int mval[2]);
void ED_sequencer_special_preview_clear(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_SEQUENCER_H__ */
diff --git a/source/blender/editors/include/ED_sound.h b/source/blender/editors/include/ED_sound.h
index 44b3c5a6b79..f7632bc81cb 100644
--- a/source/blender/editors/include/ED_sound.h
+++ b/source/blender/editors/include/ED_sound.h
@@ -24,6 +24,14 @@
#ifndef __ED_SOUND_H__
#define __ED_SOUND_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void ED_operatortypes_sound(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_SOUND_H__ */
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index 766f2b31192..ae4add2fca2 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -24,6 +24,10 @@
#ifndef __ED_SPACE_API_H__
#define __ED_SPACE_API_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegionType;
struct bContext;
@@ -72,6 +76,12 @@ void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int);
void ED_region_draw_cb_exit(struct ARegionType *, void *);
/* generic callbacks */
/* ed_util.c */
-void ED_region_draw_mouse_line_cb(const struct bContext *C, struct ARegion *ar, void *arg_info);
+void ED_region_draw_mouse_line_cb(const struct bContext *C,
+ struct ARegion *region,
+ void *arg_info);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* __ED_SPACE_API_H__ */
diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h
index ade1dde6c33..4f7b76675f0 100644
--- a/source/blender/editors/include/ED_text.h
+++ b/source/blender/editors/include/ED_text.h
@@ -24,6 +24,10 @@
#ifndef __ED_TEXT_H__
#define __ED_TEXT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegion;
struct SpaceText;
struct Text;
@@ -32,7 +36,7 @@ struct UndoType;
struct bContext;
bool ED_text_region_location_from_cursor(struct SpaceText *st,
- struct ARegion *ar,
+ struct ARegion *region,
const int cursor_co[2],
int r_pixel_co[2]);
@@ -44,4 +48,8 @@ struct UndoStep *ED_text_undo_push_init(struct bContext *C);
/* text_format.c */
bool ED_text_is_syntax_highlight_supported(struct Text *text);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_TEXT_H__ */
diff --git a/source/blender/editors/include/ED_time_scrub_ui.h b/source/blender/editors/include/ED_time_scrub_ui.h
index f010c45d939..d5b9fa2a553 100644
--- a/source/blender/editors/include/ED_time_scrub_ui.h
+++ b/source/blender/editors/include/ED_time_scrub_ui.h
@@ -24,19 +24,27 @@
#ifndef __ED_TIME_SCRUB_UI_H__
#define __ED_TIME_SCRUB_UI_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct bContext;
struct bDopeSheet;
struct wmEvent;
-void ED_time_scrub_draw(const struct ARegion *ar,
+void ED_time_scrub_draw(const struct ARegion *region,
const struct Scene *scene,
bool display_seconds,
bool discrete_frames);
-bool ED_time_scrub_event_in_region(const struct ARegion *ar, const struct wmEvent *event);
+bool ED_time_scrub_event_in_region(const struct ARegion *region, const struct wmEvent *event);
void ED_time_scrub_channel_search_draw(const struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
struct bDopeSheet *dopesheet);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_TIME_SCRUB_UI_H__ */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index d53ad7c4229..27b7511c8a2 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -24,6 +24,10 @@
#ifndef __ED_TRANSFORM_H__
#define __ED_TRANSFORM_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* ******************* Registration Function ********************** */
struct Object;
@@ -119,7 +123,7 @@ struct bContext;
void BIF_clearTransformOrientation(struct bContext *C);
void BIF_removeTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
void BIF_removeTransformOrientationIndex(struct bContext *C, int index);
-void BIF_createTransformOrientation(struct bContext *C,
+bool BIF_createTransformOrientation(struct bContext *C,
struct ReportList *reports,
const char *name,
const bool use_view,
@@ -153,6 +157,8 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_GPENCIL_EDIT (1 << 13)
#define P_CURSOR_EDIT (1 << 14)
#define P_CLNOR_INVALIDATE (1 << 15)
+/* For properties performed when confirming the transformation. */
+#define P_POST_TRANSFORM (1 << 16)
void Transform_Properties(struct wmOperatorType *ot, int flags);
@@ -206,4 +212,8 @@ int ED_transform_calc_gizmo_stats(const struct bContext *C,
const struct TransformCalcParams *params,
struct TransformBounds *tbounds);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_TRANSFORM_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 0e20abe4221..b998ac87819 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -21,6 +21,10 @@
#ifndef __ED_TRANSFORM_SNAP_OBJECT_CONTEXT_H__
#define __ED_TRANSFORM_SNAP_OBJECT_CONTEXT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct BMEdge;
struct BMFace;
struct BMVert;
@@ -75,14 +79,12 @@ struct SnapObjectParams {
typedef struct SnapObjectContext SnapObjectContext;
SnapObjectContext *ED_transform_snap_object_context_create(struct Main *bmain,
struct Scene *scene,
- struct Depsgraph *depsgraph,
int flag);
SnapObjectContext *ED_transform_snap_object_context_create_view3d(struct Main *bmain,
struct Scene *scene,
- struct Depsgraph *depsgraph,
int flag,
/* extra args for view3d */
- const struct ARegion *ar,
+ const struct ARegion *region,
const struct View3D *v3d);
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx);
@@ -95,6 +97,7 @@ void ED_transform_snap_object_context_set_editmesh_callbacks(
void *user_data);
bool ED_transform_snap_object_project_ray_ex(struct SnapObjectContext *sctx,
+ struct Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float ray_start[3],
const float ray_normal[3],
@@ -106,6 +109,7 @@ bool ED_transform_snap_object_project_ray_ex(struct SnapObjectContext *sctx,
struct Object **r_ob,
float r_obmat[4][4]);
bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx,
+ struct Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float ray_origin[3],
const float ray_direction[3],
@@ -114,6 +118,7 @@ bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx,
float r_no[3]);
bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
+ struct Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float ray_start[3],
const float ray_normal[3],
@@ -122,6 +127,7 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
struct ListBase *r_hit_list);
short ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx,
+ struct Depsgraph *depsgraph,
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2],
@@ -133,6 +139,7 @@ short ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx,
struct Object **r_ob,
float r_obmat[4][4]);
bool ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx,
+ struct Depsgraph *depsgraph,
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2],
@@ -143,10 +150,15 @@ bool ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx,
float r_no[3]);
bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
+ struct Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float mval[2],
float ray_depth,
bool sort,
ListBase *r_hit_list);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_TRANSFORM_SNAP_OBJECT_CONTEXT_H__ */
diff --git a/source/blender/editors/include/ED_transverts.h b/source/blender/editors/include/ED_transverts.h
index 3460aae32c0..062658a562b 100644
--- a/source/blender/editors/include/ED_transverts.h
+++ b/source/blender/editors/include/ED_transverts.h
@@ -24,6 +24,10 @@
#ifndef __ED_TRANSVERTS_H__
#define __ED_TRANSVERTS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Object;
typedef struct TransVert {
@@ -68,4 +72,8 @@ enum {
TX_VERT_USE_NORMAL = (1 << 2), /* avoid nonzero check */
};
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_TRANSVERTS_H__ */
diff --git a/source/blender/editors/include/ED_types.h b/source/blender/editors/include/ED_types.h
index 4b18bb699a9..4abb7d446d1 100644
--- a/source/blender/editors/include/ED_types.h
+++ b/source/blender/editors/include/ED_types.h
@@ -24,6 +24,10 @@
#ifndef __ED_TYPES_H__
#define __ED_TYPES_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* **************** GENERAL EDITOR-WIDE TYPES AND DEFINES ************************** */
/* old blender defines... should be deprecated? */
@@ -35,4 +39,8 @@
// #define BASACT (scene->basact)
// #define OBACT (BASACT ? BASACT->object : NULL)
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_TYPES_H__ */
diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h
index fa2630ba726..983e0c4f14a 100644
--- a/source/blender/editors/include/ED_undo.h
+++ b/source/blender/editors/include/ED_undo.h
@@ -23,6 +23,11 @@
#include "BLI_compiler_attrs.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Base;
struct CLG_LogRef;
struct Object;
struct UndoStack;
@@ -62,6 +67,10 @@ void ED_undo_object_editmode_restore_helper(struct bContext *C,
uint object_array_len,
uint object_array_stride);
+struct Object **ED_undo_editmode_objects_from_view_layer(struct ViewLayer *view_layer,
+ uint *r_len);
+struct Base **ED_undo_editmode_bases_from_view_layer(struct ViewLayer *view_layer, uint *r_len);
+
struct UndoStack *ED_undo_stack_get(void);
/* helpers */
@@ -77,4 +86,8 @@ void ED_undosys_type_free(void);
/* memfile_undo.c */
struct MemFile *ED_undosys_stack_memfile_get_active(struct UndoStack *ustack);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_UNDO_H__ */
diff --git a/source/blender/editors/include/ED_userpref.h b/source/blender/editors/include/ED_userpref.h
index 686b8a689f0..1d43009e37c 100644
--- a/source/blender/editors/include/ED_userpref.h
+++ b/source/blender/editors/include/ED_userpref.h
@@ -21,6 +21,14 @@
#ifndef __ED_USERPREF_H__
#define __ED_USERPREF_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void ED_operatortypes_userpref(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_USERPREF_H__ */
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 8cce8fa973a..1f2706957a7 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -26,6 +26,10 @@
#include "BLI_compiler_attrs.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Main;
struct bContext;
struct wmOperatorType;
@@ -44,7 +48,7 @@ bool ED_editors_flush_edits_for_object(struct Main *bmain, struct Object *ob);
bool ED_editors_flush_edits_ex(struct Main *bmain, bool for_render, bool check_needs_flush);
bool ED_editors_flush_edits(struct Main *bmain);
-void ED_spacedata_id_remap(struct ScrArea *sa,
+void ED_spacedata_id_remap(struct ScrArea *area,
struct SpaceLink *sl,
struct ID *old_id,
struct ID *new_id);
@@ -64,4 +68,8 @@ void unpack_menu(struct bContext *C,
const char *folder,
struct PackedFile *pf);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_UTIL_H__ */
diff --git a/source/blender/editors/include/ED_util_imbuf.h b/source/blender/editors/include/ED_util_imbuf.h
new file mode 100644
index 00000000000..76171383b49
--- /dev/null
+++ b/source/blender/editors/include/ED_util_imbuf.h
@@ -0,0 +1,52 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup editors
+ */
+
+#ifndef __ED_UTIL_IMBUF_H__
+#define __ED_UTIL_IMBUF_H__
+
+#include "BLI_compiler_attrs.h"
+#include "BLI_sys_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ARegion;
+struct Main;
+struct bContext;
+struct wmEvent;
+struct wmOperator;
+
+/* ed_util_imbuf.c */
+void ED_imbuf_sample_draw(const struct bContext *C, struct ARegion *region, void *arg_info);
+void ED_imbuf_sample_exit(struct bContext *C, struct wmOperator *op);
+int ED_imbuf_sample_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int ED_imbuf_sample_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+void ED_imbuf_sample_cancel(struct bContext *C, struct wmOperator *op);
+bool ED_imbuf_sample_poll(struct bContext *C);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ED_UTIL_IMBUF_H__ */
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index c912778afd8..8c565536c71 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -24,6 +24,10 @@
#ifndef __ED_UVEDIT_H__
#define __ED_UVEDIT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegionType;
struct BMEditMesh;
struct BMFace;
@@ -184,7 +188,7 @@ bool ED_uvedit_nearest_uv_multi(const struct Scene *scene,
float r_uv[2]);
void ED_uvedit_get_aspect(
- const struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy);
+ const struct Scene *scene, struct Object *ob, struct BMesh *em, float *r_aspx, float *r_aspy);
/* uvedit_unwrap_ops.c */
void ED_uvedit_live_unwrap_begin(struct Scene *scene, struct Object *obedit);
@@ -195,7 +199,7 @@ void ED_uvedit_live_unwrap(const struct Scene *scene, struct Object **objects, i
void ED_uvedit_add_simple_uvs(struct Main *bmain, const struct Scene *scene, struct Object *ob);
/* uvedit_draw.c */
-void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]);
+void ED_image_draw_cursor(struct ARegion *region, const float cursor[2]);
void ED_uvedit_draw_main(struct SpaceImage *sima,
const struct Scene *scene,
struct ViewLayer *view_layer,
@@ -206,4 +210,8 @@ void ED_uvedit_draw_main(struct SpaceImage *sima,
/* uvedit_buttons.c */
void ED_uvedit_buttons_register(struct ARegionType *art);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_UVEDIT_H__ */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 37ffb1b9d6d..668ca3c6437 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -24,6 +24,10 @@
#ifndef __ED_VIEW3D_H__
#define __ED_VIEW3D_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* ********* exports for space_view3d/ module ********** */
struct ARegion;
struct BMEdge;
@@ -41,7 +45,6 @@ struct EditBone;
struct GPUOffScreen;
struct GPUViewport;
struct ID;
-struct ImBuf;
struct MVert;
struct Main;
struct MetaElem;
@@ -80,7 +83,7 @@ typedef struct ViewContext {
struct ViewLayer *view_layer;
struct Object *obact;
struct Object *obedit;
- struct ARegion *ar;
+ struct ARegion *region;
struct View3D *v3d;
struct wmWindow *win;
struct RegionView3D *rv3d;
@@ -90,13 +93,31 @@ typedef struct ViewContext {
typedef struct ViewDepths {
unsigned short w, h;
- short x, y; /* only for temp use for sub-rects, added to ar->winx/y */
+ short x, y; /* only for temp use for sub-rects, added to region->winx/y */
float *depths;
double depth_range[2];
bool damaged;
} ViewDepths;
+typedef struct ViewDrawOffscreenContext {
+ struct Depsgraph *depsgraph;
+ struct Scene *scene;
+ int drawtype;
+ struct View3D *v3d;
+ struct ARegion *region;
+ int winx;
+ int winy;
+ float viewmat[4][4];
+ float winmat[4][4];
+ bool do_sky;
+ bool is_persp;
+ const char *viewname;
+ const bool do_color_management;
+ struct GPUOffScreen *ofs;
+ struct GPUViewport *viewport;
+} ViewDrawOffscreenContext;
+
/* Rotate 3D cursor on placement. */
enum eV3DCursorOrient {
V3D_CURSOR_ORIENT_NONE = 0,
@@ -139,12 +160,12 @@ void ED_view3d_to_object(const struct Depsgraph *depsgraph,
void ED_view3d_lastview_store(struct RegionView3D *rv3d);
/* Depth buffer */
-void ED_view3d_depth_update(struct ARegion *ar);
+void ED_view3d_depth_update(struct ARegion *region);
float ED_view3d_depth_read_cached(const struct ViewContext *vc, const int mval[2]);
bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
const int mval[2],
float r_normal[3]);
-bool ED_view3d_depth_unproject(const struct ARegion *ar,
+bool ED_view3d_depth_unproject(const struct ARegion *region,
const int mval[2],
const double depth,
float r_location_world[3]);
@@ -257,61 +278,61 @@ void pose_foreachScreenBone(struct ViewContext *vc,
/* *** end iterators *** */
/* view3d_project.c */
-void ED_view3d_project_float_v2_m4(const struct ARegion *ar,
+void ED_view3d_project_float_v2_m4(const struct ARegion *region,
const float co[3],
float r_co[2],
float mat[4][4]);
-void ED_view3d_project_float_v3_m4(const struct ARegion *ar,
+void ED_view3d_project_float_v3_m4(const struct ARegion *region,
const float co[3],
float r_co[3],
float mat[4][4]);
-eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base);
+eV3DProjStatus ED_view3d_project_base(const struct ARegion *region, struct Base *base);
/* *** short *** */
-eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *ar,
+eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *region,
float perspmat[4][4],
const bool is_local,
const float co[3],
short r_co[2],
const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_short_global(const struct ARegion *ar,
+eV3DProjStatus ED_view3d_project_short_global(const struct ARegion *region,
const float co[3],
short r_co[2],
const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_short_object(const struct ARegion *ar,
+eV3DProjStatus ED_view3d_project_short_object(const struct ARegion *region,
const float co[3],
short r_co[2],
const eV3DProjTest flag);
/* *** int *** */
-eV3DProjStatus ED_view3d_project_int_ex(const struct ARegion *ar,
+eV3DProjStatus ED_view3d_project_int_ex(const struct ARegion *region,
float perspmat[4][4],
const bool is_local,
const float co[3],
int r_co[2],
const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_int_global(const struct ARegion *ar,
+eV3DProjStatus ED_view3d_project_int_global(const struct ARegion *region,
const float co[3],
int r_co[2],
const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_int_object(const struct ARegion *ar,
+eV3DProjStatus ED_view3d_project_int_object(const struct ARegion *region,
const float co[3],
int r_co[2],
const eV3DProjTest flag);
/* *** float *** */
-eV3DProjStatus ED_view3d_project_float_ex(const struct ARegion *ar,
+eV3DProjStatus ED_view3d_project_float_ex(const struct ARegion *region,
float perspmat[4][4],
const bool is_local,
const float co[3],
float r_co[2],
const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar,
+eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *region,
const float co[3],
float r_co[2],
const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar,
+eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *region,
const float co[3],
float r_co[2],
const eV3DProjTest flag);
@@ -322,21 +343,21 @@ float ED_view3d_pixel_size_no_ui_scale(const struct RegionView3D *rv3d, const fl
float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip);
bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]);
bool ED_view3d_win_to_ray_clipped(struct Depsgraph *depsgraph,
- const struct ARegion *ar,
+ const struct ARegion *region,
const struct View3D *v3d,
const float mval[2],
float ray_start[3],
float ray_normal[3],
const bool do_clip);
bool ED_view3d_win_to_ray_clipped_ex(struct Depsgraph *depsgraph,
- const struct ARegion *ar,
+ const struct ARegion *region,
const struct View3D *v3d,
const float mval[2],
float r_ray_co[3],
float r_ray_normal[3],
float r_ray_start[3],
bool do_clip);
-void ED_view3d_win_to_ray(const struct ARegion *ar,
+void ED_view3d_win_to_ray(const struct ARegion *region,
const float mval[2],
float r_ray_start[3],
float r_ray_normal[3]);
@@ -344,33 +365,33 @@ void ED_view3d_global_to_vector(const struct RegionView3D *rv3d,
const float coord[3],
float vec[3]);
void ED_view3d_win_to_3d(const struct View3D *v3d,
- const struct ARegion *ar,
+ const struct ARegion *region,
const float depth_pt[3],
const float mval[2],
float r_out[3]);
void ED_view3d_win_to_3d_int(const struct View3D *v3d,
- const struct ARegion *ar,
+ const struct ARegion *region,
const float depth_pt[3],
const int mval[2],
float r_out[3]);
-bool ED_view3d_win_to_3d_on_plane(const struct ARegion *ar,
+bool ED_view3d_win_to_3d_on_plane(const struct ARegion *region,
const float plane[4],
const float mval[2],
const bool do_clip,
float r_out[3]);
-bool ED_view3d_win_to_3d_on_plane_int(const struct ARegion *ar,
+bool ED_view3d_win_to_3d_on_plane_int(const struct ARegion *region,
const float plane[4],
const int mval[2],
const bool do_clip,
float r_out[3]);
-void ED_view3d_win_to_delta(const struct ARegion *ar,
+void ED_view3d_win_to_delta(const struct ARegion *region,
const float mval[2],
float out[3],
const float zfac);
-void ED_view3d_win_to_origin(const struct ARegion *ar, const float mval[2], float out[3]);
-void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], float out[3]);
+void ED_view3d_win_to_origin(const struct ARegion *region, const float mval[2], float out[3]);
+void ED_view3d_win_to_vector(const struct ARegion *region, const float mval[2], float out[3]);
bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph,
- const struct ARegion *ar,
+ const struct ARegion *region,
struct View3D *v3d,
const float mval[2],
float r_ray_start[3],
@@ -383,9 +404,9 @@ void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d,
float obmat[4][4],
float pmat[4][4]);
-void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3]);
+void ED_view3d_project(const struct ARegion *region, const float world[3], float r_region_co[3]);
bool ED_view3d_unproject(
- const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]);
+ const struct ARegion *region, float regionx, float regiony, float regionz, float world[3]);
/* end */
@@ -410,21 +431,21 @@ void ED_view3d_polygon_offset(const struct RegionView3D *rv3d, const float dist)
void ED_view3d_calc_camera_border(const struct Scene *scene,
struct Depsgraph *depsgraph,
- const struct ARegion *ar,
+ const struct ARegion *region,
const struct View3D *v3d,
const struct RegionView3D *rv3d,
struct rctf *r_viewborder,
const bool no_shift);
void ED_view3d_calc_camera_border_size(const struct Scene *scene,
struct Depsgraph *depsgraph,
- const struct ARegion *ar,
+ const struct ARegion *region,
const struct View3D *v3d,
const struct RegionView3D *rv3d,
float r_size[2]);
bool ED_view3d_calc_render_border(const struct Scene *scene,
struct Depsgraph *depsgraph,
struct View3D *v3d,
- struct ARegion *ar,
+ struct ARegion *region,
struct rcti *rect);
void ED_view3d_clipping_calc_from_boundbox(float clip[6][4],
@@ -432,7 +453,7 @@ void ED_view3d_clipping_calc_from_boundbox(float clip[6][4],
const bool is_flip);
void ED_view3d_clipping_calc(struct BoundBox *bb,
float planes[4][4],
- const struct ARegion *ar,
+ const struct ARegion *region,
const struct Object *ob,
const struct rcti *rect);
void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[4][4]);
@@ -446,22 +467,22 @@ void ED_view3d_clipping_disable(void);
float ED_view3d_radius_to_dist_persp(const float angle, const float radius);
float ED_view3d_radius_to_dist_ortho(const float lens, const float radius);
float ED_view3d_radius_to_dist(const struct View3D *v3d,
- const struct ARegion *ar,
+ const struct ARegion *region,
const struct Depsgraph *depsgraph,
const char persp,
const bool use_aspect,
const float radius);
-void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos);
+void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned int pos);
/* backbuffer select and draw support */
void ED_view3d_backbuf_depth_validate(struct ViewContext *vc);
-int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist);
+int ED_view3d_backbuf_sample_size_clamp(struct ARegion *region, const float dist);
void ED_view3d_select_id_validate(struct ViewContext *vc);
bool ED_view3d_autodist(struct Depsgraph *depsgraph,
- struct ARegion *ar,
+ struct ARegion *region,
struct View3D *v3d,
const int mval[2],
float mouse_worldloc[3],
@@ -470,17 +491,20 @@ bool ED_view3d_autodist(struct Depsgraph *depsgraph,
/* only draw so ED_view3d_autodist_simple can be called many times after */
void ED_view3d_autodist_init(struct Depsgraph *depsgraph,
- struct ARegion *ar,
+ struct ARegion *region,
struct View3D *v3d,
int mode);
-bool ED_view3d_autodist_simple(struct ARegion *ar,
+bool ED_view3d_autodist_simple(struct ARegion *region,
const int mval[2],
float mouse_worldloc[3],
int margin,
float *force_depth);
-bool ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin, float *depth);
-bool ED_view3d_autodist_depth_seg(
- struct ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
+bool ED_view3d_autodist_depth(struct ARegion *region, const int mval[2], int margin, float *depth);
+bool ED_view3d_autodist_depth_seg(struct ARegion *region,
+ const int mval_sta[2],
+ const int mval_end[2],
+ int margin,
+ float *depth);
/* select */
#define MAXPICKELEMS 2500
@@ -524,7 +548,7 @@ void ED_view3d_viewcontext_init(struct bContext *C,
struct Depsgraph *depsgraph);
void ED_view3d_viewcontext_init_object(struct ViewContext *vc, struct Object *obact);
void view3d_operator_needs_opengl(const struct bContext *C);
-void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar);
+void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *region);
/* XXX should move to BLI_math */
bool edge_inside_circle(const float cent[2],
@@ -536,7 +560,10 @@ bool edge_inside_circle(const float cent[2],
struct RegionView3D *ED_view3d_context_rv3d(struct bContext *C);
bool ED_view3d_context_user_region(struct bContext *C,
struct View3D **r_v3d,
- struct ARegion **r_ar);
+ struct ARegion **r_region);
+bool ED_view3d_area_user_region(const struct ScrArea *area,
+ const struct View3D *v3d,
+ struct ARegion **r_region);
bool ED_operator_rv3d_user_region_poll(struct bContext *C);
void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d);
@@ -557,73 +584,37 @@ void ED_draw_object_facemap(struct Depsgraph *depsgraph,
const float col[4],
const int facemap);
-struct RenderEngineType *ED_view3d_engine_type(struct Scene *scene, int drawtype);
+struct RenderEngineType *ED_view3d_engine_type(const struct Scene *scene, int drawtype);
bool ED_view3d_context_activate(struct bContext *C);
-void ED_view3d_draw_offscreen(struct Depsgraph *depsgraph,
- struct Scene *scene,
- int drawtype,
- struct View3D *v3d,
- struct ARegion *ar,
- int winx,
- int winy,
- float viewmat[4][4],
- float winmat[4][4],
- bool do_sky,
- bool is_persp,
- const char *viewname,
- const bool do_color_management,
- struct GPUOffScreen *ofs,
- struct GPUViewport *viewport);
-void ED_view3d_draw_setup_view(struct wmWindow *win,
+void ED_view3d_draw_setup_view(const struct wmWindowManager *wm,
+ struct wmWindow *win,
struct Depsgraph *depsgraph,
struct Scene *scene,
- struct ARegion *ar,
+ struct ARegion *region,
struct View3D *v3d,
float viewmat[4][4],
float winmat[4][4],
const struct rcti *rect);
-struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Depsgraph *depsgraph,
- struct Scene *scene,
- int drawtype,
- struct View3D *v3d,
- struct ARegion *ar,
- int sizex,
- int sizey,
- unsigned int flag,
- int alpha_mode,
- const char *viewname,
- struct GPUOffScreen *ofs,
- char err_out[256]);
-struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct View3DShading *shading_override,
- int drawtype,
- struct Object *camera,
- int width,
- int height,
- unsigned int flag,
- unsigned int draw_flags,
- int alpha_mode,
- const char *viewname,
- struct GPUOffScreen *ofs,
- char err_out[256]);
-
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
struct Object *ED_view3d_give_object_under_cursor(struct bContext *C, const int mval[2]);
bool ED_view3d_is_object_under_cursor(struct bContext *C, const int mval[2]);
-void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
+void ED_view3d_quadview_update(struct ScrArea *area, struct ARegion *region, bool do_clip);
void ED_view3d_update_viewmat(struct Depsgraph *depsgraph,
- struct Scene *scene,
+ const struct Scene *scene,
struct View3D *v3d,
- struct ARegion *ar,
+ struct ARegion *region,
float viewmat[4][4],
float winmat[4][4],
const struct rcti *rect,
bool offscreen);
-bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
-char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon);
+bool ED_view3d_quat_from_axis_view(const char view, const char view_axis_roll, float quat[4]);
+bool ED_view3d_quat_to_axis_view(const float viewquat[4],
+ const float epsilon,
+ char *r_view,
+ char *r_view_axis_rotation);
+
char ED_view3d_lock_view_from_index(int index);
char ED_view3d_axis_view_opposite(char view);
bool ED_view3d_lock(struct RegionView3D *rv3d);
@@ -644,7 +635,7 @@ void ED_view3d_persp_switch_from_camera(const struct Depsgraph *depsgraph,
const char persp);
bool ED_view3d_persp_ensure(const struct Depsgraph *depsgraph,
struct View3D *v3d,
- struct ARegion *ar);
+ struct ARegion *region);
/* camera lock functions */
bool ED_view3d_camera_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
@@ -661,7 +652,7 @@ bool ED_view3d_camera_lock_sync(const struct Depsgraph *depsgraph,
struct View3D *v3d,
struct RegionView3D *rv3d);
-bool ED_view3d_camera_autokey(struct Scene *scene,
+bool ED_view3d_camera_autokey(const struct Scene *scene,
struct ID *id_key,
struct bContext *C,
const bool do_rotate,
@@ -683,18 +674,20 @@ bool ED_view3d_distance_set_from_location(struct RegionView3D *rv3d,
const float dist_co[3],
const float dist_min);
-float ED_scene_grid_scale(struct Scene *scene, const char **grid_unit);
-float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit);
-void ED_view3d_grid_steps(struct Scene *scene,
+float ED_scene_grid_scale(const struct Scene *scene, const char **r_grid_unit);
+float ED_view3d_grid_scale(const struct Scene *scene,
+ struct View3D *v3d,
+ const char **r_grid_unit);
+void ED_view3d_grid_steps(const struct Scene *scene,
struct View3D *v3d,
struct RegionView3D *rv3d,
float *r_grid_steps);
float ED_view3d_grid_view_scale(struct Scene *scene,
struct View3D *v3d,
struct RegionView3D *rv3d,
- const char **grid_unit);
+ const char **r_grid_unit);
-void ED_scene_draw_fps(struct Scene *scene, int xoffset, int *yoffset);
+void ED_scene_draw_fps(const struct Scene *scene, int xoffset, int *yoffset);
/* view matrix properties utilities */
/* unused */
@@ -708,8 +701,8 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op,
#endif
/* render */
-void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *ar);
-void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa);
+void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *region);
+void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *area);
#define XRAY_ALPHA(v3d) \
(((v3d)->shading.type == OB_WIRE) ? (v3d)->shading.xray_alpha_wire : (v3d)->shading.xray_alpha)
@@ -721,9 +714,9 @@ void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrAr
/* view3d_draw_legacy.c */
/* Try avoid using these more move out of legacy. */
-void ED_view3d_draw_bgpic_test(struct Scene *scene,
+void ED_view3d_draw_bgpic_test(const struct Scene *scene,
struct Depsgraph *depsgraph,
- struct ARegion *ar,
+ struct ARegion *region,
struct View3D *v3d,
const bool do_foreground,
const bool do_camera_frame);
@@ -736,11 +729,27 @@ void ED_view3d_gizmo_mesh_preselect_get_active(struct bContext *C,
/* space_view3d.c */
void ED_view3d_buttons_region_layout_ex(const struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
const char *category_override);
/* view3d_view.c */
bool ED_view3d_local_collections_set(struct Main *bmain, struct View3D *v3d);
void ED_view3d_local_collections_reset(struct bContext *C, const bool reset_all);
+#ifdef WITH_XR_OPENXR
+void ED_view3d_xr_mirror_update(const struct ScrArea *area,
+ const struct View3D *v3d,
+ const bool enable);
+void ED_view3d_xr_shading_update(struct wmWindowManager *wm,
+ const View3D *v3d,
+ const struct Scene *scene);
+bool ED_view3d_is_region_xr_mirror_active(const struct wmWindowManager *wm,
+ const struct View3D *v3d,
+ const struct ARegion *region);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/ED_view3d_offscreen.h b/source/blender/editors/include/ED_view3d_offscreen.h
new file mode 100644
index 00000000000..11d1aed1e73
--- /dev/null
+++ b/source/blender/editors/include/ED_view3d_offscreen.h
@@ -0,0 +1,110 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup editors
+ */
+
+#ifndef __ED_VIEW3D_OFFSCREEN_H__
+#define __ED_VIEW3D_OFFSCREEN_H__
+
+#include "DNA_object_enums.h"
+#include "DNA_view3d_types.h"
+
+#include "IMB_imbuf_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ********* exports for space_view3d/ module for offscreen rendering ********** */
+struct ARegion;
+struct Depsgraph;
+struct GPUOffScreen;
+struct GPUViewport;
+struct Scene;
+struct View3D;
+struct View3DShading;
+
+void ED_view3d_draw_offscreen(struct Depsgraph *depsgraph,
+ const struct Scene *scene,
+ eDrawType drawtype,
+ struct View3D *v3d,
+ struct ARegion *region,
+ int winx,
+ int winy,
+ float viewmat[4][4],
+ float winmat[4][4],
+ bool is_image_render,
+ bool do_sky,
+ bool is_persp,
+ const char *viewname,
+ const bool do_color_management,
+ struct GPUOffScreen *ofs,
+ struct GPUViewport *viewport);
+void ED_view3d_draw_offscreen_simple(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct View3DShading *shading_override,
+ int drawtype,
+ int winx,
+ int winy,
+ unsigned int draw_flags,
+ float viewmat[4][4],
+ float winmat[4][4],
+ float clip_start,
+ float clip_end,
+ bool is_image_render,
+ bool do_sky,
+ bool is_persp,
+ const char *viewname,
+ const bool do_color_management,
+ struct GPUOffScreen *ofs,
+ struct GPUViewport *viewport);
+
+struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ eDrawType drawtype,
+ struct View3D *v3d,
+ struct ARegion *region,
+ int sizex,
+ int sizey,
+ eImBufFlags imbuf_flag,
+ int alpha_mode,
+ const char *viewname,
+ struct GPUOffScreen *ofs,
+ char err_out[256]);
+struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct View3DShading *shading_override,
+ eDrawType drawtype,
+ struct Object *camera,
+ int width,
+ int height,
+ eImBufFlags imbuf_flags,
+ eV3DOffscreenDrawFlag draw_flags,
+ int alpha_mode,
+ const char *viewname,
+ struct GPUOffScreen *ofs,
+ char err_out[256]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index fabf6baed23..452a1fca111 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -428,7 +428,7 @@ DEF_ICON(FORCE_CURVE)
DEF_ICON(FORCE_BOID)
DEF_ICON(FORCE_TURBULENCE)
DEF_ICON(FORCE_DRAG)
-DEF_ICON(FORCE_SMOKEFLOW)
+DEF_ICON(FORCE_FLUIDFLOW)
DEF_ICON_BLANK(673)
DEF_ICON_BLANK(674)
DEF_ICON(RIGID_BODY)
@@ -745,21 +745,22 @@ DEF_ICON_BLANK(252b)
DEF_ICON_BLANK(252c)
DEF_ICON(LAYER_USED)
DEF_ICON(LAYER_ACTIVE)
-/* available */
DEF_ICON_BLANK(254)
DEF_ICON_BLANK(255)
DEF_ICON_BLANK(256)
DEF_ICON_BLANK(257)
DEF_ICON_BLANK(257b)
-DEF_ICON_BLANK(258)
-DEF_ICON_BLANK(259)
-DEF_ICON_BLANK(260)
-DEF_ICON_BLANK(261)
-DEF_ICON_BLANK(262)
-DEF_ICON_BLANK(263)
-DEF_ICON_BLANK(264)
-DEF_ICON_BLANK(265)
-DEF_ICON_BLANK(266)
+
+/* ADDITIONAL OBJECT TYPES */
+DEF_ICON_OBJECT(OUTLINER_OB_HAIR)
+DEF_ICON_OBJECT_DATA(OUTLINER_DATA_HAIR)
+DEF_ICON_OBJECT_DATA(HAIR_DATA)
+DEF_ICON_OBJECT(OUTLINER_OB_POINTCLOUD)
+DEF_ICON_OBJECT_DATA(OUTLINER_DATA_POINTCLOUD)
+DEF_ICON_OBJECT_DATA(POINTCLOUD_DATA)
+DEF_ICON_OBJECT(OUTLINER_OB_VOLUME)
+DEF_ICON_OBJECT_DATA(OUTLINER_DATA_VOLUME)
+DEF_ICON_OBJECT_DATA(VOLUME_DATA)
DEF_ICON_BLANK(267)
DEF_ICON_BLANK(268)
DEF_ICON_BLANK(269)
@@ -793,7 +794,7 @@ DEF_ICON(BOOKMARKS)
DEF_ICON(FONTPREVIEW)
DEF_ICON(FILTER)
DEF_ICON(NEWFOLDER)
-DEF_ICON(FOLDER_REDIRECT)
+DEF_ICON_FOLDER(FOLDER_REDIRECT)
DEF_ICON(FILE_PARENT)
DEF_ICON(FILE_REFRESH)
DEF_ICON_FOLDER(FILE_FOLDER)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 3089d980f06..8b7b0430765 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -28,6 +28,10 @@
#include "BLI_sys_types.h" /* size_t */
#include "RNA_types.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Struct Declarations */
struct ARegion;
@@ -45,6 +49,7 @@ struct PanelType;
struct PointerRNA;
struct PropertyRNA;
struct ReportList;
+struct ResultBLF;
struct ScrArea;
struct bContext;
struct bContextStore;
@@ -245,6 +250,8 @@ enum {
UI_BUT_TEXT_RIGHT = 1 << 3,
/** Prevent the button to show any tooltip. */
UI_BUT_NO_TOOLTIP = 1 << 4,
+ /** Do not add the usual horizontal padding for text drawing. */
+ UI_BUT_NO_TEXT_PADDING = 1 << 5,
/* Button align flag, for drawing groups together.
* Used in 'uiBlock.flag', take care! */
@@ -403,22 +410,22 @@ void UI_draw_roundbox_aa(
bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]);
void UI_draw_roundbox_4fv(
bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4]);
-void UI_draw_roundbox_3ubAlpha(bool filled,
- float minx,
- float miny,
- float maxx,
- float maxy,
- float rad,
- const unsigned char col[3],
- unsigned char alpha);
-void UI_draw_roundbox_3fvAlpha(bool filled,
- float minx,
- float miny,
- float maxx,
- float maxy,
- float rad,
- const float col[3],
- float alpha);
+void UI_draw_roundbox_3ub_alpha(bool filled,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ float rad,
+ const unsigned char col[3],
+ unsigned char alpha);
+void UI_draw_roundbox_3fv_alpha(bool filled,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ float rad,
+ const float col[3],
+ float alpha);
void UI_draw_roundbox_shade_x(bool filled,
float minx,
float miny,
@@ -495,13 +502,25 @@ typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origs
typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2);
typedef void (*uiButHandleHoldFunc)(struct bContext *C, struct ARegion *butregion, uiBut *but);
typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
-typedef struct ARegion *(*uiButSearchCreateFunc)(struct bContext *C,
- struct ARegion *butregion,
- uiBut *but);
-typedef void (*uiButSearchFunc)(const struct bContext *C,
- void *arg,
- const char *str,
- uiSearchItems *items);
+
+/* Search types. */
+typedef struct ARegion *(*uiButSearchCreateFn)(struct bContext *C,
+ struct ARegion *butregion,
+ uiBut *but);
+typedef void (*uiButSearchUpdateFn)(const struct bContext *C,
+ void *arg,
+ const char *str,
+ uiSearchItems *items);
+typedef void (*uiButSearchArgFreeFn)(void *arg);
+typedef bool (*uiButSearchContextMenuFn)(struct bContext *C,
+ void *arg,
+ void *active,
+ const struct wmEvent *event);
+typedef struct ARegion *(*uiButSearchTooltipFn)(struct bContext *C,
+ struct ARegion *region,
+ void *arg,
+ void *active);
+
/* Must return allocated string. */
typedef char *(*uiButToolTipFunc)(struct bContext *C, void *argN, const char *tip);
typedef int (*uiButPushedStateFunc)(struct bContext *C, void *arg);
@@ -600,7 +619,7 @@ struct uiLayout *UI_pie_menu_layout(struct uiPieMenu *pie);
*
* Functions used to create popup blocks. These are like popup menus
* but allow using all button types and creating an own layout. */
-typedef uiBlock *(*uiBlockCreateFunc)(struct bContext *C, struct ARegion *ar, void *arg1);
+typedef uiBlock *(*uiBlockCreateFunc)(struct bContext *C, struct ARegion *region, void *arg1);
typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1);
void UI_popup_block_invoke(struct bContext *C,
@@ -611,8 +630,7 @@ void UI_popup_block_invoke_ex(struct bContext *C,
uiBlockCreateFunc func,
void *arg,
void (*arg_free)(void *arg),
- const char *opname,
- int opcontext);
+ bool can_refresh);
void UI_popup_block_ex(struct bContext *C,
uiBlockCreateFunc func,
uiBlockHandleFunc popup_func,
@@ -628,7 +646,7 @@ void uiPupBlockOperator(struct bContext *C,
void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *block);
-bool UI_popup_block_name_exists(struct bContext *C, const char *name);
+bool UI_popup_block_name_exists(const struct bScreen *screen, const char *name);
/* Blocks
*
@@ -723,12 +741,20 @@ void UI_but_drawflag_disable(uiBut *but, int flag);
void UI_but_type_set_menu_from_pulldown(uiBut *but);
/* special button case, only draw it when used actively, for outliner etc */
-bool UI_but_active_only(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but);
+bool UI_but_active_only_ex(const struct bContext *C,
+ struct ARegion *region,
+ uiBlock *block,
+ uiBut *but,
+ const bool remove_on_failure);
+bool UI_but_active_only(const struct bContext *C,
+ struct ARegion *region,
+ uiBlock *block,
+ uiBut *but);
bool UI_block_active_only_flagged_buttons(const struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
struct uiBlock *block);
-void UI_but_execute(const struct bContext *C, struct ARegion *ar, uiBut *but);
+void UI_but_execute(const struct bContext *C, struct ARegion *region, uiBut *but);
bool UI_but_online_manual_id(const uiBut *but,
char *r_str,
@@ -1112,7 +1138,9 @@ uiBut *uiDefIconButO_ptr(uiBlock *block,
short width,
short height,
const char *tip);
-
+uiBut *uiDefButImage(
+ uiBlock *block, void *imbuf, int x, int y, short width, short height, const uchar color[4]);
+uiBut *uiDefButAlert(uiBlock *block, int icon, int x, int y, short width, short height);
uiBut *uiDefIconTextBut(uiBlock *block,
int type,
int retval,
@@ -1551,21 +1579,26 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
const bool compact);
/* use inside searchfunc to add items */
-bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid);
-/* bfunc gets search item *poin as arg2, or if NULL the old string */
+bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int state);
void UI_but_func_search_set(uiBut *but,
- uiButSearchCreateFunc cfunc,
- uiButSearchFunc sfunc,
+ uiButSearchCreateFn search_create_fn,
+ uiButSearchUpdateFn search_update_fn,
void *arg,
- bool free_arg,
- uiButHandleFunc bfunc,
+ uiButSearchArgFreeFn search_arg_free_fn,
+ uiButHandleFunc search_exec_fn,
void *active);
+void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn);
+void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn);
+void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string);
+
/* height in pixels, it's using hardcoded values still */
int UI_searchbox_size_y(void);
int UI_searchbox_size_x(void);
/* check if a string is in an existing search box */
int UI_search_items_find_index(uiSearchItems *items, const char *name);
+void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]);
+
void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg);
void UI_block_func_butmenu_set(uiBlock *block, uiMenuHandleFunc func, void *arg);
void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2);
@@ -1590,7 +1623,7 @@ void UI_but_tooltip_refresh(struct bContext *C, uiBut *but);
void UI_but_tooltip_timer_remove(struct bContext *C, uiBut *but);
bool UI_textbutton_activate_rna(const struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
const void *rna_poin_data,
const char *rna_prop_id);
bool UI_textbutton_activate_but(const struct bContext *C, uiBut *but);
@@ -1628,42 +1661,44 @@ int UI_autocomplete_end(AutoComplete *autocpl, char *autoname);
* could use a good cleanup, though how they will function in 2.5 is
* not clear yet so we postpone that. */
-void UI_panels_begin(const struct bContext *C, struct ARegion *ar);
-void UI_panels_end(const struct bContext *C, struct ARegion *ar, int *r_x, int *r_y);
-void UI_panels_draw(const struct bContext *C, struct ARegion *ar);
+void UI_panels_begin(const struct bContext *C, struct ARegion *region);
+void UI_panels_end(const struct bContext *C, struct ARegion *region, int *r_x, int *r_y);
+void UI_panels_draw(const struct bContext *C, struct ARegion *region);
struct Panel *UI_panel_find_by_type(struct ListBase *lb, struct PanelType *pt);
-struct Panel *UI_panel_begin(struct ScrArea *sa,
- struct ARegion *ar,
+struct Panel *UI_panel_begin(struct ScrArea *area,
+ struct ARegion *region,
struct ListBase *lb,
uiBlock *block,
struct PanelType *pt,
- struct Panel *pa,
+ struct Panel *panel,
bool *r_open);
-void UI_panel_end(const struct ScrArea *sa,
- const struct ARegion *ar,
+void UI_panel_end(const struct ScrArea *area,
+ const struct ARegion *region,
uiBlock *block,
int width,
int height,
bool open);
-void UI_panels_scale(struct ARegion *ar, float new_width);
+void UI_panels_scale(struct ARegion *region, float new_width);
void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y);
-int UI_panel_size_y(const struct Panel *pa);
-
-bool UI_panel_category_is_visible(const struct ARegion *ar);
-void UI_panel_category_add(struct ARegion *ar, const char *name);
-struct PanelCategoryDyn *UI_panel_category_find(struct ARegion *ar, const char *idname);
-struct PanelCategoryStack *UI_panel_category_active_find(struct ARegion *ar, const char *idname);
-const char *UI_panel_category_active_get(struct ARegion *ar, bool set_fallback);
-void UI_panel_category_active_set(struct ARegion *ar, const char *idname);
-void UI_panel_category_active_set_default(struct ARegion *ar, const char *idname);
-struct PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(struct ARegion *ar,
+int UI_panel_size_y(const struct Panel *panel);
+bool UI_panel_is_dragging(const struct Panel *panel);
+
+bool UI_panel_category_is_visible(const struct ARegion *region);
+void UI_panel_category_add(struct ARegion *region, const char *name);
+struct PanelCategoryDyn *UI_panel_category_find(struct ARegion *region, const char *idname);
+struct PanelCategoryStack *UI_panel_category_active_find(struct ARegion *region,
+ const char *idname);
+const char *UI_panel_category_active_get(struct ARegion *region, bool set_fallback);
+void UI_panel_category_active_set(struct ARegion *region, const char *idname);
+void UI_panel_category_active_set_default(struct ARegion *region, const char *idname);
+struct PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(struct ARegion *region,
const int x,
const int y);
-struct PanelCategoryDyn *UI_panel_category_find_mouse_over(struct ARegion *ar,
+struct PanelCategoryDyn *UI_panel_category_find_mouse_over(struct ARegion *region,
const struct wmEvent *event);
-void UI_panel_category_clear_all(struct ARegion *ar);
-void UI_panel_category_draw_all(struct ARegion *ar, const char *category_id_active);
+void UI_panel_category_clear_all(struct ARegion *region);
+void UI_panel_category_draw_all(struct ARegion *region, const char *category_id_active);
struct PanelType *UI_paneltype_find(int space_id, int region_id, const char *idname);
@@ -1727,7 +1762,7 @@ enum {
};
enum {
- UI_ITEM_O_RETURN_PROPS = 1 << 0,
+ /* UI_ITEM_O_RETURN_PROPS = 1 << 0, */ /* UNUSED */
UI_ITEM_R_EXPAND = 1 << 1,
UI_ITEM_R_SLIDER = 1 << 2,
/**
@@ -1752,6 +1787,10 @@ enum {
UI_ITEM_O_DEPRESS = 1 << 10,
UI_ITEM_R_COMPACT = 1 << 11,
UI_ITEM_R_CHECKBOX_INVERT = 1 << 12,
+ /** Don't add a real decorator item, just blank space. */
+ UI_ITEM_R_FORCE_BLANK_DECORATE = 1 << 13,
+ /* Even create the property split layout if there's no name to show there. */
+ UI_ITEM_R_SPLIT_EMPTY_NAME = 1 << 14,
};
#define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X)
@@ -1762,6 +1801,9 @@ enum {
UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = 1 << 1,
UI_TEMPLATE_OP_PROPS_COMPACT = 1 << 2,
UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = 1 << 3,
+ /* Disable property split for the default layout (custom ui callbacks still have full control
+ * over the layout and can enable it). */
+ UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT = 1 << 4,
};
/* used for transp checkers */
@@ -1792,11 +1834,11 @@ uiLayout *UI_block_layout(uiBlock *block,
int size,
int em,
int padding,
- struct uiStyle *style);
+ const struct uiStyle *style);
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout);
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y);
-void UI_region_message_subscribe(struct ARegion *ar, struct wmMsgBus *mbus);
+void UI_region_message_subscribe(struct ARegion *region, struct wmMsgBus *mbus);
uiBlock *uiLayoutGetBlock(uiLayout *layout);
@@ -1849,7 +1891,9 @@ bool uiLayoutGetPropDecorate(uiLayout *layout);
/* layout specifiers */
uiLayout *uiLayoutRow(uiLayout *layout, bool align);
+uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading);
uiLayout *uiLayoutColumn(uiLayout *layout, bool align);
+uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading);
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align);
uiLayout *uiLayoutGridFlow(uiLayout *layout,
bool row_major,
@@ -2020,13 +2064,16 @@ void uiTemplateImageInfo(uiLayout *layout,
void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C);
void UI_but_func_operator_search(uiBut *but);
void uiTemplateOperatorSearch(uiLayout *layout);
-eAutoPropButsReturn uiTemplateOperatorPropertyButs(const struct bContext *C,
- uiLayout *layout,
- struct wmOperator *op,
- const eButLabelAlign label_align,
- const short flag);
+
+void UI_but_func_menu_search(uiBut *but);
+void uiTemplateMenuSearch(uiLayout *layout);
+
+void uiTemplateOperatorPropertyButs(const struct bContext *C,
+ uiLayout *layout,
+ struct wmOperator *op,
+ eButLabelAlign label_align,
+ short flag);
void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C);
-void uiTemplateHeader3D(uiLayout *layout, struct bContext *C);
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateInputStatus(uiLayout *layout, struct bContext *C);
@@ -2047,8 +2094,6 @@ void uiTemplateCacheFile(uiLayout *layout,
struct PointerRNA *ptr,
const char *propname);
-struct ColorBand *UI_block_get_colorband_from_template_menu(struct uiBlock *block);
-
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
void uiTemplateList(uiLayout *layout,
@@ -2067,6 +2112,7 @@ void uiTemplateList(uiLayout *layout,
bool sort_reverse,
bool sort_lock);
void uiTemplateNodeLink(uiLayout *layout,
+ struct bContext *C,
struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocket *input);
@@ -2276,7 +2322,17 @@ void uiItemsFullEnumO_items(uiLayout *layout,
const EnumPropertyItem *item_array,
int totitem);
+typedef struct uiPropertySplitWrapper {
+ uiLayout *label_column;
+ uiLayout *property_row;
+ uiLayout *decorate_column;
+} uiPropertySplitWrapper;
+
+uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout);
+
void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
+void uiItemL_ex(
+ uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert);
uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon);
/* label icon for dragging */
void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int icon);
@@ -2285,6 +2341,9 @@ void uiItemM_ptr(uiLayout *layout, struct MenuType *mt, const char *name, int ic
void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon);
/* menu contents */
void uiItemMContents(uiLayout *layout, const char *menuname);
+/* Decorators */
+void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index);
+void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index);
/* value */
void uiItemV(uiLayout *layout, const char *name, int icon, int argval);
/* separator */
@@ -2341,7 +2400,7 @@ void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
bool UI_drop_color_poll(struct bContext *C,
struct wmDrag *drag,
const struct wmEvent *event,
- const char **tooltip);
+ const char **r_tooltip);
bool UI_context_copy_to_selected_list(struct bContext *C,
struct PointerRNA *ptr,
@@ -2352,6 +2411,7 @@ bool UI_context_copy_to_selected_list(struct bContext *C,
/* Helpers for Operators */
uiBut *UI_context_active_but_get(const struct bContext *C);
+uiBut *UI_context_active_but_get_respect_menu(const struct bContext *C);
uiBut *UI_context_active_but_prop_get(const struct bContext *C,
struct PointerRNA *r_ptr,
struct PropertyRNA **r_prop,
@@ -2368,8 +2428,11 @@ void UI_context_active_but_prop_get_templateID(struct bContext *C,
struct PropertyRNA **r_prop);
struct ID *UI_context_active_but_get_tab_ID(struct bContext *C);
-uiBut *UI_region_active_but_get(struct ARegion *ar);
-uiBut *UI_region_but_find_rect_over(const struct ARegion *ar, const struct rcti *isect);
+uiBut *UI_region_active_but_get(struct ARegion *region);
+uiBut *UI_region_but_find_rect_over(const struct ARegion *region, const struct rcti *isect);
+uiBlock *UI_region_block_find_mouse_over(const struct ARegion *region,
+ const int xy[2],
+ bool only_clip);
/* uiFontStyle.align */
typedef enum eFontStyle_Align {
@@ -2391,8 +2454,9 @@ void UI_fontstyle_draw_ex(const struct uiFontStyle *fs,
const uchar col[4],
const struct uiFontStyleDraw_Params *fs_params,
size_t len,
- float *r_xofs,
- float *r_yofs);
+ int *r_xofs,
+ int *r_yofs,
+ struct ResultBLF *r_info);
void UI_fontstyle_draw(const struct uiFontStyle *fs,
const struct rcti *rect,
const char *str,
@@ -2416,8 +2480,8 @@ int UI_fontstyle_height_max(const struct uiFontStyle *fs);
void UI_draw_icon_tri(float x, float y, char dir, const float[4]);
-struct uiStyle *UI_style_get(void); /* use for fonts etc */
-struct uiStyle *UI_style_get_dpi(void); /* DPI scaled settings for drawing */
+const struct uiStyle *UI_style_get(void); /* use for fonts etc */
+const struct uiStyle *UI_style_get_dpi(void); /* DPI scaled settings for drawing */
/* linker workaround ack! */
void UI_template_fix_linking(void);
@@ -2446,7 +2510,7 @@ struct ARegion *UI_tooltip_create_from_button(struct bContext *C,
uiBut *but,
bool is_label);
struct ARegion *UI_tooltip_create_from_gizmo(struct bContext *C, struct wmGizmo *gz);
-void UI_tooltip_free(struct bContext *C, struct bScreen *sc, struct ARegion *ar);
+void UI_tooltip_free(struct bContext *C, struct bScreen *screen, struct ARegion *region);
/* How long before a tool-tip shows. */
#define UI_TOOLTIP_DELAY 0.5
@@ -2479,4 +2543,8 @@ void UI_interface_tag_script_reload(void);
/* Support click-drag motion which presses the button and closes a popover (like a menu). */
#define USE_UI_POPOVER_ONCE
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __UI_INTERFACE_H__ */
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index db8afccbe2d..a304c76bc9d 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -24,6 +24,10 @@
#ifndef __UI_INTERFACE_ICONS_H__
#define __UI_INTERFACE_ICONS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ID;
struct PointerRNA;
struct PreviewImage;
@@ -48,6 +52,17 @@ typedef struct IconFile {
#define PREVIEW_DEFAULT_HEIGHT 128
+typedef enum eAlertIcon {
+ ALERT_ICON_WARNING = 0,
+ ALERT_ICON_QUESTION = 1,
+ ALERT_ICON_ERROR = 2,
+ ALERT_ICON_INFO = 3,
+ ALERT_ICON_BLENDER = 4,
+ ALERT_ICON_MAX,
+} eAlertIcon;
+
+struct ImBuf *UI_alert_image(eAlertIcon icon);
+
/*
* Resizable Icons for Blender
*/
@@ -78,14 +93,6 @@ void UI_icon_draw_ex(float x,
const uchar mono_color[4],
const bool mono_border);
-void UI_icon_draw_desaturate(float x,
- float y,
- int icon_id,
- float aspect,
- float alpha,
- float desaturate,
- const char mono_color[4]);
-
void UI_icons_free(void);
void UI_icons_free_drawinfo(void *drawinfo);
@@ -100,4 +107,8 @@ struct PreviewImage *UI_icon_to_preview(int icon_id);
int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
int UI_idcode_icon_get(const int idcode);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __UI_INTERFACE_ICONS_H__ */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 1e6e46cbe71..c5c4ca79f14 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -43,6 +43,10 @@ typedef enum {
/* use to denote intentionally unset theme color */
#define TH_UNDEFINED -1
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef enum ThemeColorID {
TH_REDALERT,
@@ -108,6 +112,8 @@ typedef enum ThemeColorID {
TH_FACEDOT_SIZE,
TH_CFRAME,
TH_TIME_SCRUB_BACKGROUND,
+ TH_TIME_MARKER_LINE,
+ TH_TIME_MARKER_LINE_SELECTED,
TH_TIME_KEYFRAME,
TH_TIME_GP_KEYFRAME,
TH_NURB_ULINE,
@@ -199,10 +205,12 @@ typedef enum ThemeColorID {
TH_SEQ_SCENE,
TH_SEQ_AUDIO,
TH_SEQ_EFFECT,
- TH_SEQ_TRANSITION,
TH_SEQ_META,
TH_SEQ_TEXT,
TH_SEQ_PREVIEW,
+ TH_SEQ_COLOR,
+ TH_SEQ_ACTIVE,
+ TH_SEQ_SELECTED,
TH_EDGE_SHARP,
TH_EDITMESH_ACTIVE,
@@ -229,6 +237,7 @@ typedef enum ThemeColorID {
TH_DRAWEXTRA_FACEANG,
TH_NODE_CURVING,
+ TH_NODE_GRID_LEVELS,
TH_MARKER_OUTLINE,
TH_MARKER,
@@ -299,6 +308,10 @@ typedef enum ThemeColorID {
TH_WIDGET_TEXT_CURSOR,
TH_EDITOR_OUTLINE,
+ TH_TRANSPARENT_CHECKER_PRIMARY,
+ TH_TRANSPARENT_CHECKER_SECONDARY,
+ TH_TRANSPARENT_CHECKER_SIZE,
+
TH_AXIS_X, /* X/Y/Z Axis */
TH_AXIS_Y,
TH_AXIS_Z,
@@ -306,10 +319,11 @@ typedef enum ThemeColorID {
TH_GIZMO_HI,
TH_GIZMO_PRIMARY,
TH_GIZMO_SECONDARY,
+ TH_GIZMO_VIEW_ALIGN,
TH_GIZMO_A,
TH_GIZMO_B,
- TH_SHOW_BACK_GRAD,
+ TH_BACKGROUND_TYPE,
TH_INFO_SELECTED,
TH_INFO_SELECTED_TEXT,
@@ -441,4 +455,8 @@ const unsigned char *UI_ThemeGetColorPtr(struct bTheme *btheme, int spacetype, i
void UI_make_axis_color(const unsigned char *src_col, unsigned char *dst_col, const char axis);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __UI_RESOURCES_H__ */
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index e34f40d057d..ffc06e94a90 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -28,6 +28,10 @@
#include "BLI_compiler_attrs.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* ------------------------------------------ */
/* Settings and Defines: */
@@ -115,7 +119,7 @@ void UI_view2d_region_reinit(struct View2D *v2d, short type, int winx, int winy)
void UI_view2d_curRect_validate(struct View2D *v2d);
void UI_view2d_curRect_reset(struct View2D *v2d);
-void UI_view2d_sync(struct bScreen *screen, struct ScrArea *sa, struct View2D *v2dcur, int flag);
+void UI_view2d_sync(struct bScreen *screen, struct ScrArea *area, struct View2D *v2dcur, int flag);
void UI_view2d_totRect_set(struct View2D *v2d, int width, int height);
void UI_view2d_totRect_set_resize(struct View2D *v2d, int width, int height, bool resize);
@@ -129,13 +133,13 @@ void UI_view2d_zoom_cache_reset(void);
/* view matrix operations */
void UI_view2d_view_ortho(const struct View2D *v2d);
-void UI_view2d_view_orthoSpecial(struct ARegion *ar, struct View2D *v2d, const bool xaxis);
+void UI_view2d_view_orthoSpecial(struct ARegion *region, struct View2D *v2d, const bool xaxis);
void UI_view2d_view_restore(const struct bContext *C);
/* grid drawing */
-void UI_view2d_constant_grid_draw(struct View2D *v2d, float step);
+void UI_view2d_constant_grid_draw(const struct View2D *v2d, float step);
void UI_view2d_multi_grid_draw(
- struct View2D *v2d, int colorid, float step, int level_size, int totlevels);
+ const struct View2D *v2d, int colorid, float step, int level_size, int totlevels);
void UI_view2d_draw_lines_y__values(const struct View2D *v2d);
void UI_view2d_draw_lines_x__values(const struct View2D *v2d);
@@ -154,21 +158,21 @@ float UI_view2d_grid_resolution_x__frames_or_seconds(const struct View2D *v2d,
float UI_view2d_grid_resolution_y__values(const struct View2D *v2d);
/* scale indicator text drawing */
-void UI_view2d_draw_scale_y__values(const struct ARegion *ar,
+void UI_view2d_draw_scale_y__values(const struct ARegion *region,
const struct View2D *v2d,
const struct rcti *rect,
int colorid);
-void UI_view2d_draw_scale_y__block(const struct ARegion *ar,
+void UI_view2d_draw_scale_y__block(const struct ARegion *region,
const struct View2D *v2d,
const struct rcti *rect,
int colorid);
-void UI_view2d_draw_scale_x__discrete_frames_or_seconds(const struct ARegion *ar,
+void UI_view2d_draw_scale_x__discrete_frames_or_seconds(const struct ARegion *region,
const struct View2D *v2d,
const struct rcti *rect,
const struct Scene *scene,
bool display_seconds,
int colorid);
-void UI_view2d_draw_scale_x__frames_or_seconds(const struct ARegion *ar,
+void UI_view2d_draw_scale_x__frames_or_seconds(const struct ARegion *region,
const struct View2D *v2d,
const struct rcti *rect,
const struct Scene *scene,
@@ -205,14 +209,17 @@ bool UI_view2d_view_to_region_clip(
const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL();
void UI_view2d_view_to_region(
- struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL();
-void UI_view2d_view_to_region_fl(
- struct View2D *v2d, float x, float y, float *r_region_x, float *r_region_y) ATTR_NONNULL();
-void UI_view2d_view_to_region_m4(struct View2D *v2d, float matrix[4][4]) ATTR_NONNULL();
-void UI_view2d_view_to_region_rcti(struct View2D *v2d,
+ const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL();
+void UI_view2d_view_to_region_fl(const struct View2D *v2d,
+ float x,
+ float y,
+ float *r_region_x,
+ float *r_region_y) ATTR_NONNULL();
+void UI_view2d_view_to_region_m4(const struct View2D *v2d, float matrix[4][4]) ATTR_NONNULL();
+void UI_view2d_view_to_region_rcti(const struct View2D *v2d,
const struct rctf *rect_src,
struct rcti *rect_dst) ATTR_NONNULL();
-bool UI_view2d_view_to_region_rcti_clip(struct View2D *v2d,
+bool UI_view2d_view_to_region_rcti_clip(const struct View2D *v2d,
const struct rctf *rect_src,
struct rcti *rect_dst) ATTR_NONNULL();
@@ -224,43 +231,47 @@ void UI_view2d_scroller_size_get(const struct View2D *v2d, float *r_x, float *r_
void UI_view2d_scale_get(struct View2D *v2d, float *r_x, float *r_y);
float UI_view2d_scale_get_x(const struct View2D *v2d);
float UI_view2d_scale_get_y(const struct View2D *v2d);
-void UI_view2d_scale_get_inverse(struct View2D *v2d, float *r_x, float *r_y);
+void UI_view2d_scale_get_inverse(const struct View2D *v2d, float *r_x, float *r_y);
-void UI_view2d_center_get(struct View2D *v2d, float *r_x, float *r_y);
+void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y);
void UI_view2d_center_set(struct View2D *v2d, float x, float y);
void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac);
char UI_view2d_mouse_in_scrollers_ex(
- const struct ARegion *ar, const struct View2D *v2d, int x, int y, int *r_scroll);
-char UI_view2d_mouse_in_scrollers(const struct ARegion *ar,
+ const struct ARegion *region, const struct View2D *v2d, int x, int y, int *r_scroll);
+char UI_view2d_mouse_in_scrollers(const struct ARegion *region,
const struct View2D *v2d,
int x,
int y);
-char UI_view2d_rect_in_scrollers_ex(const struct ARegion *ar,
+char UI_view2d_rect_in_scrollers_ex(const struct ARegion *region,
const struct View2D *v2d,
const struct rcti *rect,
int *r_scroll);
-char UI_view2d_rect_in_scrollers(const struct ARegion *ar,
+char UI_view2d_rect_in_scrollers(const struct ARegion *region,
const struct View2D *v2d,
const struct rcti *rect);
/* cached text drawing in v2d, to allow pixel-aligned draw as post process */
-void UI_view2d_text_cache_add(
- struct View2D *v2d, float x, float y, const char *str, size_t str_len, const char col[4]);
+void UI_view2d_text_cache_add(struct View2D *v2d,
+ float x,
+ float y,
+ const char *str,
+ size_t str_len,
+ const unsigned char col[4]);
void UI_view2d_text_cache_add_rectf(struct View2D *v2d,
const struct rctf *rect_view,
const char *str,
size_t str_len,
- const char col[4]);
-void UI_view2d_text_cache_draw(struct ARegion *ar);
+ const unsigned char col[4]);
+void UI_view2d_text_cache_draw(struct ARegion *region);
/* operators */
void ED_operatortypes_view2d(void);
void ED_keymap_view2d(struct wmKeyConfig *keyconf);
void UI_view2d_smooth_view(struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
const struct rctf *cur,
const int smooth_viewtx);
@@ -273,4 +284,8 @@ void UI_view2d_smooth_view(struct bContext *C,
/* Caller passes in own idname. */
void VIEW2D_GGT_navigate_impl(struct wmGizmoGroupType *gzgt, const char *idname);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __UI_VIEW2D_H__ */
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index d33023c69a1..c2c27af9770 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -69,6 +69,9 @@ set(SRC
interface_regions.c
interface_style.c
interface_templates.c
+ interface_template_search_menu.c
+ interface_template_search_operator.c
+ interface_undo.c
interface_utils.c
interface_widgets.c
resources.c
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 8af8fdb06a1..04c259ab092 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -21,12 +21,12 @@
* \ingroup edinterface
*/
+#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <math.h>
-#include <string.h>
-#include <ctype.h>
#include <stddef.h> /* offsetof() */
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -36,15 +36,14 @@
#include "DNA_userdef_types.h"
#include "DNA_workspace_types.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
-#include "BLI_rect.h"
#include "BLI_utildefines.h"
-#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
@@ -65,15 +64,15 @@
#include "IMB_imbuf.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "BPY_extern.h"
-#include "ED_screen.h"
#include "ED_numinput.h"
+#include "ED_screen.h"
#include "IMB_colormanagement.h"
@@ -83,7 +82,7 @@
/* prototypes. */
static void ui_but_to_pixelrect(struct rcti *rect,
- const struct ARegion *ar,
+ const struct ARegion *region,
struct uiBlock *block,
struct uiBut *but);
static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *but_p);
@@ -124,15 +123,15 @@ static bool ui_but_is_unit_radians(const uiBut *but)
/* ************* window matrix ************** */
-void ui_block_to_window_fl(const ARegion *ar, uiBlock *block, float *x, float *y)
+void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *x, float *y)
{
float gx, gy;
int sx, sy, getsizex, getsizey;
- getsizex = BLI_rcti_size_x(&ar->winrct) + 1;
- getsizey = BLI_rcti_size_y(&ar->winrct) + 1;
- sx = ar->winrct.xmin;
- sy = ar->winrct.ymin;
+ getsizex = BLI_rcti_size_x(&region->winrct) + 1;
+ getsizey = BLI_rcti_size_y(&region->winrct) + 1;
+ sx = region->winrct.xmin;
+ sy = region->winrct.ymin;
gx = *x;
gy = *y;
@@ -150,48 +149,51 @@ void ui_block_to_window_fl(const ARegion *ar, uiBlock *block, float *x, float *y
block->winmat[3][1]));
}
-void ui_block_to_window(const ARegion *ar, uiBlock *block, int *x, int *y)
+void ui_block_to_window(const ARegion *region, uiBlock *block, int *x, int *y)
{
float fx, fy;
fx = *x;
fy = *y;
- ui_block_to_window_fl(ar, block, &fx, &fy);
+ ui_block_to_window_fl(region, block, &fx, &fy);
*x = (int)(fx + 0.5f);
*y = (int)(fy + 0.5f);
}
-void ui_block_to_window_rctf(const ARegion *ar, uiBlock *block, rctf *rct_dst, const rctf *rct_src)
+void ui_block_to_window_rctf(const ARegion *region,
+ uiBlock *block,
+ rctf *rct_dst,
+ const rctf *rct_src)
{
*rct_dst = *rct_src;
- ui_block_to_window_fl(ar, block, &rct_dst->xmin, &rct_dst->ymin);
- ui_block_to_window_fl(ar, block, &rct_dst->xmax, &rct_dst->ymax);
+ ui_block_to_window_fl(region, block, &rct_dst->xmin, &rct_dst->ymin);
+ ui_block_to_window_fl(region, block, &rct_dst->xmax, &rct_dst->ymax);
}
-float ui_block_to_window_scale(const ARegion *ar, uiBlock *block)
+float ui_block_to_window_scale(const ARegion *region, uiBlock *block)
{
/* We could have function for this to avoid dummy arg. */
float dummy_x;
float min_y = 0, max_y = 1;
dummy_x = 0.0f;
- ui_block_to_window_fl(ar, block, &dummy_x, &min_y);
+ ui_block_to_window_fl(region, block, &dummy_x, &min_y);
dummy_x = 0.0f;
- ui_block_to_window_fl(ar, block, &dummy_x, &max_y);
+ ui_block_to_window_fl(region, block, &dummy_x, &max_y);
return max_y - min_y;
}
/* for mouse cursor */
-void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y)
+void ui_window_to_block_fl(const ARegion *region, uiBlock *block, float *x, float *y)
{
float a, b, c, d, e, f, px, py;
int sx, sy, getsizex, getsizey;
- getsizex = BLI_rcti_size_x(&ar->winrct) + 1;
- getsizey = BLI_rcti_size_y(&ar->winrct) + 1;
- sx = ar->winrct.xmin;
- sy = ar->winrct.ymin;
+ getsizex = BLI_rcti_size_x(&region->winrct) + 1;
+ getsizey = BLI_rcti_size_y(&region->winrct) + 1;
+ sx = region->winrct.xmin;
+ sy = region->winrct.ymin;
a = 0.5f * ((float)getsizex) * block->winmat[0][0];
b = 0.5f * ((float)getsizex) * block->winmat[1][0];
@@ -213,53 +215,53 @@ void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y
}
}
-void ui_window_to_block_rctf(const struct ARegion *ar,
+void ui_window_to_block_rctf(const struct ARegion *region,
uiBlock *block,
rctf *rct_dst,
const rctf *rct_src)
{
*rct_dst = *rct_src;
- ui_window_to_block_fl(ar, block, &rct_dst->xmin, &rct_dst->ymin);
- ui_window_to_block_fl(ar, block, &rct_dst->xmax, &rct_dst->ymax);
+ ui_window_to_block_fl(region, block, &rct_dst->xmin, &rct_dst->ymin);
+ ui_window_to_block_fl(region, block, &rct_dst->xmax, &rct_dst->ymax);
}
-void ui_window_to_block(const ARegion *ar, uiBlock *block, int *x, int *y)
+void ui_window_to_block(const ARegion *region, uiBlock *block, int *x, int *y)
{
float fx, fy;
fx = *x;
fy = *y;
- ui_window_to_block_fl(ar, block, &fx, &fy);
+ ui_window_to_block_fl(region, block, &fx, &fy);
*x = (int)(fx + 0.5f);
*y = (int)(fy + 0.5f);
}
-void ui_window_to_region(const ARegion *ar, int *x, int *y)
+void ui_window_to_region(const ARegion *region, int *x, int *y)
{
- *x -= ar->winrct.xmin;
- *y -= ar->winrct.ymin;
+ *x -= region->winrct.xmin;
+ *y -= region->winrct.ymin;
}
-void ui_window_to_region_rcti(const ARegion *ar, rcti *rect_dst, const rcti *rct_src)
+void ui_window_to_region_rcti(const ARegion *region, rcti *rect_dst, const rcti *rct_src)
{
- rect_dst->xmin = rct_src->xmin - ar->winrct.xmin;
- rect_dst->xmax = rct_src->xmax - ar->winrct.xmin;
- rect_dst->ymin = rct_src->ymin - ar->winrct.ymin;
- rect_dst->ymax = rct_src->ymax - ar->winrct.ymin;
+ rect_dst->xmin = rct_src->xmin - region->winrct.xmin;
+ rect_dst->xmax = rct_src->xmax - region->winrct.xmin;
+ rect_dst->ymin = rct_src->ymin - region->winrct.ymin;
+ rect_dst->ymax = rct_src->ymax - region->winrct.ymin;
}
-void ui_region_to_window(const ARegion *ar, int *x, int *y)
+void ui_region_to_window(const ARegion *region, int *x, int *y)
{
- *x += ar->winrct.xmin;
- *y += ar->winrct.ymin;
+ *x += region->winrct.xmin;
+ *y += region->winrct.ymin;
}
static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block)
{
int sepr_flex_len = 0;
- for (uiBut *but = block->buttons.first; but; but = but->next) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (but->type == UI_BTYPE_SEPR_SPACER) {
sepr_flex_len++;
}
@@ -281,7 +283,7 @@ static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block)
/* We could get rid of this loop if we agree on a max number of spacer */
int *spacers_pos = alloca(sizeof(*spacers_pos) * (size_t)sepr_flex_len);
int i = 0;
- for (uiBut *but = block->buttons.first; but; but = but->next) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (but->type == UI_BTYPE_SEPR_SPACER) {
ui_but_to_pixelrect(&rect, region, block, but);
spacers_pos[i] = rect.xmax + UI_HEADER_OFFSET;
@@ -292,7 +294,7 @@ static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block)
const float segment_width = region_width / (float)sepr_flex_len;
float offset = 0, remaining_space = region_width - buttons_width;
i = 0;
- for (uiBut *but = block->buttons.first; but; but = but->next) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
BLI_rctf_translate(&but->rect, offset, 0);
if (but->type == UI_BTYPE_SEPR_SPACER) {
/* How much the next block overlap with the current segment */
@@ -336,15 +338,15 @@ static void ui_update_window_matrix(const wmWindow *window, const ARegion *regio
* Popups will add a margin to #ARegion.winrct for shadow,
* for interactivity (point-inside tests for eg), we want the winrct without the margin added.
*/
-void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect)
+void ui_region_winrct_get_no_margin(const struct ARegion *region, struct rcti *r_rect)
{
- uiBlock *block = ar->uiblocks.first;
+ uiBlock *block = region->uiblocks.first;
if (block && (block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_RADIAL) == 0) {
BLI_rcti_rctf_copy_floor(r_rect, &block->rect);
- BLI_rcti_translate(r_rect, ar->winrct.xmin, ar->winrct.ymin);
+ BLI_rcti_translate(r_rect, region->winrct.xmin, region->winrct.ymin);
}
else {
- *r_rect = ar->winrct;
+ *r_rect = region->winrct;
}
}
@@ -363,7 +365,7 @@ void UI_block_translate(uiBlock *block, int x, int y)
static void ui_block_bounds_calc_text(uiBlock *block, float offset)
{
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
uiBut *bt, *init_col_bt, *col_bt;
int i = 0, j, x1addval = offset;
@@ -639,6 +641,26 @@ static int ui_but_calc_float_precision(uiBut *but, double value)
/* ************** BLOCK ENDING FUNCTION ************* */
+bool ui_but_rna_equals(const uiBut *a, const uiBut *b)
+{
+ return ui_but_rna_equals_ex(a, &b->rnapoin, b->rnaprop, b->rnaindex);
+}
+
+bool ui_but_rna_equals_ex(const uiBut *but,
+ const PointerRNA *ptr,
+ const PropertyRNA *prop,
+ int index)
+{
+ if (but->rnapoin.data != ptr->data) {
+ return false;
+ }
+ if (but->rnaprop != prop || but->rnaindex != index) {
+ return false;
+ }
+
+ return true;
+}
+
/* NOTE: if but->poin is allocated memory for every defbut, things fail... */
static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
{
@@ -647,10 +669,7 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
if (but->retval != oldbut->retval) {
return false;
}
- if (but->rnapoin.data != oldbut->rnapoin.data) {
- return false;
- }
- if (but->rnaprop != oldbut->rnaprop || but->rnaindex != oldbut->rnaindex) {
+ if (!ui_but_rna_equals(but, oldbut)) {
return false;
}
if (but->func != oldbut->func) {
@@ -788,6 +807,8 @@ static bool ui_but_update_from_old_block(const bContext *C,
SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons);
+ SWAP(struct uiButSearchData *, oldbut->search, but->search);
+
/* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
* when scrolling without moving mouse (see [#28432]) */
if (ELEM(oldbut->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
@@ -849,7 +870,8 @@ static bool ui_but_update_from_old_block(const bContext *C,
/* needed for temporarily rename buttons, such as in outliner or file-select,
* they should keep calling uiDefButs to keep them alive */
/* returns 0 when button removed */
-bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
+bool UI_but_active_only_ex(
+ const bContext *C, ARegion *region, uiBlock *block, uiBut *but, const bool remove_on_failure)
{
uiBlock *oldblock;
uiBut *oldbut;
@@ -870,40 +892,61 @@ bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *b
}
}
if ((activate == true) || (found == false)) {
- ui_but_activate_event((bContext *)C, ar, but);
+ ui_but_activate_event((bContext *)C, region, but);
}
else if ((found == true) && (isactive == false)) {
- BLI_remlink(&block->buttons, but);
- ui_but_free(C, but);
+ if (remove_on_failure) {
+ BLI_remlink(&block->buttons, but);
+ ui_but_free(C, but);
+ }
return false;
}
return true;
}
-bool UI_block_active_only_flagged_buttons(const bContext *C, ARegion *ar, uiBlock *block)
+bool UI_but_active_only(const bContext *C, ARegion *region, uiBlock *block, uiBut *but)
+{
+ return UI_but_active_only_ex(C, region, block, but, true);
+}
+
+/**
+ * \warning This must run after other handlers have been added,
+ * otherwise the handler wont be removed, see: T71112.
+ */
+bool UI_block_active_only_flagged_buttons(const bContext *C, ARegion *region, uiBlock *block)
{
bool done = false;
- for (uiBut *but = block->buttons.first; but; but = but->next) {
- if (!done && ui_but_is_editable(but)) {
- if (but->flag & UI_BUT_ACTIVATE_ON_INIT) {
- if (UI_but_active_only(C, ar, block, but)) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ if (but->flag & UI_BUT_ACTIVATE_ON_INIT) {
+ but->flag &= ~UI_BUT_ACTIVATE_ON_INIT;
+ if (ui_but_is_editable(but)) {
+ if (UI_but_active_only_ex(C, region, block, but, false)) {
done = true;
+ break;
}
}
}
- but->flag &= ~UI_BUT_ACTIVATE_ON_INIT;
}
+
+ if (done) {
+ /* Run this in a second pass since it's possible activating the button
+ * removes the buttons being looped over. */
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ but->flag &= ~UI_BUT_ACTIVATE_ON_INIT;
+ }
+ }
+
return done;
}
/* simulate button click */
-void UI_but_execute(const bContext *C, ARegion *ar, uiBut *but)
+void UI_but_execute(const bContext *C, ARegion *region, uiBut *but)
{
void *active_back;
- ui_but_execute_begin((bContext *)C, ar, but, &active_back);
+ ui_but_execute_begin((bContext *)C, region, but, &active_back);
/* Value is applied in begin. No further action required. */
- ui_but_execute_end((bContext *)C, ar, but, active_back);
+ ui_but_execute_end((bContext *)C, region, but, active_back);
}
/* use to check if we need to disable undo, but don't make any changes
@@ -946,13 +989,15 @@ static void ui_menu_block_set_keyaccels(uiBlock *block)
/* 2 Passes, on for first letter only, second for any letter if first fails
* fun first pass on all buttons so first word chars always get first priority */
- for (uiBut *but = block->buttons.first; but; but = but->next) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (!ELEM(but->type,
UI_BTYPE_BUT,
UI_BTYPE_BUT_MENU,
UI_BTYPE_MENU,
UI_BTYPE_BLOCK,
- UI_BTYPE_PULLDOWN) ||
+ UI_BTYPE_PULLDOWN,
+ /* For PIE-menus. */
+ UI_BTYPE_ROW) ||
(but->flag & UI_HIDDEN)) {
/* pass */
}
@@ -1272,9 +1317,8 @@ static bool ui_but_event_property_operator_string(const bContext *C,
}
else if (GS(id->name) == ID_SCE) {
if (RNA_struct_is_a(ptr->type, &RNA_ToolSettings)) {
- /* toolsettings property
- * NOTE: toolsettings is usually accessed directly (i.e. not through scene)
- */
+ /* Tool-settings property:
+ * NOTE: tool-settings is usually accessed directly (i.e. not through scene). */
data_path = RNA_path_from_ID_to_property(ptr, prop);
}
else {
@@ -1639,7 +1683,7 @@ static void ui_but_predefined_extra_operator_icons_add(uiBut *but)
}
if (optype) {
- for (uiButExtraOpIcon *op_icon = but->extra_op_icons.first; op_icon; op_icon = op_icon->next) {
+ LISTBASE_FOREACH (uiButExtraOpIcon *, op_icon, &but->extra_op_icons) {
if ((op_icon->optype_params->optype == optype) && (op_icon->icon == icon)) {
/* Don't add the same operator icon twice (happens if button is kept alive while active).
*/
@@ -1805,27 +1849,27 @@ void ui_fontscale(short *points, float aspect)
}
/* project button or block (but==NULL) to pixels in regionspace */
-static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, uiBut *but)
+static void ui_but_to_pixelrect(rcti *rect, const ARegion *region, uiBlock *block, uiBut *but)
{
rctf rectf;
- ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
+ ui_block_to_window_rctf(region, block, &rectf, (but) ? &but->rect : &block->rect);
BLI_rcti_rctf_copy_round(rect, &rectf);
- BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
+ BLI_rcti_translate(rect, -region->winrct.xmin, -region->winrct.ymin);
}
/* uses local copy of style, to scale things down, and allow widgets to change stuff */
void UI_block_draw(const bContext *C, uiBlock *block)
{
uiStyle style = *UI_style_get_dpi(); /* XXX pass on as arg */
- ARegion *ar;
+ ARegion *region;
uiBut *but;
rcti rect;
/* get menu region or area region */
- ar = CTX_wm_menu(C);
- if (!ar) {
- ar = CTX_wm_region(C);
+ region = CTX_wm_menu(C);
+ if (!region) {
+ region = CTX_wm_region(C);
}
if (!block->endblock) {
@@ -1843,40 +1887,41 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ui_fontscale(&style.widget.points, block->aspect);
/* scale block min/max to rect */
- ui_but_to_pixelrect(&rect, ar, block, NULL);
+ ui_but_to_pixelrect(&rect, region, block, NULL);
/* pixel space for AA widgets */
GPU_matrix_push_projection();
GPU_matrix_push();
GPU_matrix_identity_set();
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
/* back */
if (block->flag & UI_BLOCK_RADIAL) {
ui_draw_pie_center(block);
}
else if (block->flag & UI_BLOCK_POPOVER) {
- ui_draw_popover_back(ar, &style, block, &rect);
+ ui_draw_popover_back(region, &style, block, &rect);
}
else if (block->flag & UI_BLOCK_LOOP) {
ui_draw_menu_back(&style, block, &rect);
}
else if (block->panel) {
- bool show_background = ar->alignment != RGN_ALIGN_FLOAT;
+ bool show_background = region->alignment != RGN_ALIGN_FLOAT;
if (show_background) {
if (block->panel->type && (block->panel->type->flag & PNL_NO_HEADER)) {
- if (ar->regiontype == RGN_TYPE_TOOLS) {
+ if (region->regiontype == RGN_TYPE_TOOLS) {
/* We never want a background around active tools. */
show_background = false;
}
else {
/* Without a header there is no background except for region overlap. */
- show_background = ar->overlap != 0;
+ show_background = region->overlap != 0;
}
}
}
- ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar), show_background);
+ ui_draw_aligned_panel(
+ &style, block, &rect, UI_panel_category_is_visible(region), show_background);
}
BLF_batch_draw_begin();
@@ -1886,12 +1931,12 @@ void UI_block_draw(const bContext *C, uiBlock *block)
/* widgets */
for (but = block->buttons.first; but; but = but->next) {
if (!(but->flag & (UI_HIDDEN | UI_SCROLLED))) {
- ui_but_to_pixelrect(&rect, ar, block, but);
+ ui_but_to_pixelrect(&rect, region, block, but);
/* XXX: figure out why invalid coordinates happen when closing render window */
/* and material preview is redrawn in main window (temp fix for bug #23848) */
if (rect.xmin < rect.xmax && rect.ymin < rect.ymax) {
- ui_draw_but(C, ar, &style, but, &rect);
+ ui_draw_but(C, region, &style, but, &rect);
}
}
}
@@ -1905,11 +1950,11 @@ void UI_block_draw(const bContext *C, uiBlock *block)
GPU_matrix_pop();
}
-static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlock *block)
+static void ui_block_message_subscribe(ARegion *region, struct wmMsgBus *mbus, uiBlock *block)
{
uiBut *but_prev = NULL;
/* possibly we should keep the region this block is contained in? */
- for (uiBut *but = block->buttons.first; but; but = but->next) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (but->rnapoin.type && but->rnaprop) {
/* quick check to avoid adding buttons representing a vector, multiple times. */
if ((but_prev && (but_prev->rnaprop == but->rnaprop) &&
@@ -1921,8 +1966,8 @@ static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlo
&but->rnapoin,
but->rnaprop,
&(const wmMsgSubscribeValue){
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
},
__func__);
@@ -1932,10 +1977,10 @@ static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlo
}
}
-void UI_region_message_subscribe(ARegion *ar, struct wmMsgBus *mbus)
+void UI_region_message_subscribe(ARegion *region, struct wmMsgBus *mbus)
{
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
- ui_block_message_subscribe(ar, mbus, block);
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
+ ui_block_message_subscribe(region, mbus, block);
}
}
@@ -3181,8 +3226,12 @@ static void ui_but_free(const bContext *C, uiBut *but)
MEM_freeN(but->hold_argN);
}
- if (but->free_search_arg) {
- MEM_SAFE_FREE(but->search_arg);
+ if (but->search != NULL) {
+ if (but->search->arg_free_fn) {
+ but->search->arg_free_fn(but->search->arg);
+ but->search->arg = NULL;
+ }
+ MEM_freeN(but->search);
}
if (but->active) {
@@ -3248,7 +3297,7 @@ void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb)
ARegion *region = CTX_wm_region(C);
wmWindow *window = CTX_wm_window(C);
- for (uiBlock *block = lb->first; block; block = block->next) {
+ LISTBASE_FOREACH (uiBlock *, block, lb) {
if (block->active) {
ui_update_window_matrix(window, region, block);
}
@@ -3257,7 +3306,7 @@ void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb)
void UI_blocklist_draw(const bContext *C, const ListBase *lb)
{
- for (uiBlock *block = lb->first; block; block = block->next) {
+ LISTBASE_FOREACH (uiBlock *, block, lb) {
if (block->active) {
UI_block_draw(C, block);
}
@@ -4089,9 +4138,9 @@ static void ui_def_but_rna__panel_type(bContext *C, uiLayout *layout, void *but_
void ui_but_rna_menu_convert_to_panel_type(uiBut *but, const char *panel_type)
{
- BLI_assert(but->type == UI_BTYPE_MENU);
- BLI_assert(but->menu_create_func == ui_def_but_rna__menu);
- BLI_assert((void *)but->poin == but);
+ BLI_assert(ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_COLOR));
+ // BLI_assert(but->menu_create_func == ui_def_but_rna__menu);
+ // BLI_assert((void *)but->poin == but);
but->menu_create_func = ui_def_but_rna__panel_type;
but->func_argN = BLI_strdup(panel_type);
}
@@ -4413,6 +4462,48 @@ uiBut *uiDefBut(uiBlock *block,
return but;
}
+uiBut *uiDefButImage(
+ uiBlock *block, void *imbuf, int x, int y, short width, short height, const uchar color[4])
+{
+ uiBut *but = ui_def_but(
+ block, UI_BTYPE_IMAGE, 0, "", x, y, width, height, imbuf, 0, 0, 0, 0, "");
+ if (color) {
+ copy_v4_v4_uchar(but->col, color);
+ }
+ else {
+ but->col[0] = 255;
+ but->col[1] = 255;
+ but->col[2] = 255;
+ but->col[3] = 255;
+ }
+ ui_but_update(but);
+ return but;
+}
+
+uiBut *uiDefButAlert(uiBlock *block, int icon, int x, int y, short width, short height)
+{
+ struct ImBuf *ibuf = UI_alert_image(icon);
+
+ if (icon == ALERT_ICON_BLENDER) {
+ return uiDefButImage(block, ibuf, x, y, width, height, NULL);
+ }
+ else {
+ uchar icon_color[4];
+ ThemeColorID color_id = TH_INFO_WARNING;
+ if (icon == ALERT_ICON_ERROR) {
+ color_id = TH_INFO_ERROR;
+ }
+ else if (icon == ALERT_ICON_INFO) {
+ color_id = TH_INFO_INFO;
+ }
+ else if (icon == ALERT_ICON_QUESTION) {
+ color_id = TH_INFO_PROPERTY;
+ }
+ UI_GetThemeColorType4ubv(color_id, SPACE_INFO, icon_color);
+ return uiDefButImage(block, ibuf, x, y, width, height, icon_color);
+ }
+}
+
/**
* if \a _x_ is a power of two (only one bit) return the power,
* otherwise return -1.
@@ -6260,34 +6351,51 @@ uiBut *uiDefSearchBut(uiBlock *block,
}
/**
- * \param search_func, bfunc: both get it as \a arg.
- * \param arg: user value,
- * \param active: when set, button opens with this item visible and selected.
+ * \note The item-pointer (referred to below) is a per search item user pointer
+ * passed to #UI_search_item_add (stored in #uiSearchItems.pointers).
+ *
+ * \param search_create_fn: Function to create the menu.
+ * \param search_update_fn: Function to refresh search content after the search text has changed.
+ * \param arg: user value.
+ * \param search_arg_free_fn: When non-null, use this function to free \a arg.
+ * \param search_exec_fn: Function that executes the action, gets \a arg as the first argument.
+ * The second argument as the active item-pointer
+ * \param active: When non-null, this item-pointer item will be visible and selected,
+ * otherwise the first item will be selected.
*/
void UI_but_func_search_set(uiBut *but,
- uiButSearchCreateFunc search_create_func,
- uiButSearchFunc search_func,
+ uiButSearchCreateFn search_create_fn,
+ uiButSearchUpdateFn search_update_fn,
void *arg,
- bool free_arg,
- uiButHandleFunc bfunc,
+ uiButSearchArgFreeFn search_arg_free_fn,
+ uiButHandleFunc search_exec_fn,
void *active)
{
/* needed since callers don't have access to internal functions
* (as an alternative we could expose it) */
- if (search_create_func == NULL) {
- search_create_func = ui_searchbox_create_generic;
+ if (search_create_fn == NULL) {
+ search_create_fn = ui_searchbox_create_generic;
}
- if (but->free_search_arg) {
- MEM_SAFE_FREE(but->search_arg);
+ struct uiButSearchData *search = but->search;
+ if (search != NULL) {
+ if (search->arg_free_fn != NULL) {
+ search->arg_free_fn(but->search->arg);
+ search->arg = NULL;
+ }
+ }
+ else {
+ search = MEM_callocN(sizeof(*but->search), __func__);
+ but->search = search;
}
- but->search_create_func = search_create_func;
- but->search_func = search_func;
- but->search_arg = arg;
- but->free_search_arg = free_arg;
+ search->create_fn = search_create_fn;
+ search->update_fn = search_update_fn;
- if (bfunc) {
+ search->arg = arg;
+ search->arg_free_fn = search_arg_free_fn;
+
+ if (search_exec_fn) {
#ifdef DEBUG
if (but->func) {
/* watch this, can be cause of much confusion, see: T47691 */
@@ -6295,7 +6403,7 @@ void UI_but_func_search_set(uiBut *but,
__func__);
}
#endif
- UI_but_func_set(but, bfunc, arg, active);
+ UI_but_func_set(but, search_exec_fn, search->arg, active);
}
/* search buttons show red-alert if item doesn't exist, not for menus */
@@ -6307,11 +6415,33 @@ void UI_but_func_search_set(uiBut *but,
}
}
+void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn)
+{
+ struct uiButSearchData *search = but->search;
+ search->context_menu_fn = context_menu_fn;
+}
+
+/**
+ * \param separator_string: when not NULL, this string is used as a separator,
+ * showing the icon and highlighted text after the last instance of this string.
+ */
+void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string)
+{
+ struct uiButSearchData *search = but->search;
+ search->sep_string = search_sep_string;
+}
+
+void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn)
+{
+ struct uiButSearchData *search = but->search;
+ search->tooltip_fn = tooltip_fn;
+}
+
/* Callbacks for operator search button. */
-static void operator_enum_search_cb(const struct bContext *C,
- void *but,
- const char *str,
- uiSearchItems *items)
+static void operator_enum_search_update_fn(const struct bContext *C,
+ void *but,
+ const char *str,
+ uiSearchItems *items)
{
wmOperatorType *ot = ((uiBut *)but)->optype;
PropertyRNA *prop = ot->prop;
@@ -6336,8 +6466,7 @@ static void operator_enum_search_cb(const struct bContext *C,
/* note: need to give the index rather than the
* identifier because the enum can be freed */
if (BLI_strcasestr(item->name, str)) {
- if (false ==
- UI_search_item_add(items, item->name, POINTER_FROM_INT(item->value), item->icon)) {
+ if (!UI_search_item_add(items, item->name, POINTER_FROM_INT(item->value), item->icon, 0)) {
break;
}
}
@@ -6349,7 +6478,7 @@ static void operator_enum_search_cb(const struct bContext *C,
}
}
-static void operator_enum_call_cb(struct bContext *UNUSED(C), void *but, void *arg2)
+static void operator_enum_search_exec_fn(struct bContext *UNUSED(C), void *but, void *arg2)
{
wmOperatorType *ot = ((uiBut *)but)->optype;
PointerRNA *opptr = UI_but_operator_ptr_get(but); /* Will create it if needed! */
@@ -6392,10 +6521,10 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block,
but = uiDefSearchBut(block, arg, retval, icon, maxlen, x, y, width, height, a1, a2, tip);
UI_but_func_search_set(but,
ui_searchbox_create_generic,
- operator_enum_search_cb,
+ operator_enum_search_update_fn,
but,
- false,
- operator_enum_call_cb,
+ NULL,
+ operator_enum_search_exec_fn,
NULL);
but->optype = ot;
@@ -6410,6 +6539,13 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block,
return but;
}
+void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4])
+{
+ but->flag |= UI_BUT_NODE_LINK;
+ but->custom_data = socket;
+ rgba_float_to_uchar(but->col, draw_color);
+}
+
/**
* push a new event onto event queue to activate the given button
* (usually a text-field) upon entering a popup
@@ -6538,8 +6674,8 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
}
else {
/* Not all menus are from Python. */
- if (mt->ext.srna) {
- const char *t = RNA_struct_ui_description(mt->ext.srna);
+ if (mt->rna_ext.srna) {
+ const char *t = RNA_struct_ui_description(mt->rna_ext.srna);
if (t && t[0]) {
tmp = BLI_strdup(t);
}
@@ -6556,7 +6692,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
}
else {
/* Not all panels are from Python. */
- if (pt->ext.srna) {
+ if (pt->rna_ext.srna) {
/* Panels don't yet have descriptions, this may be added. */
}
}
@@ -6575,7 +6711,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
MenuType *mt = UI_but_menutype_get(but);
if (mt) {
- _tmp = RNA_struct_translation_context(mt->ext.srna);
+ _tmp = RNA_struct_translation_context(mt->rna_ext.srna);
}
}
if (BLT_is_default_context(_tmp)) {
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index c058fefb4fa..09811fab52d 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -122,9 +122,9 @@ bool ui_but_can_align(const uiBut *but)
(BLI_rctf_size_y(&but->rect) > 0.0f));
}
-int ui_but_align_opposite_to_area_align_get(const ARegion *ar)
+int ui_but_align_opposite_to_area_align_get(const ARegion *region)
{
- switch (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment)) {
+ switch (RGN_ALIGN_ENUM_FROM_MASK(region->alignment)) {
case RGN_ALIGN_TOP:
return UI_BUT_ALIGN_DOWN;
case RGN_ALIGN_BOTTOM:
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 15fc23bc539..8c9768f523d 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -28,12 +28,14 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
+#include "BKE_fcurve_driver.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_nla.h"
@@ -114,10 +116,40 @@ void ui_but_anim_flag(uiBut *but, float cfra)
}
}
+static uiBut *ui_but_anim_decorate_find_attached_button(uiBut *but_decorate)
+{
+ uiBut *but_iter = NULL;
+
+ BLI_assert(UI_but_is_decorator(but_decorate));
+ BLI_assert(but_decorate->rnasearchpoin.data && but_decorate->rnasearchprop);
+
+ LISTBASE_CIRCULAR_BACKWARD_BEGIN (&but_decorate->block->buttons, but_iter, but_decorate->prev) {
+ if (but_iter != but_decorate &&
+ ui_but_rna_equals_ex(but_iter,
+ &but_decorate->rnasearchpoin,
+ but_decorate->rnasearchprop,
+ POINTER_AS_INT(but_decorate->custom_data))) {
+ return but_iter;
+ }
+ }
+ LISTBASE_CIRCULAR_BACKWARD_END(&but_decorate->block->buttons, but_iter, but_decorate->prev);
+
+ return NULL;
+}
+
void ui_but_anim_decorate_update_from_flag(uiBut *but)
{
- BLI_assert(UI_but_is_decorator(but) && but->prev);
- int flag = but->prev->flag;
+ const uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but);
+
+ if (!but_anim) {
+ printf("Could not find button with matching property to decorate (%s.%s)\n",
+ RNA_struct_identifier(but->rnasearchpoin.type),
+ RNA_property_identifier(but->rnasearchprop));
+ return;
+ }
+
+ int flag = but_anim->flag;
+
if (flag & UI_BUT_DRIVEN) {
but->icon = ICON_DECORATE_DRIVER;
}
@@ -289,22 +321,26 @@ void ui_but_anim_paste_driver(bContext *C)
void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
{
wmWindowManager *wm = CTX_wm_manager(C);
- uiBut *but = arg_but;
- but = but->prev;
+ uiBut *but_decorate = arg_but;
+ uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but_decorate);
+
+ if (!but_anim) {
+ return;
+ }
/* FIXME(campbell), swapping active pointer is weak. */
- SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+ SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active);
wm->op_undo_depth++;
- if (but->flag & UI_BUT_DRIVEN) {
+ if (but_anim->flag & UI_BUT_DRIVEN) {
/* pass */
/* TODO: report? */
}
- else if (but->flag & UI_BUT_ANIMATED_KEY) {
+ else if (but_anim->flag & UI_BUT_ANIMATED_KEY) {
PointerRNA props_ptr;
wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false);
WM_operator_properties_create_ptr(&props_ptr, ot);
- RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+ RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
WM_operator_properties_free(&props_ptr);
}
@@ -312,11 +348,11 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)
PointerRNA props_ptr;
wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false);
WM_operator_properties_create_ptr(&props_ptr, ot);
- RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+ RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
WM_operator_properties_free(&props_ptr);
}
- SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+ SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active);
wm->op_undo_depth--;
}
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index ae6a71f17e6..cc370113422 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -38,8 +38,8 @@
#include "BKE_idprop.h"
#include "BKE_screen.h"
-#include "ED_screen.h"
#include "ED_keyframing.h"
+#include "ED_screen.h"
#include "UI_interface.h"
@@ -160,7 +160,7 @@ static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event))
shortcut_free_operator_property(prop);
}
-static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
+static uiBlock *menu_change_shortcut(bContext *C, ARegion *region, void *arg)
{
wmWindowManager *wm = CTX_wm_manager(C);
uiBlock *block;
@@ -169,7 +169,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
wmKeyMapItem *kmi;
PointerRNA ptr;
uiLayout *layout;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
IDProperty *prop;
const char *idname = shortcut_get_operator_property(C, but, &prop);
@@ -186,7 +186,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
- block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
UI_block_func_handle_set(block, but_shortcut_name_func, but);
UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
UI_block_direction_set(block, UI_DIR_CENTER_Y);
@@ -216,7 +216,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
static int g_kmi_id_hack;
#endif
-static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
+static uiBlock *menu_add_shortcut(bContext *C, ARegion *region, void *arg)
{
wmWindowManager *wm = CTX_wm_manager(C);
uiBlock *block;
@@ -225,7 +225,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
wmKeyMapItem *kmi;
PointerRNA ptr;
uiLayout *layout;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
int kmi_id;
IDProperty *prop;
const char *idname = shortcut_get_operator_property(C, but, &prop);
@@ -233,7 +233,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
/* XXX this guess_opname can potentially return a different keymap
* than being found on adding later... */
km = WM_keymap_guess_opname(C, idname);
- kmi = WM_keymap_add_item(km, idname, AKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(km, idname, EVT_AKEY, KM_PRESS, 0, 0);
kmi_id = kmi->id;
/* This takes ownership of prop, or prop can be NULL for reset. */
@@ -248,7 +248,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
- block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
UI_block_func_handle_set(block, but_shortcut_name_func, but);
UI_block_direction_set(block, UI_DIR_CENTER_Y);
@@ -962,7 +962,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
const PropertyType prop_type = RNA_property_type(but->rnaprop);
if (((prop_type == PROP_POINTER) ||
(prop_type == PROP_STRING && but->type == UI_BTYPE_SEARCH_MENU &&
- but->search_func == ui_rna_collection_search_cb)) &&
+ but->search->update_fn == ui_rna_collection_search_update_fn)) &&
ui_jump_to_target_button_poll(C)) {
uiItemO(layout,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Jump to Target"),
@@ -1194,22 +1194,22 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
/* Show header tools for header buttons. */
if (ui_block_is_popup_any(but->block) == false) {
- const ARegion *ar = CTX_wm_region(C);
+ const ARegion *region = CTX_wm_region(C);
- if (!ar) {
+ if (!region) {
/* skip */
}
- else if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ else if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
}
- else if (ar->regiontype == RGN_TYPE_NAV_BAR) {
+ else if (region->regiontype == RGN_TYPE_NAV_BAR) {
uiItemMenuF(layout,
IFACE_("Navigation Bar"),
ICON_NONE,
ED_screens_navigation_bar_tools_menu_create,
NULL);
}
- else if (ar->regiontype == RGN_TYPE_FOOTER) {
+ else if (region->regiontype == RGN_TYPE_FOOTER) {
uiItemMenuF(layout, IFACE_("Footer"), ICON_NONE, ED_screens_footer_tools_menu_create, NULL);
}
}
@@ -1231,10 +1231,10 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
/**
* menu to show when right clicking on the panel header
*/
-void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa)
+void ui_popup_context_menu_for_panel(bContext *C, ARegion *region, Panel *panel)
{
- bScreen *sc = CTX_wm_screen(C);
- const bool has_panel_category = UI_panel_category_is_visible(ar);
+ bScreen *screen = CTX_wm_screen(C);
+ const bool has_panel_category = UI_panel_category_is_visible(region);
const bool any_item_visible = has_panel_category;
PointerRNA ptr;
uiPopupMenu *pup;
@@ -1243,11 +1243,11 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa)
if (!any_item_visible) {
return;
}
- if (pa->type->parent != NULL) {
+ if (panel->type->parent != NULL) {
return;
}
- RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr);
+ RNA_pointer_create(&screen->id, &RNA_Panel, panel, &ptr);
pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 31cbd2a3831..499d2f7f1fa 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -25,27 +25,27 @@
#include <string.h>
#include "DNA_color_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_movieclip_types.h"
#include "DNA_curveprofile_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_screen_types.h"
#include "BLI_math.h"
+#include "BLI_polyfill_2d.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLI_polyfill_2d.h"
#include "MEM_guardedalloc.h"
#include "BKE_colorband.h"
#include "BKE_colortools.h"
+#include "BKE_curveprofile.h"
#include "BKE_node.h"
#include "BKE_tracking.h"
-#include "BKE_curveprofile.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "IMB_colormanagement.h"
#include "BIF_glutil.h"
@@ -80,14 +80,14 @@ int UI_draw_roundbox_corner_get(void)
}
#endif
-void UI_draw_roundbox_3ubAlpha(bool filled,
- float minx,
- float miny,
- float maxx,
- float maxy,
- float rad,
- const uchar col[3],
- uchar alpha)
+void UI_draw_roundbox_3ub_alpha(bool filled,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ float rad,
+ const uchar col[3],
+ uchar alpha)
{
float colv[4];
colv[0] = ((float)col[0]) / 255;
@@ -97,14 +97,14 @@ void UI_draw_roundbox_3ubAlpha(bool filled,
UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
}
-void UI_draw_roundbox_3fvAlpha(bool filled,
- float minx,
- float miny,
- float maxx,
- float maxy,
- float rad,
- const float col[3],
- float alpha)
+void UI_draw_roundbox_3fv_alpha(bool filled,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ float rad,
+ const float col[3],
+ float alpha)
{
float colv[4];
colv[0] = col[0];
@@ -692,7 +692,7 @@ void ui_draw_but_TAB_outline(const rcti *rect,
immUnbindProgram();
}
-void ui_draw_but_IMAGE(ARegion *UNUSED(ar),
+void ui_draw_but_IMAGE(ARegion *UNUSED(region),
uiBut *but,
const uiWidgetColors *UNUSED(wcol),
const rcti *rect)
@@ -707,9 +707,6 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar),
return;
}
- float facx = 1.0f;
- float facy = 1.0f;
-
int w = BLI_rcti_size_x(rect);
int h = BLI_rcti_size_y(rect);
@@ -722,10 +719,18 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar),
# endif
GPU_blend(true);
+ /* Combine with premultiplied alpha. */
+ GPU_blend_set_func_separate(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
if (w != ibuf->x || h != ibuf->y) {
- facx = (float)w / (float)ibuf->x;
- facy = (float)h / (float)ibuf->y;
+ /* We scale the bitmap, rather than have OGL do a worse job. */
+ IMB_scaleImBuf(ibuf, w, h);
+ }
+
+ float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ if (but->col[3] != 0) {
+ /* Optionally use uiBut's col to recolor the image. */
+ rgba_uchar_to_float(col, but->col);
}
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
@@ -738,11 +743,14 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar),
GL_UNSIGNED_BYTE,
GL_NEAREST,
ibuf->rect,
- facx,
- facy,
- NULL);
+ 1.0f,
+ 1.0f,
+ col);
GPU_blend(false);
+ /* Reset default. */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
# if 0
// restore scissortest
@@ -872,7 +880,7 @@ static void histogram_draw_one(float r,
#define HISTOGRAM_TOT_GRID_LINES 4
-void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar),
+void ui_draw_but_HISTOGRAM(ARegion *UNUSED(region),
uiBut *but,
const uiWidgetColors *UNUSED(wcol),
const rcti *recti)
@@ -985,7 +993,7 @@ static void waveform_draw_one(float *waveform, int nbr, const float col[3])
GPU_batch_discard(batch);
}
-void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar),
+void ui_draw_but_WAVEFORM(ARegion *UNUSED(region),
uiBut *but,
const uiWidgetColors *UNUSED(wcol),
const rcti *recti)
@@ -1330,7 +1338,7 @@ static void vectorscope_draw_target(
immEnd();
}
-void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar),
+void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(region),
uiBut *but,
const uiWidgetColors *UNUSED(wcol),
const rcti *recti)
@@ -1736,11 +1744,11 @@ void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rec
/* sphere color */
float diffuse[3] = {1.0f, 1.0f, 1.0f};
float light[3];
- float size;
+ const float size = 0.5f * min_ff(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
/* backdrop */
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_3ubAlpha(
+ UI_draw_roundbox_3ub_alpha(
true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, wcol->inner, 255);
glCullFace(GL_BACK);
@@ -1752,11 +1760,10 @@ void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rec
/* transform to button */
GPU_matrix_push();
- if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect)) {
- size = 0.5f * BLI_rcti_size_x(rect);
- }
- else {
- size = 0.5f * BLI_rcti_size_y(rect);
+ bool use_project_matrix = (size >= -GPU_MATRIX_ORTHO_CLIP_NEAR_DEFAULT);
+ if (use_project_matrix) {
+ GPU_matrix_push_projection();
+ GPU_matrix_ortho_set_z(-size, size);
}
GPU_matrix_translate_2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect),
@@ -1784,6 +1791,10 @@ void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rec
GPU_blend(false);
GPU_line_smooth(false);
+ if (use_project_matrix) {
+ GPU_matrix_pop_projection();
+ }
+
/* matrix after circle */
GPU_matrix_pop();
@@ -1845,7 +1856,7 @@ static void gl_shaded_color(const uchar *color, int shade)
immUniformColor3ubv(color_shaded);
}
-void ui_draw_but_CURVE(ARegion *ar, uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
+void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
{
CurveMapping *cumap;
@@ -1886,7 +1897,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, const uiWidgetColors *wcol, cons
.xmax = rect->xmax,
.ymax = rect->ymax,
};
- rcti scissor_region = {0, ar->winx, 0, ar->winy};
+ rcti scissor_region = {0, region->winx, 0, region->winy};
BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
GPU_scissor(scissor_new.xmin,
scissor_new.ymin,
@@ -2121,7 +2132,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, const uiWidgetColors *wcol, cons
}
/** Used to draw a curve profile widget. Somewhat similar to ui_draw_but_CURVE */
-void ui_draw_but_CURVEPROFILE(ARegion *ar,
+void ui_draw_but_CURVEPROFILE(ARegion *region,
uiBut *but,
const uiWidgetColors *wcol,
const rcti *rect)
@@ -2156,7 +2167,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *ar,
.xmax = rect->xmax,
.ymax = rect->ymax,
};
- rcti scissor_region = {0, ar->winx, 0, ar->winy};
+ rcti scissor_region = {0, region->winx, 0, region->winy};
BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
GPU_scissor(scissor_new.xmin,
scissor_new.ymin,
@@ -2345,7 +2356,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *ar,
immUnbindProgram();
}
-void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar),
+void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region),
uiBut *but,
const uiWidgetColors *UNUSED(wcol),
const rcti *recti)
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 988dea270f5..817cb44db29 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -21,8 +21,8 @@
* \ingroup edinterface
*/
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "BLI_blenlib.h"
@@ -54,14 +54,14 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Eyedropper Modal Map");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Eyedropper Modal Map");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return NULL;
}
- keymap = WM_modalkeymap_add(keyconf, "Eyedropper Modal Map", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "Eyedropper Modal Map", modal_items);
/* assign to operators */
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_colorramp");
@@ -84,12 +84,12 @@ wmKeyMap *eyedropper_colorband_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Eyedropper ColorRamp PointSampling Map");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Eyedropper ColorRamp PointSampling Map");
if (keymap && keymap->modal_items) {
return keymap;
}
- keymap = WM_modalkeymap_add(
+ keymap = WM_modalkeymap_ensure(
keyconf, "Eyedropper ColorRamp PointSampling Map", modal_items_point);
/* assign to operators */
@@ -106,7 +106,7 @@ wmKeyMap *eyedropper_colorband_modal_keymap(wmKeyConfig *keyconf)
/** \name Generic Shared Functions
* \{ */
-void eyedropper_draw_cursor_text(const struct bContext *C, const ARegion *ar, const char *name)
+void eyedropper_draw_cursor_text(const struct bContext *C, const ARegion *region, const char *name)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
wmWindow *win = CTX_wm_window(C);
@@ -115,12 +115,12 @@ void eyedropper_draw_cursor_text(const struct bContext *C, const ARegion *ar, co
const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f};
const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f};
- if ((name[0] == '\0') || (BLI_rcti_isect_pt(&ar->winrct, x, y) == false)) {
+ if ((name[0] == '\0') || (BLI_rcti_isect_pt(&region->winrct, x, y) == false)) {
return;
}
- x = x - ar->winrct.xmin;
- y = y - ar->winrct.ymin;
+ x = x - region->winrct.xmin;
+ y = y - region->winrct.ymin;
y += U.widget_unit;
@@ -139,10 +139,10 @@ void eyedropper_draw_cursor_text(const struct bContext *C, const ARegion *ar, co
uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event)
{
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y);
- ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_ANY, event->x, event->y);
+ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y);
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_ANY, event->x, event->y);
- uiBut *but = ui_but_find_mouse_over(ar, event);
+ uiBut *but = ui_but_find_mouse_over(region, event);
if (ELEM(NULL, but, but->rnapoin.data, but->rnaprop)) {
return NULL;
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index 2b5cf2ed6b9..7527a1e0662 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -28,8 +28,8 @@
#include "MEM_guardedalloc.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "BLI_math_vector.h"
@@ -52,9 +52,9 @@
#include "interface_intern.h"
+#include "ED_clip.h"
#include "ED_image.h"
#include "ED_node.h"
-#include "ED_clip.h"
#include "interface_eyedropper_intern.h"
@@ -137,40 +137,40 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
/* we could use some clever */
Main *bmain = CTX_data_main(C);
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
const char *display_device = CTX_data_scene(C)->display_settings.display_device;
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
- if (sa) {
- if (sa->spacetype == SPACE_IMAGE) {
- ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
- if (ar) {
- SpaceImage *sima = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
+ if (area) {
+ if (area->spacetype == SPACE_IMAGE) {
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
+ if (region) {
+ SpaceImage *sima = area->spacedata.first;
+ int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
- if (ED_space_image_color_sample(sima, ar, mval, r_col)) {
+ if (ED_space_image_color_sample(sima, region, mval, r_col)) {
return;
}
}
}
- else if (sa->spacetype == SPACE_NODE) {
- ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
- if (ar) {
- SpaceNode *snode = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
+ else if (area->spacetype == SPACE_NODE) {
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
+ if (region) {
+ SpaceNode *snode = area->spacedata.first;
+ int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
- if (ED_space_node_color_sample(bmain, snode, ar, mval, r_col)) {
+ if (ED_space_node_color_sample(bmain, snode, region, mval, r_col)) {
return;
}
}
}
- else if (sa->spacetype == SPACE_CLIP) {
- ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
- if (ar) {
- SpaceClip *sc = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
+ else if (area->spacetype == SPACE_CLIP) {
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
+ if (region) {
+ SpaceClip *sc = area->spacedata.first;
+ int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
- if (ED_space_clip_color_sample(sc, ar, mval, r_col)) {
+ if (ED_space_clip_color_sample(sc, region, mval, r_col)) {
return;
}
}
diff --git a/source/blender/editors/interface/interface_eyedropper_colorband.c b/source/blender/editors/interface/interface_eyedropper_colorband.c
index 479cf9ccffe..be23eacafff 100644
--- a/source/blender/editors/interface/interface_eyedropper_colorband.c
+++ b/source/blender/editors/interface/interface_eyedropper_colorband.c
@@ -38,8 +38,8 @@
#include "BLI_bitmap_draw_2d.h"
#include "BLI_math_vector.h"
-#include "BKE_context.h"
#include "BKE_colorband.h"
+#include "BKE_context.h"
#include "RNA_access.h"
diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c
index fd5a46e7716..d9c77c26941 100644
--- a/source/blender/editors/interface/interface_eyedropper_datablock.c
+++ b/source/blender/editors/interface/interface_eyedropper_datablock.c
@@ -28,18 +28,18 @@
#include "MEM_guardedalloc.h"
-#include "DNA_space_types.h"
-#include "DNA_screen_types.h"
#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "BLI_string.h"
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
+#include "BKE_idtype.h"
#include "BKE_report.h"
-#include "BKE_idcode.h"
+#include "BKE_screen.h"
#include "RNA_access.h"
@@ -48,13 +48,13 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_space_api.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "ED_view3d.h"
-#include "ED_outliner.h"
-#include "interface_intern.h"
#include "interface_eyedropper_intern.h"
+#include "interface_intern.h"
/**
* \note #DataDropper is only internal name to avoid confusion with other kinds of eye-droppers.
@@ -74,10 +74,10 @@ typedef struct DataDropper {
char name[200];
} DataDropper;
-static void datadropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
+static void datadropper_draw_cb(const struct bContext *C, ARegion *region, void *arg)
{
DataDropper *ddr = arg;
- eyedropper_draw_cursor_text(C, ar, ddr->name);
+ eyedropper_draw_cursor_text(C, region, ddr->name);
}
static int datadropper_init(bContext *C, wmOperator *op)
@@ -115,7 +115,7 @@ static int datadropper_init(bContext *C, wmOperator *op)
BLI_assert(ddr->idcode != 0);
/* Note we can translate here (instead of on draw time),
* because this struct has very short lifetime. */
- ddr->idcode_name = TIP_(BKE_idcode_to_name(ddr->idcode));
+ ddr->idcode_name = TIP_(BKE_idtype_idcode_to_name(ddr->idcode));
PointerRNA ptr = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
ddr->init_id = ptr.owner_id;
@@ -125,7 +125,9 @@ static int datadropper_init(bContext *C, wmOperator *op)
static void datadropper_exit(bContext *C, wmOperator *op)
{
- WM_cursor_modal_restore(CTX_wm_window(C));
+ wmWindow *win = CTX_wm_window(C);
+
+ WM_cursor_modal_restore(win);
if (op->customdata) {
DataDropper *ddr = (DataDropper *)op->customdata;
@@ -139,7 +141,7 @@ static void datadropper_exit(bContext *C, wmOperator *op)
op->customdata = NULL;
}
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(win);
}
/* *** datadropper id helper functions *** */
@@ -150,27 +152,27 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
{
/* we could use some clever */
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my);
+ ScrArea *area = BKE_screen_find_area_xy(screen, -1, mx, my);
ScrArea *area_prev = CTX_wm_area(C);
- ARegion *ar_prev = CTX_wm_region(C);
+ ARegion *region_prev = CTX_wm_region(C);
ddr->name[0] = '\0';
- if (sa) {
- if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_OUTLINER)) {
- ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
- if (ar) {
- const int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
+ if (area) {
+ if (ELEM(area->spacetype, SPACE_VIEW3D, SPACE_OUTLINER)) {
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
+ if (region) {
+ const int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
Base *base;
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
/* grr, always draw else we leave stale text */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
- if (sa->spacetype == SPACE_VIEW3D) {
+ if (area->spacetype == SPACE_VIEW3D) {
base = ED_view3d_give_base_under_cursor(C, mval);
}
else {
@@ -206,7 +208,7 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
}
CTX_wm_area_set(C, area_prev);
- CTX_wm_region_set(C, ar_prev);
+ CTX_wm_region_set(C, region_prev);
}
/* sets the ID, returns success */
@@ -248,22 +250,22 @@ static void datadropper_set_draw_callback_region(bContext *C,
const int my)
{
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my);
+ ScrArea *area = BKE_screen_find_area_xy(screen, -1, mx, my);
- if (sa) {
+ if (area) {
/* If spacetype changed */
- if (sa->spacetype != ddr->cursor_area->spacetype) {
+ if (area->spacetype != ddr->cursor_area->spacetype) {
/* Remove old callback */
ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
/* Redraw old area */
- ARegion *ar = BKE_area_find_region_type(ddr->cursor_area, RGN_TYPE_WINDOW);
- ED_region_tag_redraw(ar);
+ ARegion *region = BKE_area_find_region_type(ddr->cursor_area, RGN_TYPE_WINDOW);
+ ED_region_tag_redraw(region);
/* Set draw callback in new region */
- ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_WINDOW);
+ ARegionType *art = BKE_regiontype_from_id(area->type, RGN_TYPE_WINDOW);
- ddr->cursor_area = sa;
+ ddr->cursor_area = area;
ddr->art = art;
ddr->draw_handle_pixel = ED_region_draw_cb_activate(
art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index 8a48ca19db2..907da917e75 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -28,14 +28,14 @@
#include "MEM_guardedalloc.h"
-#include "DNA_space_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_object_types.h"
#include "DNA_camera_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
-#include "BLI_string.h"
#include "BLI_math_vector.h"
+#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -54,8 +54,8 @@
#include "ED_space_api.h"
#include "ED_view3d.h"
-#include "interface_intern.h"
#include "interface_eyedropper_intern.h"
+#include "interface_intern.h"
/**
* \note #DepthDropper is only internal name to avoid confusion with other kinds of eye-droppers.
@@ -77,10 +77,10 @@ typedef struct DepthDropper {
char name[200];
} DepthDropper;
-static void depthdropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
+static void depthdropper_draw_cb(const struct bContext *C, ARegion *region, void *arg)
{
DepthDropper *ddr = arg;
- eyedropper_draw_cursor_text(C, ar, ddr->name);
+ eyedropper_draw_cursor_text(C, region, ddr->name);
}
static int depthdropper_init(bContext *C, wmOperator *op)
@@ -156,40 +156,40 @@ static void depthdropper_depth_sample_pt(
{
/* we could use some clever */
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
Scene *scene = CTX_data_scene(C);
ScrArea *area_prev = CTX_wm_area(C);
- ARegion *ar_prev = CTX_wm_region(C);
+ ARegion *region_prev = CTX_wm_region(C);
ddr->name[0] = '\0';
- if (sa) {
- if (sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
- if (ar) {
+ if (area) {
+ if (area->spacetype == SPACE_VIEW3D) {
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
+ if (region) {
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = area->spacedata.first;
+ RegionView3D *rv3d = region->regiondata;
/* weak, we could pass in some reference point */
const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3];
- const int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
+ const int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
float co[3];
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
/* grr, always draw else we leave stale text */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(depsgraph, ar, v3d, mval, co, true, NULL)) {
- const float mval_center_fl[2] = {(float)ar->winx / 2, (float)ar->winy / 2};
+ if (ED_view3d_autodist(depsgraph, region, v3d, mval, co, true, NULL)) {
+ const float mval_center_fl[2] = {(float)region->winx / 2, (float)region->winy / 2};
float co_align[3];
/* quick way to get view-center aligned point */
- ED_view3d_win_to_3d(v3d, ar, co, mval_center_fl, co_align);
+ ED_view3d_win_to_3d(v3d, region, co, mval_center_fl, co_align);
*r_depth = len_v3v3(view_co, co_align);
@@ -209,7 +209,7 @@ static void depthdropper_depth_sample_pt(
}
CTX_wm_area_set(C, area_prev);
- CTX_wm_region_set(C, ar_prev);
+ CTX_wm_region_set(C, region_prev);
}
/* sets the sample depth RGB, maintaining A */
diff --git a/source/blender/editors/interface/interface_eyedropper_driver.c b/source/blender/editors/interface/interface_eyedropper_driver.c
index cc13367c190..89c087855bc 100644
--- a/source/blender/editors/interface/interface_eyedropper_driver.c
+++ b/source/blender/editors/interface/interface_eyedropper_driver.c
@@ -29,11 +29,11 @@
#include "MEM_guardedalloc.h"
#include "DNA_anim_types.h"
-#include "DNA_screen_types.h"
#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
-#include "BKE_context.h"
#include "BKE_animsys.h"
+#include "BKE_context.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -48,8 +48,8 @@
#include "ED_keyframing.h"
-#include "interface_intern.h"
#include "interface_eyedropper_intern.h"
+#include "interface_intern.h"
typedef struct DriverDropper {
/* Destination property (i.e. where we'll add a driver) */
diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
index 02d4596e93c..3d32ede60c2 100644
--- a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
@@ -28,6 +28,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLT_translation.h"
@@ -39,6 +40,7 @@
#include "BKE_gpencil.h"
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "UI_interface.h"
@@ -58,13 +60,15 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#include "interface_intern.h"
#include "interface_eyedropper_intern.h"
+#include "interface_intern.h"
typedef struct EyedropperGPencil {
struct ColorManagedDisplay *display;
/** color under cursor RGB */
float color[3];
+ /** Mode */
+ int mode;
} EyedropperGPencil;
/* Helper: Draw status message while the user is running the operator */
@@ -89,6 +93,7 @@ static bool eyedropper_gpencil_init(bContext *C, wmOperator *op)
display_device = scene->display_settings.display_device;
eye->display = IMB_colormanagement_display_get_named(display_device);
+ eye->mode = RNA_enum_get(op->ptr, "mode");
return true;
}
@@ -101,35 +106,19 @@ static void eyedropper_gpencil_exit(bContext *C, wmOperator *op)
MEM_SAFE_FREE(op->customdata);
}
-/* Set the material. */
-static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye)
+static void eyedropper_add_material(
+ bContext *C, float col_conv[4], const bool only_stroke, const bool only_fill, const bool both)
{
Main *bmain = CTX_data_main(C);
Object *ob = CTX_data_active_object(C);
Material *ma = NULL;
- const bool only_stroke = ((!event->ctrl) && (!event->shift));
- const bool only_fill = ((!event->ctrl) && (event->shift));
- const bool both = ((event->ctrl) && (event->shift));
-
- float col_conv[4];
bool found = false;
- /* Convert from linear rgb space to display space because grease pencil colors are in display
- * space, and this conversion is needed to undo the conversion to linear performed by
- * eyedropper_color_sample_fl. */
- if (eye->display) {
- copy_v3_v3(col_conv, eye->color);
- IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
- }
- else {
- copy_v3_v3(col_conv, eye->color);
- }
-
/* Look for a similar material in grease pencil slots. */
- short *totcol = give_totcolp(ob);
+ short *totcol = BKE_object_material_len_p(ob);
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_object_material_get(ob, i + 1);
if (ma == NULL) {
continue;
}
@@ -138,15 +127,15 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed
if (gp_style != NULL) {
/* Check stroke color. */
bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) &&
- (gp_style->flag & GP_STYLE_STROKE_SHOW);
+ (gp_style->flag & GP_MATERIAL_STROKE_SHOW);
/* Check fill color. */
bool found_fill = compare_v3v3(gp_style->fill_rgba, col_conv, 0.01f) &&
- (gp_style->flag & GP_STYLE_FILL_SHOW);
+ (gp_style->flag & GP_MATERIAL_FILL_SHOW);
- if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) {
+ if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) {
found = true;
}
- else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0)) {
+ else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0)) {
found = true;
}
else if ((both) && (found_stroke) && (found_fill)) {
@@ -180,22 +169,22 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed
/* Only create Stroke (default option). */
if (only_stroke) {
/* Stroke color. */
- gp_style_new->flag |= GP_STYLE_STROKE_SHOW;
- gp_style_new->flag &= ~GP_STYLE_FILL_SHOW;
+ gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW;
+ gp_style_new->flag &= ~GP_MATERIAL_FILL_SHOW;
copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
zero_v4(gp_style_new->fill_rgba);
}
/* Fill Only. */
else if (only_fill) {
/* Fill color. */
- gp_style_new->flag &= ~GP_STYLE_STROKE_SHOW;
- gp_style_new->flag |= GP_STYLE_FILL_SHOW;
+ gp_style_new->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ gp_style_new->flag |= GP_MATERIAL_FILL_SHOW;
zero_v4(gp_style_new->stroke_rgba);
copy_v3_v3(gp_style_new->fill_rgba, col_conv);
}
/* Stroke and Fill. */
else if (both) {
- gp_style_new->flag |= GP_STYLE_STROKE_SHOW | GP_STYLE_FILL_SHOW;
+ gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW | GP_MATERIAL_FILL_SHOW;
copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
copy_v3_v3(gp_style_new->fill_rgba, col_conv);
}
@@ -203,6 +192,69 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed
ED_undo_push(C, "Add Grease Pencil Material");
}
+/* Create a new palette color and palette if needed. */
+static void eyedropper_add_palette_color(bContext *C, float col_conv[4])
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ GpPaint *gp_paint = ts->gp_paint;
+ GpVertexPaint *gp_vertexpaint = ts->gp_vertexpaint;
+ Paint *paint = &gp_paint->paint;
+ Paint *vertexpaint = &gp_vertexpaint->paint;
+
+ /* Check for Palette in Draw and Vertex Paint Mode. */
+ if (paint->palette == NULL) {
+ paint->palette = BKE_palette_add(bmain, "Grease Pencil");
+ if (vertexpaint->palette == NULL) {
+ vertexpaint->palette = paint->palette;
+ }
+ }
+ /* Check if the color exist already. */
+ Palette *palette = paint->palette;
+ LISTBASE_FOREACH (PaletteColor *, palcolor, &palette->colors) {
+ if (compare_v3v3(palcolor->rgb, col_conv, 0.01f)) {
+ return;
+ }
+ }
+
+ /* Create Colors. */
+ PaletteColor *palcol = BKE_palette_color_add(palette);
+ if (palcol) {
+ copy_v3_v3(palcol->rgb, col_conv);
+ }
+}
+
+/* Set the material or the palette color. */
+static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye)
+{
+
+ const bool only_stroke = ((!event->ctrl) && (!event->shift));
+ const bool only_fill = ((!event->ctrl) && (event->shift));
+ const bool both = ((event->ctrl) && (event->shift));
+
+ float col_conv[4];
+
+ /* Convert from linear rgb space to display space because grease pencil colors are in display
+ * space, and this conversion is needed to undo the conversion to linear performed by
+ * eyedropper_color_sample_fl. */
+ if (eye->display) {
+ copy_v3_v3(col_conv, eye->color);
+ IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
+ }
+ else {
+ copy_v3_v3(col_conv, eye->color);
+ }
+
+ /* Add material or Palette color*/
+ if (eye->mode == 0) {
+ eyedropper_add_material(C, col_conv, only_stroke, only_fill, both);
+ }
+ else {
+ eyedropper_add_palette_color(C, col_conv);
+ }
+}
+
/* Sample the color below cursor. */
static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, int mx, int my)
{
@@ -307,6 +359,12 @@ static bool eyedropper_gpencil_poll(bContext *C)
void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot)
{
+ static const EnumPropertyItem items_mode[] = {
+ {0, "MATERIAL", 0, "Material", ""},
+ {1, "PALETTE", 0, "Palette", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
/* identifiers */
ot->name = "Grease Pencil Eyedropper";
ot->idname = "UI_OT_eyedropper_gpencil_color";
@@ -321,4 +379,7 @@ void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "mode", items_mode, 0, "Mode", "");
}
diff --git a/source/blender/editors/interface/interface_eyedropper_intern.h b/source/blender/editors/interface/interface_eyedropper_intern.h
index d9ec0657bfe..cabf997b725 100644
--- a/source/blender/editors/interface/interface_eyedropper_intern.h
+++ b/source/blender/editors/interface/interface_eyedropper_intern.h
@@ -25,7 +25,7 @@
/* interface_eyedropper.c */
void eyedropper_draw_cursor_text(const struct bContext *C,
- const struct ARegion *ar,
+ const struct ARegion *region,
const char *name);
uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 7332f3ee776..ebde1d54c07 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -21,13 +21,13 @@
* \ingroup edinterface
*/
+#include <assert.h>
+#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
@@ -36,28 +36,29 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
-#include "BLI_math.h"
-#include "BLI_listbase.h"
#include "BLI_linklist.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
#include "BLI_string.h"
-#include "BLI_string_utf8.h"
#include "BLI_string_cursor_utf8.h"
-#include "BLI_rect.h"
+#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
#include "PIL_time.h"
-#include "BKE_colorband.h"
#include "BKE_blender_undo.h"
#include "BKE_brush.h"
+#include "BKE_colorband.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
+#include "BKE_curveprofile.h"
+#include "BKE_movieclip.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_tracking.h"
#include "BKE_unit.h"
-#include "BKE_paint.h"
-#include "BKE_curveprofile.h"
#include "IMB_colormanagement.h"
@@ -78,9 +79,9 @@
#include "wm_event_system.h"
#ifdef WITH_INPUT_IME
-# include "wm_window.h"
-# include "BLT_translation.h"
# include "BLT_lang.h"
+# include "BLT_translation.h"
+# include "wm_window.h"
#endif
/* place the mouse at the scaled down location when un-grabbing */
@@ -334,12 +335,7 @@ typedef struct uiHandleButtonData {
int maxlen;
/* Button text selection:
* extension direction, selextend, inside ui_do_but_TEX */
- enum {
- EXTEND_NONE = 0,
- EXTEND_LEFT = 1,
- EXTEND_RIGHT = 2,
- } selextend;
- float selstartx;
+ int sel_pos_init;
/* allow to realloc str/editstr and use 'maxlen' to track alloc size (maxlen + 1) */
bool is_str_dynamic;
@@ -385,6 +381,9 @@ typedef struct uiHandleButtonData {
uiSelectContextStore select_others;
#endif
+ /* Text field undo. */
+ struct uiUndoStack_Text *undo_stack_text;
+
/* post activate */
uiButtonActivateType posttype;
uiBut *postbut;
@@ -420,18 +419,24 @@ typedef struct uiAfterFunc {
PointerRNA rnapoin;
PropertyRNA *rnaprop;
+ void *search_arg;
+ uiButSearchArgFreeFn search_arg_free_fn;
+
bContextStore *context;
char undostr[BKE_UNDO_STR_MAX];
} uiAfterFunc;
-static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type);
+static void button_activate_init(bContext *C,
+ ARegion *region,
+ uiBut *but,
+ uiButtonActivateType type);
static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
static void button_activate_exit(
bContext *C, uiBut *but, uiHandleButtonData *data, const bool mousemove, const bool onfree);
static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata);
static void ui_handle_button_activate(bContext *C,
- ARegion *ar,
+ ARegion *region,
uiBut *but,
uiButtonActivateType type);
@@ -476,7 +481,7 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
else {
lastdy += dy;
- if (ABS(lastdy) > (int)UI_UNIT_Y) {
+ if (abs(lastdy) > (int)UI_UNIT_Y) {
if (U.uiflag2 & USER_TRACKPAD_NATURAL) {
dy = -dy;
}
@@ -565,7 +570,7 @@ static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx)
}
if (data->draglock) {
- if (ABS(mx - data->dragstartx) <= BUTTON_DRAGLOCK_THRESH) {
+ if (abs(mx - data->dragstartx) <= BUTTON_DRAGLOCK_THRESH) {
return false;
}
#ifdef USE_DRAG_MULTINUM
@@ -630,8 +635,8 @@ static enum eSnapType ui_event_to_snap(const wmEvent *event)
static bool ui_event_is_snap(const wmEvent *event)
{
- return (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY) ||
- ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY));
+ return (ELEM(event->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) ||
+ ELEM(event->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY));
}
static void ui_color_snap_hue(const enum eSnapType snap, float *r_hue)
@@ -751,6 +756,13 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
after->rnapoin = but->rnapoin;
after->rnaprop = but->rnaprop;
+ if (but->search != NULL) {
+ after->search_arg_free_fn = but->search->arg_free_fn;
+ after->search_arg = but->search->arg;
+ but->search->arg_free_fn = NULL;
+ but->search->arg = NULL;
+ }
+
if (but->context) {
after->context = CTX_store_copy(but->context);
}
@@ -917,6 +929,10 @@ static void ui_apply_but_funcs_after(bContext *C)
MEM_freeN(after.rename_orig);
}
+ if (after.search_arg_free_fn) {
+ after.search_arg_free_fn(after.search_arg);
+ }
+
ui_afterfunc_update_preferences_dirty(&after);
if (after.undostr[0]) {
@@ -1256,7 +1272,7 @@ static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *dat
data->multi_data.bs_mbuts = UI_butstore_create(but_active->block);
- for (uiBut *but = but_active->block->buttons.first; but; but = but->next) {
+ LISTBASE_FOREACH (uiBut *, but, &but_active->block->buttons) {
if (but->flag & UI_BUT_DRAG_MULTI) {
ui_multibut_add(data, but);
}
@@ -1266,7 +1282,7 @@ static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *dat
* note: if we mix buttons which are proportional and others which are not,
* this may work a bit strangely */
if ((but_active->rnaprop && (RNA_property_flag(but_active->rnaprop) & PROP_PROPORTIONAL)) ||
- ELEM(but_active->unit_type, PROP_UNIT_LENGTH)) {
+ ELEM(but_active->unit_type, RNA_SUBTYPE_UNIT_VALUE(PROP_UNIT_LENGTH))) {
if (data->origvalue != 0.0) {
data->multi_data.is_proportional = true;
}
@@ -1275,7 +1291,7 @@ static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *dat
static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBlock *block)
{
- ARegion *ar = data->region;
+ ARegion *region = data->region;
const double value_delta = data->value - data->origvalue;
const double value_scale = data->multi_data.is_proportional ? (data->value / data->origvalue) :
0.0;
@@ -1292,7 +1308,7 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
if (mbut_state) {
void *active_back;
- ui_but_execute_begin(C, ar, but, &active_back);
+ ui_but_execute_begin(C, region, but, &active_back);
# ifdef USE_ALLSELECT
if (data->select_others.is_enabled) {
@@ -1330,7 +1346,7 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
/* clamp based on soft limits, see: T40154 */
CLAMP(but->active->value, (double)but->softmin, (double)but->softmax);
}
- ui_but_execute_end(C, ar, but, active_back);
+ ui_but_execute_end(C, region, but, active_back);
}
else {
/* highly unlikely */
@@ -1406,21 +1422,21 @@ typedef struct uiDragToggleHandle {
} uiDragToggleHandle;
static bool ui_drag_toggle_set_xy_xy(
- bContext *C, ARegion *ar, const int pushed_state, const int xy_src[2], const int xy_dst[2])
+ bContext *C, ARegion *region, const int pushed_state, const int xy_src[2], const int xy_dst[2])
{
/* popups such as layers won't re-evaluate on redraw */
- const bool do_check = (ar->regiontype == RGN_TYPE_TEMPORARY);
+ const bool do_check = (region->regiontype == RGN_TYPE_TEMPORARY);
bool changed = false;
uiBlock *block;
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
uiBut *but;
float xy_a_block[2] = {UNPACK2(xy_src)};
float xy_b_block[2] = {UNPACK2(xy_dst)};
- ui_window_to_block_fl(ar, block, &xy_a_block[0], &xy_a_block[1]);
- ui_window_to_block_fl(ar, block, &xy_b_block[0], &xy_b_block[1]);
+ ui_window_to_block_fl(region, block, &xy_a_block[0], &xy_a_block[1]);
+ ui_window_to_block_fl(region, block, &xy_b_block[0], &xy_b_block[1]);
for (but = block->buttons.first; but; but = but->next) {
/* Note: ctrl is always true here because (at least for now)
@@ -1433,7 +1449,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, ar, but);
+ UI_but_execute(C, region, but);
if (do_check) {
ui_but_update_edited(but);
}
@@ -1458,7 +1474,7 @@ static bool ui_drag_toggle_set_xy_xy(
static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const int xy_input[2])
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bool do_draw = false;
int xy[2];
@@ -1470,7 +1486,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const
*/
if (drag_info->is_xy_lock_init == false) {
/* first store the buttons original coords */
- uiBut *but = ui_but_find_mouse_over_ex(ar, xy_input[0], xy_input[1], true);
+ uiBut *but = ui_but_find_mouse_over_ex(region, xy_input[0], xy_input[1], true);
if (but) {
if (but->flag & UI_BUT_DRAG_LOCK) {
@@ -1503,10 +1519,10 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const
xy[1] = (drag_info->xy_lock[1] == false) ? xy_input[1] : drag_info->xy_last[1];
/* touch all buttons between last mouse coord and this one */
- do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->pushed_state, drag_info->xy_last, xy);
+ do_draw = ui_drag_toggle_set_xy_xy(C, region, drag_info->pushed_state, drag_info->xy_last, xy);
if (do_draw) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
copy_v2_v2_int(drag_info->xy_last, xy);
@@ -1538,8 +1554,9 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
if (done) {
wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
- uiBut *but = ui_but_find_mouse_over_ex(ar, drag_info->xy_init[0], drag_info->xy_init[1], true);
+ ARegion *region = CTX_wm_region(C);
+ uiBut *but = ui_but_find_mouse_over_ex(
+ region, drag_info->xy_init[0], drag_info->xy_init[1], true);
if (but) {
ui_apply_but_undo(but);
@@ -1552,7 +1569,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
false);
ui_handler_region_drag_toggle_remove(C, drag_info);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(win);
return WM_UI_HANDLER_BREAK;
}
else {
@@ -1843,7 +1860,7 @@ static bool ui_but_drag_init(bContext *C,
const wmEvent *event)
{
/* prevent other WM gestures to start while we try to drag */
- WM_gestures_remove(C);
+ WM_gestures_remove(CTX_wm_window(C));
/* Clamp the maximum to half the UI unit size so a high user preference
* doesn't require the user to drag more then half the default button height. */
@@ -1851,13 +1868,13 @@ static bool ui_but_drag_init(bContext *C,
WM_event_drag_threshold(event),
(int)((UI_UNIT_Y / 2) * ui_block_to_window_scale(data->region, but->block)));
- if (ABS(data->dragstartx - event->x) + ABS(data->dragstarty - event->y) > drag_threshold) {
+ if (abs(data->dragstartx - event->x) + abs(data->dragstarty - event->y) > drag_threshold) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
data->cancel = true;
#ifdef USE_DRAG_TOGGLE
if (ui_drag_toggle_but_is_supported(but)) {
uiDragToggleHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
- ARegion *ar_prev;
+ ARegion *region_prev;
/* call here because regular mouse-up event wont run,
* typically 'button_activate_exit()' handles this */
@@ -1870,7 +1887,7 @@ static bool ui_but_drag_init(bContext *C,
copy_v2_v2_int(drag_info->xy_last, &event->x);
/* needed for toggle drag on popups */
- ar_prev = CTX_wm_region(C);
+ region_prev = CTX_wm_region(C);
CTX_wm_region_set(C, data->region);
WM_event_add_ui_handler(C,
@@ -1880,7 +1897,7 @@ static bool ui_but_drag_init(bContext *C,
drag_info,
WM_HANDLER_BLOCKING);
- CTX_wm_region_set(C, ar_prev);
+ CTX_wm_region_set(C, region_prev);
/* Initialize alignment for single row/column regions,
* otherwise we use the relative position of the first other button dragged over. */
@@ -1889,13 +1906,13 @@ static bool ui_but_drag_init(bContext *C,
RGN_TYPE_HEADER,
RGN_TYPE_TOOL_HEADER,
RGN_TYPE_FOOTER)) {
- const int ar_alignment = RGN_ALIGN_ENUM_FROM_MASK(data->region->alignment);
+ const int region_alignment = RGN_ALIGN_ENUM_FROM_MASK(data->region->alignment);
int lock_axis = -1;
- if (ELEM(ar_alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
+ if (ELEM(region_alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
lock_axis = 0;
}
- else if (ELEM(ar_alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
+ else if (ELEM(region_alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
lock_axis = 1;
}
if (lock_axis != -1) {
@@ -2836,6 +2853,23 @@ static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
return changed;
}
+static bool ui_textedit_set_cursor_pos_foreach_glyph(const char *UNUSED(str),
+ const size_t str_step_ofs,
+ const rcti *glyph_step_bounds,
+ const int UNUSED(glyph_advance_x),
+ const rctf *glyph_bounds,
+ const int UNUSED(glyph_bearing[2]),
+ void *user_data)
+{
+ int *cursor_data = user_data;
+ float center = glyph_step_bounds->xmin + (BLI_rctf_size_x(glyph_bounds) / 2.0f);
+ if (cursor_data[0] < center) {
+ cursor_data[1] = str_step_ofs;
+ return false;
+ }
+ return true;
+}
+
/**
* \param x: Screen space cursor location - #wmEvent.x
*
@@ -2843,10 +2877,9 @@ static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
*/
static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, const float x)
{
- uiStyle *style = UI_style_get(); // XXX pass on as arg
- uiFontStyle *fstyle = &style->widget;
+ /* XXX pass on as arg. */
+ uiFontStyle fstyle = UI_style_get()->widget;
const float aspect = but->block->aspect;
- const short fstyle_points_prev = fstyle->points;
float startx = but->rect.xmin;
float starty_dummy = 0.0f;
@@ -2856,13 +2889,13 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
ui_block_to_window_fl(data->region, but->block, &startx, &starty_dummy);
- ui_fontscale(&fstyle->points, aspect);
+ ui_fontscale(&fstyle.points, aspect);
- UI_fontstyle_set(fstyle);
+ UI_fontstyle_set(&fstyle);
- if (fstyle->kerning == 1) {
+ if (fstyle.kerning == 1) {
/* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ BLF_enable(fstyle.uifont_id, BLF_KERNING_DEFAULT);
}
ui_but_text_password_hide(password_str, but, false);
@@ -2872,8 +2905,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
startx += UI_DPI_ICON_SIZE / aspect;
}
}
- /* But this extra .05 makes clicks in between characters feel nicer. */
- startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit) / aspect;
+ startx += (UI_TEXT_MARGIN_X * U.widget_unit) / aspect;
/* mouse dragged outside the widget to the left */
if (x < startx) {
@@ -2884,7 +2916,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
while (i > 0) {
if (BLI_str_cursor_step_prev_utf8(str, but->ofs, &i)) {
/* 0.25 == scale factor for less sensitivity */
- if (BLF_width(fstyle->uifont_id, str + i, (str_last - str) - i) > (startx - x) * 0.25f) {
+ if (BLF_width(fstyle.uifont_id, str + i, (str_last - str) - i) > (startx - x) * 0.25f) {
break;
}
}
@@ -2896,75 +2928,41 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
but->pos = but->ofs;
}
/* mouse inside the widget, mouse coords mapped in widget space */
- else { /* (x >= startx) */
- int pos_i;
-
- /* keep track of previous distance from the cursor to the char */
- float cdist, cdist_prev = 0.0f;
- short pos_prev;
-
- str_last = &str[strlen(str)];
-
- but->pos = pos_prev = ((str_last - str) - but->ofs);
-
- while (true) {
- cdist = startx + BLF_width(fstyle->uifont_id, str + but->ofs, (str_last - str) - but->ofs);
-
- /* check if position is found */
- if (cdist < x) {
- /* check is previous location was in fact closer */
- if ((x - cdist) > (cdist_prev - x)) {
- but->pos = pos_prev;
- }
- break;
- }
- cdist_prev = cdist;
- pos_prev = but->pos;
- /* done with tricky distance checks */
-
- pos_i = but->pos;
- if (but->pos <= 0) {
- break;
- }
- if (BLI_str_cursor_step_prev_utf8(str, but->ofs, &pos_i)) {
- but->pos = pos_i;
- str_last = &str[but->pos + but->ofs];
- }
- else {
- break; /* unlikely but possible */
- }
- }
- but->pos += but->ofs;
- if (but->pos < 0) {
- but->pos = 0;
+ else {
+ str_last = &str[but->ofs];
+ const int str_last_len = strlen(str_last);
+ int x_pos = (int)(x - startx);
+ int glyph_data[2] = {
+ x_pos, /* horizontal position to test. */
+ -1, /* Write the character offset here. */
+ };
+ BLF_boundbox_foreach_glyph(fstyle.uifont_id,
+ str + but->ofs,
+ INT_MAX,
+ ui_textedit_set_cursor_pos_foreach_glyph,
+ glyph_data);
+ /* If value untouched then we are to the right. */
+ if (glyph_data[1] == -1) {
+ glyph_data[1] = str_last_len;
}
+ but->pos = glyph_data[1] + but->ofs;
}
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ if (fstyle.kerning == 1) {
+ BLF_disable(fstyle.uifont_id, BLF_KERNING_DEFAULT);
}
ui_but_text_password_hide(password_str, but, true);
-
- fstyle->points = fstyle_points_prev;
}
static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, const float x)
{
- if (x > data->selstartx) {
- data->selextend = EXTEND_RIGHT;
- }
- else if (x < data->selstartx) {
- data->selextend = EXTEND_LEFT;
- }
-
ui_textedit_set_cursor_pos(but, data, x);
- if (data->selextend == EXTEND_RIGHT) {
- but->selend = but->pos;
- }
- else if (data->selextend == EXTEND_LEFT) {
- but->selsta = but->pos;
+ but->selsta = but->pos;
+ but->selend = data->sel_pos_init;
+ if (but->selend < but->selsta) {
+ SWAP(short, but->selsta, but->selend);
}
ui_but_update(but);
@@ -3060,7 +3058,7 @@ static void ui_textedit_move(uiBut *but,
but->pos = but->selend = but->selsta;
}
}
- data->selextend = EXTEND_NONE;
+ data->sel_pos_init = but->pos;
}
else {
int pos_i = but->pos;
@@ -3068,48 +3066,14 @@ static void ui_textedit_move(uiBut *but,
but->pos = pos_i;
if (select) {
- /* existing selection */
- if (has_sel) {
-
- if (data->selextend == EXTEND_NONE) {
- data->selextend = EXTEND_RIGHT;
- }
-
- if (direction) {
- if (data->selextend == EXTEND_RIGHT) {
- but->selend = but->pos;
- }
- else {
- but->selsta = but->pos;
- }
- }
- else {
- if (data->selextend == EXTEND_LEFT) {
- but->selsta = but->pos;
- }
- else {
- but->selend = but->pos;
- }
- }
-
- if (but->selend < but->selsta) {
- SWAP(short, but->selsta, but->selend);
- data->selextend = (data->selextend == EXTEND_RIGHT) ? EXTEND_LEFT : EXTEND_RIGHT;
- }
-
- } /* new selection */
- else {
- if (direction) {
- data->selextend = EXTEND_RIGHT;
- but->selend = but->pos;
- but->selsta = pos_prev;
- }
- else {
- data->selextend = EXTEND_LEFT;
- but->selend = pos_prev;
- but->selsta = but->pos;
- }
+ if (has_sel == false) {
+ data->sel_pos_init = pos_prev;
}
+ but->selsta = but->pos;
+ but->selend = data->sel_pos_init;
+ }
+ if (but->selend < but->selsta) {
+ SWAP(short, but->selsta, but->selend);
}
}
}
@@ -3280,7 +3244,7 @@ wmIMEData *ui_but_ime_data_get(uiBut *but)
static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- wmWindow *win = CTX_wm_window(C);
+ wmWindow *win = data->window;
int len;
const bool is_num_but = ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER);
bool no_zero_strip = false;
@@ -3339,8 +3303,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
len = strlen(data->str);
data->origstr = BLI_strdupn(data->str, len);
- data->selextend = EXTEND_NONE;
- data->selstartx = 0.0f;
+ data->sel_pos_init = 0;
/* set cursor pos to the end of the text */
but->editstr = data->str;
@@ -3348,9 +3311,13 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
but->selsta = 0;
but->selend = len;
+ /* Initialize undo history tracking. */
+ data->undo_stack_text = ui_textedit_undo_stack_create();
+ ui_textedit_undo_push(data->undo_stack_text, but->editstr, but->pos);
+
/* optional searchbox */
if (but->type == UI_BTYPE_SEARCH_MENU) {
- data->searchbox = but->search_create_func(C, data->region, but);
+ data->searchbox = but->search->create_fn(C, data->region, but);
ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */
}
@@ -3370,7 +3337,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
{
- wmWindow *win = CTX_wm_window(C);
+ wmWindow *win = data->window;
if (but) {
if (UI_but_is_utf8(but)) {
@@ -3390,6 +3357,9 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
/* ensure menu (popup) too is closed! */
data->escapecancel = true;
+
+ WM_reportf(RPT_ERROR, "Failed to find '%s'", but->editstr);
+ WM_report_banner_show();
}
}
@@ -3403,6 +3373,10 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
WM_cursor_modal_restore(win);
+ /* Free text undo history text blocks. */
+ ui_textedit_undo_stack_destroy(data->undo_stack_text);
+ data->undo_stack_text = NULL;
+
#ifdef WITH_INPUT_IME
if (win->ime_data) {
ui_textedit_ime_end(win, but);
@@ -3482,7 +3456,7 @@ static void ui_do_but_textedit(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int retval = WM_UI_HANDLER_CONTINUE;
- bool changed = false, inbox = false, update = false;
+ bool changed = false, inbox = false, update = false, skip_undo_push = false;
#ifdef WITH_INPUT_IME
wmWindow *win = CTX_wm_window(C);
@@ -3502,7 +3476,7 @@ static void ui_do_but_textedit(
/* pass */
}
else {
- ui_searchbox_event(C, data->searchbox, but, event);
+ ui_searchbox_event(C, data->searchbox, but, data->region, event);
}
#else
ui_searchbox_event(C, data->searchbox, but, event);
@@ -3511,8 +3485,18 @@ static void ui_do_but_textedit(
break;
case RIGHTMOUSE:
- case ESCKEY:
+ case EVT_ESCKEY:
if (event->val == KM_PRESS) {
+ /* Support search context menu. */
+ if (event->type == RIGHTMOUSE) {
+ if (data->searchbox) {
+ if (ui_searchbox_event(C, data->searchbox, but, data->region, event)) {
+ /* Only break if the event was handled. */
+ break;
+ }
+ }
+ }
+
#ifdef WITH_INPUT_IME
/* skips button handling since it is not wanted */
if (is_ime_composing) {
@@ -3546,7 +3530,7 @@ static void ui_do_but_textedit(
if (ui_but_contains_pt(but, mx, my)) {
ui_textedit_set_cursor_pos(but, data, event->x);
but->selsta = but->selend = but->pos;
- data->selstartx = event->x;
+ data->sel_pos_init = but->pos;
button_activate_state(C, but, BUTTON_STATE_TEXT_SELECTING);
retval = WM_UI_HANDLER_BREAK;
@@ -3582,24 +3566,24 @@ static void ui_do_but_textedit(
if (event->val == KM_PRESS && !is_ime_composing) {
switch (event->type) {
- case VKEY:
- case XKEY:
- case CKEY:
+ case EVT_VKEY:
+ case EVT_XKEY:
+ case EVT_CKEY:
if (IS_EVENT_MOD(event, ctrl, oskey)) {
- if (event->type == VKEY) {
+ if (event->type == EVT_VKEY) {
changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_PASTE);
}
- else if (event->type == CKEY) {
+ else if (event->type == EVT_CKEY) {
changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_COPY);
}
- else if (event->type == XKEY) {
+ else if (event->type == EVT_XKEY) {
changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_CUT);
}
retval = WM_UI_HANDLER_BREAK;
}
break;
- case RIGHTARROWKEY:
+ case EVT_RIGHTARROWKEY:
ui_textedit_move(but,
data,
STRCUR_DIR_NEXT,
@@ -3607,7 +3591,7 @@ static void ui_do_but_textedit(
event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
retval = WM_UI_HANDLER_BREAK;
break;
- case LEFTARROWKEY:
+ case EVT_LEFTARROWKEY:
ui_textedit_move(but,
data,
STRCUR_DIR_PREV,
@@ -3616,57 +3600,57 @@ static void ui_do_but_textedit(
retval = WM_UI_HANDLER_BREAK;
break;
case WHEELDOWNMOUSE:
- case DOWNARROWKEY:
+ case EVT_DOWNARROWKEY:
if (data->searchbox) {
#ifdef USE_KEYNAV_LIMIT
ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event);
#endif
- ui_searchbox_event(C, data->searchbox, but, event);
+ ui_searchbox_event(C, data->searchbox, but, data->region, event);
break;
}
if (event->type == WHEELDOWNMOUSE) {
break;
}
ATTR_FALLTHROUGH;
- case ENDKEY:
+ case EVT_ENDKEY:
ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->shift != 0, STRCUR_JUMP_ALL);
retval = WM_UI_HANDLER_BREAK;
break;
case WHEELUPMOUSE:
- case UPARROWKEY:
+ case EVT_UPARROWKEY:
if (data->searchbox) {
#ifdef USE_KEYNAV_LIMIT
ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event);
#endif
- ui_searchbox_event(C, data->searchbox, but, event);
+ ui_searchbox_event(C, data->searchbox, but, data->region, event);
break;
}
if (event->type == WHEELUPMOUSE) {
break;
}
ATTR_FALLTHROUGH;
- case HOMEKEY:
+ case EVT_HOMEKEY:
ui_textedit_move(but, data, STRCUR_DIR_PREV, event->shift != 0, STRCUR_JUMP_ALL);
retval = WM_UI_HANDLER_BREAK;
break;
- case PADENTER:
- case RETKEY:
+ case EVT_PADENTER:
+ case EVT_RETKEY:
button_activate_state(C, but, BUTTON_STATE_EXIT);
retval = WM_UI_HANDLER_BREAK;
break;
- case DELKEY:
+ case EVT_DELKEY:
changed = ui_textedit_delete(
but, data, 1, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
retval = WM_UI_HANDLER_BREAK;
break;
- case BACKSPACEKEY:
+ case EVT_BACKSPACEKEY:
changed = ui_textedit_delete(
but, data, 0, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
retval = WM_UI_HANDLER_BREAK;
break;
- case AKEY:
+ case EVT_AKEY:
/* Ctrl + A: Select all */
#if defined(__APPLE__)
@@ -3683,7 +3667,7 @@ static void ui_do_but_textedit(
}
break;
- case TABKEY:
+ case EVT_TABKEY:
/* there is a key conflict here, we can't tab with autocomplete */
if (but->autocomplete_func || data->searchbox) {
int autocomplete = ui_textedit_autocomplete(C, but, data);
@@ -3704,6 +3688,32 @@ static void ui_do_but_textedit(
}
retval = WM_UI_HANDLER_BREAK;
break;
+ case EVT_ZKEY: {
+ /* Ctrl-Z or Ctrl-Shift-Z: Undo/Redo (allowing for OS-Key on Apple). */
+
+ const bool is_redo = (event->shift != 0);
+ if (
+#if defined(__APPLE__)
+ (event->oskey && !IS_EVENT_MOD(event, alt, ctrl)) ||
+#endif
+ (event->ctrl && !IS_EVENT_MOD(event, alt, oskey))) {
+ int undo_pos;
+ const char *undo_str = ui_textedit_undo(
+ data->undo_stack_text, is_redo ? 1 : -1, &undo_pos);
+ if (undo_str != NULL) {
+ ui_textedit_string_set(but, data, undo_str);
+
+ /* Set the cursor & clear selection. */
+ but->pos = undo_pos;
+ but->selsta = but->pos;
+ but->selend = but->pos;
+ changed = true;
+ }
+ retval = WM_UI_HANDLER_BREAK;
+ skip_undo_push = true;
+ }
+ break;
+ }
}
if ((event->ascii || event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE)
@@ -3717,7 +3727,7 @@ static void ui_do_but_textedit(
/* exception that's useful for number buttons, some keyboard
* numpads have a comma instead of a period */
if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) { /* could use data->min*/
- if (event->type == PADPERIOD && ascii == ',') {
+ if (event->type == EVT_PADPERIOD && ascii == ',') {
ascii = '.';
utf8_buf = NULL; /* force ascii fallback */
}
@@ -3725,12 +3735,7 @@ static void ui_do_but_textedit(
if (utf8_buf && utf8_buf[0]) {
int utf8_buf_len = BLI_str_utf8_size(utf8_buf);
- /* keep this printf until utf8 is well tested */
- if (utf8_buf_len != 1) {
- printf("%s: utf8 char '%.*s'\n", __func__, utf8_buf_len, utf8_buf);
- }
-
- // strcpy(utf8_buf, "12345");
+ BLI_assert(utf8_buf_len != -1);
changed = ui_textedit_insert_buf(but, data, event->utf8_buf, utf8_buf_len);
}
else {
@@ -3762,6 +3767,11 @@ static void ui_do_but_textedit(
#endif
if (changed) {
+ /* The undo stack may be NULL if an event exits editing. */
+ if ((skip_undo_push == false) && (data->undo_stack_text != NULL)) {
+ ui_textedit_undo_push(data->undo_stack_text, data->str, but->pos);
+ }
+
/* only do live update when but flag request it (UI_BUT_TEXTEDIT_UPDATE). */
if (update && data->interactive) {
ui_apply_but(C, block, but, data, true);
@@ -3945,7 +3955,7 @@ static void ui_but_extra_operator_icon_apply(bContext *C, uiBut *but, uiButExtra
/* Force recreation of extra operator icons (pseudo update). */
ui_but_extra_operator_icons_free(but);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
}
/** \} */
@@ -3990,7 +4000,12 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
copy_v3_v3(data->vec, data->origvec);
but->editvec = data->vec;
- handlefunc = ui_block_func_COLOR;
+ if (ui_but_menu_draw_as_popover(but)) {
+ popoverfunc = but->menu_create_func;
+ }
+ else {
+ handlefunc = ui_block_func_COLOR;
+ }
arg = but;
break;
@@ -4020,8 +4035,7 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
#ifdef USE_ALLSELECT
{
- wmWindow *win = CTX_wm_window(C);
- if (IS_ALLSELECT_EVENT(win->eventstate)) {
+ if (IS_ALLSELECT_EVENT(data->window->eventstate)) {
data->select_others.is_enabled = true;
}
}
@@ -4060,8 +4074,8 @@ int ui_but_menu_direction(uiBut *but)
}
/**
- * Hack for #uiList #UI_BTYPE_LISTROW buttons to "give" events to overlaying #UI_BTYPE_TEXT buttons
- * (Ctrl-Click rename feature & co).
+ * Hack for #uiList #UI_BTYPE_LISTROW buttons to "give" events to overlaying #UI_BTYPE_TEXT
+ * buttons (Ctrl-Click rename feature & co).
*/
static uiBut *ui_but_list_row_text_activate(bContext *C,
uiBut *but,
@@ -4069,8 +4083,8 @@ static uiBut *ui_but_list_row_text_activate(bContext *C,
const wmEvent *event,
uiButtonActivateType activate_type)
{
- ARegion *ar = CTX_wm_region(C);
- uiBut *labelbut = ui_but_find_mouse_over_ex(ar, event->x, event->y, true);
+ ARegion *region = CTX_wm_region(C);
+ uiBut *labelbut = ui_but_find_mouse_over_ex(region, event->x, event->y, true);
if (labelbut && labelbut->type == UI_BTYPE_TEXT && !(labelbut->flag & UI_BUT_DISABLED)) {
/* exit listrow */
@@ -4078,7 +4092,7 @@ static uiBut *ui_but_list_row_text_activate(bContext *C,
button_activate_exit(C, but, data, false, false);
/* Activate the text button. */
- button_activate_init(C, ar, labelbut, activate_type);
+ button_activate_init(C, region, labelbut, activate_type);
return labelbut;
}
@@ -4188,7 +4202,7 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
- else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ else if (ELEM(event->type, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH);
return WM_UI_HANDLER_BREAK;
}
@@ -4212,7 +4226,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C,
const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
but->drawstr[0] = 0;
but->modifier_key = 0;
button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
@@ -4223,11 +4237,11 @@ static int ui_do_but_HOTKEYEVT(bContext *C,
if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
return WM_UI_HANDLER_CONTINUE;
}
- else if (event->type == UNKNOWNKEY) {
+ else if (event->type == EVT_UNKNOWNKEY) {
WM_report(RPT_WARNING, "Unsupported key: Unknown");
return WM_UI_HANDLER_CONTINUE;
}
- else if (event->type == CAPSLOCKKEY) {
+ else if (event->type == EVT_CAPSLOCKKEY) {
WM_report(RPT_WARNING, "Unsupported key: CapsLock");
return WM_UI_HANDLER_CONTINUE;
}
@@ -4266,7 +4280,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C,
ED_region_tag_redraw(data->region);
if (event->val == KM_PRESS) {
- if (ISHOTKEY(event->type) && (event->type != ESCKEY)) {
+ if (ISHOTKEY(event->type) && (event->type != EVT_ESCKEY)) {
if (WM_key_event_string(event->type, false)[0]) {
ui_but_value_set(but, event->type);
}
@@ -4277,7 +4291,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C,
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
- else if (event->type == ESCKEY) {
+ else if (event->type == EVT_ESCKEY) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -4296,7 +4310,7 @@ static int ui_do_but_KEYEVT(bContext *C,
const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
return WM_UI_HANDLER_BREAK;
}
@@ -4343,7 +4357,7 @@ static int ui_do_but_TAB(
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
return WM_UI_HANDLER_BREAK;
}
- else if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY)) {
+ else if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY)) {
int event_val = (is_property) ? KM_PRESS : KM_CLICK;
if (event->val == event_val) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -4367,8 +4381,9 @@ static int ui_do_but_TEX(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
- if (ELEM(event->type, PADENTER, RETKEY) && (!UI_but_is_utf8(but))) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, EVT_PADENTER, EVT_RETKEY) &&
+ event->val == KM_PRESS) {
+ if (ELEM(event->type, EVT_PADENTER, EVT_RETKEY) && (!UI_but_is_utf8(but))) {
/* pass - allow filesel, enter to execute */
}
else if (but->dt == UI_EMBOSS_NONE && !event->ctrl) {
@@ -4398,7 +4413,7 @@ static int ui_do_but_SEARCH_UNLINK(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
/* unlink icon is on right */
- if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, EVT_PADENTER, EVT_RETKEY)) {
/* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
if ((event->val == KM_RELEASE) && ui_do_but_extra_operator_icon(C, but, data, event)) {
return WM_UI_HANDLER_BREAK;
@@ -4420,7 +4435,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
if (data->state == BUTTON_STATE_HIGHLIGHT) {
bool do_activate = false;
- if (ELEM(event->type, PADENTER, RETKEY)) {
+ if (ELEM(event->type, EVT_PADENTER, EVT_RETKEY)) {
if (event->val == KM_PRESS) {
do_activate = true;
}
@@ -4431,7 +4446,8 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
do_activate = (event->val == KM_RELEASE);
}
else {
- do_activate = (event->val == KM_PRESS);
+ /* Also use double-clicks to prevent fast clicks to leak to other handlers (T76481). */
+ do_activate = ELEM(event->val, KM_PRESS, KM_DBL_CLICK);
}
}
@@ -4451,20 +4467,20 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
if (but_select) {
uiBut *but_other = (direction == -1) ? but_select->next : but_select->prev;
if (but_other && ui_but_find_select_in_enum__cmp(but, but_other)) {
- ARegion *ar = data->region;
+ ARegion *region = data->region;
data->cancel = true;
button_activate_exit(C, but, data, false, false);
/* Activate the text button. */
- button_activate_init(C, ar, but_other, BUTTON_ACTIVATE_OVER);
+ button_activate_init(C, region, but_other, BUTTON_ACTIVATE_OVER);
data = but_other->active;
if (data) {
ui_apply_but(C, but->block, but_other, but_other->active, true);
button_activate_exit(C, but_other, data, false, false);
/* restore active button */
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER);
}
else {
/* shouldn't happen */
@@ -4505,7 +4521,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
}
#endif
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
int ret = WM_UI_HANDLER_BREAK;
/* XXX (a bit ugly) Special case handling for filebrowser drag button */
if (but->dragpoin && but->imb && ui_but_contains_point_px_icon(but, data->region, event)) {
@@ -4904,7 +4920,7 @@ static int ui_do_but_NUM(
click = 1;
}
else if (event->val == KM_PRESS) {
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->ctrl) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
@@ -4913,10 +4929,10 @@ static int ui_do_but_NUM(
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
- else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ else if (ELEM(event->type, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
click = 1;
}
- else if (event->type == MINUSKEY && event->val == KM_PRESS) {
+ else if (event->type == EVT_MINUSKEY && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
data->value = -data->value;
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -4929,7 +4945,7 @@ static int ui_do_but_NUM(
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->type == EVT_ESCKEY || event->type == RIGHTMOUSE) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -5208,7 +5224,7 @@ static int ui_do_but_SLI(
click = 2;
}
else if (event->val == KM_PRESS) {
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->ctrl) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
@@ -5232,10 +5248,10 @@ static int ui_do_but_SLI(
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
- else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ else if (ELEM(event->type, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
click = 1;
}
- else if (event->type == MINUSKEY && event->val == KM_PRESS) {
+ else if (event->type == EVT_MINUSKEY && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
data->value = -data->value;
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -5247,7 +5263,7 @@ static int ui_do_but_SLI(
#endif
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->type == EVT_ESCKEY || event->type == RIGHTMOUSE) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -5414,7 +5430,7 @@ static int ui_do_but_SCROLL(
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
+ if (event->type == EVT_ESCKEY) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -5466,7 +5482,7 @@ static int ui_do_but_GRIP(
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
+ if (event->type == EVT_ESCKEY) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -5499,7 +5515,7 @@ static int ui_do_but_LISTROW(bContext *C,
/* hack to pass on ctrl+click and double click to overlapping text
* editing field for editing list item names
*/
- if ((ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS &&
+ if ((ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS &&
event->ctrl) ||
(event->type == LEFTMOUSE && event->val == KM_DBL_CLICK)) {
uiBut *labelbut = ui_but_list_row_text_activate(
@@ -5537,7 +5553,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
#endif
/* regular open menu */
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
}
@@ -5550,14 +5566,13 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
button_activate_state(C, but, BUTTON_STATE_EXIT);
ui_apply_but(C, but->block, but, data, true);
- /* Button's state need to be changed to EXIT so moving mouse away from this mouse wouldn't
- * lead to cancel changes made to this button, but changing state to EXIT also makes no
- * button active for a while which leads to triggering operator
- * when doing fast scrolling mouse wheel.
- * using post activate stuff from button allows to make button be active again after
- * checking for all all that mouse leave and cancel stuff,
- * so quick scroll wouldn't be an issue anymore.
- * Same goes for scrolling wheel in another direction below (sergey).
+ /* Button's state need to be changed to EXIT so moving mouse away from this mouse
+ * wouldn't lead to cancel changes made to this button, but changing state to EXIT also
+ * makes no button active for a while which leads to triggering operator when doing fast
+ * scrolling mouse wheel. using post activate stuff from button allows to make button be
+ * active again after checking for all all that mouse leave and cancel stuff, so quick
+ * scroll wouldn't be an issue anymore. Same goes for scrolling wheel in another
+ * direction below (sergey).
*/
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_OVER;
@@ -5570,7 +5585,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
* The active state of the button could be maintained some other way
* and remove this mousemove event.
*/
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(data->window);
return WM_UI_HANDLER_BREAK;
}
@@ -5711,7 +5726,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
#endif
/* regular open menu */
- if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
ui_palette_set_active(but);
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
@@ -5743,7 +5758,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
ui_apply_but(C, but->block, but, data, true);
return WM_UI_HANDLER_BREAK;
}
- else if ((int)(but->a1) == UI_PALETTE_COLOR && event->type == DELKEY &&
+ else if ((int)(but->a1) == UI_PALETTE_COLOR && event->type == EVT_DELKEY &&
event->val == KM_PRESS) {
Palette *palette = (Palette *)but->rnapoin.owner_id;
PaletteColor *color = but->rnapoin.data;
@@ -5794,15 +5809,27 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
else {
Scene *scene = CTX_data_scene(C);
+ bool updated = false;
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
BKE_brush_color_set(scene, brush, color);
+ updated = true;
}
else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
IMB_colormanagement_scene_linear_to_srgb_v3(color);
BKE_brush_color_set(scene, brush, color);
+ updated = true;
+ }
+
+ if (updated) {
+ PointerRNA brush_ptr;
+ PropertyRNA *brush_color_prop;
+
+ RNA_id_pointer_create(&brush->id, &brush_ptr);
+ brush_color_prop = RNA_struct_find_property(&brush_ptr, "color");
+ RNA_property_update(C, &brush_ptr, brush_color_prop);
}
}
@@ -5857,7 +5884,7 @@ static int ui_do_but_UNITVEC(
}
}
}
- else if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ else if (event->type == EVT_ESCKEY || event->type == RIGHTMOUSE) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -6150,7 +6177,7 @@ static int ui_do_but_HSVCUBE(
}
#endif /* WITH_INPUT_NDOF */
/* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
+ else if (event->type == EVT_BACKSPACEKEY && event->val == KM_PRESS) {
if (ELEM(but->a1, UI_GRAD_V_ALT, UI_GRAD_L_ALT)) {
int len;
@@ -6182,7 +6209,7 @@ static int ui_do_but_HSVCUBE(
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->type == EVT_ESCKEY || event->type == RIGHTMOUSE) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -6426,7 +6453,7 @@ static int ui_do_but_HSVCIRCLE(
}
#endif /* WITH_INPUT_NDOF */
/* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
+ else if (event->type == EVT_BACKSPACEKEY && event->val == KM_PRESS) {
int len;
/* reset only saturation */
@@ -6457,7 +6484,7 @@ static int ui_do_but_HSVCIRCLE(
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->type == EVT_ESCKEY || event->type == RIGHTMOUSE) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -6551,7 +6578,7 @@ static int ui_do_but_COLORBAND(
/* activate new key when mouse is close */
for (a = 0, cbd = coba->data; a < coba->tot; a++, cbd++) {
xco = but->rect.xmin + (cbd->pos * BLI_rctf_size_x(&but->rect));
- xco = ABS(xco - mx);
+ xco = abs(xco - mx);
if (a == coba->cur) {
/* Selected one disadvantage. */
xco += 5;
@@ -6581,7 +6608,7 @@ static int ui_do_but_COLORBAND(
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
- else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
+ else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
data->dragcbd->pos = data->dragfstart;
BKE_colorband_update_sort(data->coba);
@@ -6736,7 +6763,7 @@ static int ui_do_but_CURVE(
CurveMap *cuma = cumap->cm + cumap->cur;
CurveMapPoint *cmp;
const float m_xy[2] = {mx, my};
- float dist_min_sq = SQUARE(U.dpi_fac * 14.0f); /* 14 pixels radius */
+ float dist_min_sq = square_f(U.dpi_fac * 14.0f); /* 14 pixels radius */
int sel = -1;
if (event->ctrl) {
@@ -6771,7 +6798,7 @@ static int ui_do_but_CURVE(
BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[0].x);
/* with 160px height 8px should translate to the old 0.05 coefficient at no zoom */
- dist_min_sq = SQUARE(U.dpi_fac * 8.0f);
+ dist_min_sq = square_f(U.dpi_fac * 8.0f);
/* loop through the curve segment table and find what's near the mouse. */
for (i = 1; i <= CM_TABLE; i++) {
@@ -7007,7 +7034,7 @@ static int ui_do_but_CURVEPROFILE(
ui_window_to_block(data->region, block, &mx, &my);
/* Move selected control points. */
- if (event->type == GKEY && event->val == KM_RELEASE) {
+ if (event->type == EVT_GKEY && event->val == KM_RELEASE) {
data->dragstartx = mx;
data->dragstarty = my;
data->draglastx = mx;
@@ -7019,7 +7046,7 @@ static int ui_do_but_CURVEPROFILE(
CurveProfile *profile = (CurveProfile *)but->poin;
/* Delete selected control points. */
- if (event->type == XKEY && event->val == KM_RELEASE) {
+ if (event->type == EVT_XKEY && event->val == KM_RELEASE) {
BKE_curveprofile_remove_by_flag(profile, PROF_SELECT);
BKE_curveprofile_update(profile, false);
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -7043,7 +7070,7 @@ static int ui_do_but_CURVEPROFILE(
}
/* Check for selecting of a point by finding closest point in radius. */
- dist_min_sq = SQUARE(U.dpi_fac * 14.0f); /* 14 pixels radius for selecting points. */
+ dist_min_sq = square_f(U.dpi_fac * 14.0f); /* 14 pixels radius for selecting points. */
pts = profile->path;
for (i = 0; i < profile->path_len; i++) {
float f_xy[2];
@@ -7061,7 +7088,7 @@ static int ui_do_but_CURVEPROFILE(
pts = profile->table;
BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &pts[0].x);
- dist_min_sq = SQUARE(U.dpi_fac * 8.0f); /* 8 pixel radius from each table point. */
+ dist_min_sq = square_f(U.dpi_fac * 8.0f); /* 8 pixel radius from each table point. */
/* Loop through the path's high resolution table and find what's near the click. */
for (i = 1; i <= PROF_N_TABLE(profile->path_len); i++) {
@@ -7196,7 +7223,7 @@ static int ui_do_but_HISTOGRAM(
return WM_UI_HANDLER_BREAK;
}
/* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
+ else if (event->type == EVT_BACKSPACEKEY && event->val == KM_PRESS) {
Histogram *hist = (Histogram *)but->poin;
hist->ymax = 1.f;
@@ -7205,7 +7232,7 @@ static int ui_do_but_HISTOGRAM(
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
+ if (event->type == EVT_ESCKEY) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -7272,7 +7299,7 @@ static int ui_do_but_WAVEFORM(
return WM_UI_HANDLER_BREAK;
}
/* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
+ else if (event->type == EVT_BACKSPACEKEY && event->val == KM_PRESS) {
Scopes *scopes = (Scopes *)but->poin;
scopes->wavefrm_yfac = 1.f;
@@ -7281,7 +7308,7 @@ static int ui_do_but_WAVEFORM(
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
+ if (event->type == EVT_ESCKEY) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -7320,8 +7347,10 @@ static bool ui_numedit_but_TRACKPREVIEW(
}
if (!scopes->track_locked) {
- if (scopes->marker->framenr != scopes->framenr) {
- scopes->marker = BKE_tracking_marker_ensure(scopes->track, scopes->framenr);
+ const MovieClip *clip = CTX_data_edit_movieclip(C);
+ int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scopes->framenr);
+ if (scopes->marker->framenr != clip_framenr) {
+ scopes->marker = BKE_tracking_marker_ensure(scopes->track, clip_framenr);
}
scopes->marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
@@ -7365,7 +7394,7 @@ static int ui_do_but_TRACKPREVIEW(
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == ESCKEY) {
+ if (event->type == EVT_ESCKEY) {
if (event->val == KM_PRESS) {
data->cancel = true;
data->escapecancel = true;
@@ -7409,8 +7438,8 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/* handle copy and paste */
bool is_press_ctrl_but_no_shift = event->val == KM_PRESS && IS_EVENT_MOD(event, ctrl, oskey) &&
!event->shift;
- bool do_copy = event->type == CKEY && is_press_ctrl_but_no_shift;
- bool do_paste = event->type == VKEY && is_press_ctrl_but_no_shift;
+ bool do_copy = event->type == EVT_CKEY && is_press_ctrl_but_no_shift;
+ bool do_paste = event->type == EVT_VKEY && is_press_ctrl_but_no_shift;
/* Specific handling for listrows, we try to find their overlapping tex button. */
if ((do_copy || do_paste) && but->type == UI_BTYPE_LISTROW) {
@@ -7451,7 +7480,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
if ((data->state == BUTTON_STATE_HIGHLIGHT) &&
- ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) &&
+ ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, EVT_PADENTER, EVT_RETKEY) &&
(event->val == KM_RELEASE) &&
/* Only returns true if the event was handled. */
ui_do_but_extra_operator_icon(C, but, data, event)) {
@@ -7583,7 +7612,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
data = but->active;
if (data && data->state == BUTTON_STATE_HIGHLIGHT) {
if ((retval == WM_UI_HANDLER_CONTINUE) &&
- (event->type == BACKSPACEKEY && event->val == KM_PRESS)) {
+ (event->type == EVT_BACKSPACEKEY && event->val == KM_PRESS)) {
/* ctrl+backspace = reset active button; backspace = reset a whole array*/
ui_but_default_set(C, !event->ctrl, true);
ED_region_tag_redraw(data->region);
@@ -7658,17 +7687,17 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/** \name Button Tool Tip
* \{ */
-static void ui_blocks_set_tooltips(ARegion *ar, const bool enable)
+static void ui_blocks_set_tooltips(ARegion *region, const bool enable)
{
uiBlock *block;
- if (!ar) {
+ if (!region) {
return;
}
/* we disabled buttons when when they were already shown, and
* re-enable them on mouse move */
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
block->tooltipdisabled = !enable;
}
}
@@ -7680,8 +7709,8 @@ void UI_but_tooltip_refresh(bContext *C, uiBut *but)
{
uiHandleButtonData *data = but->active;
if (data) {
- bScreen *sc = WM_window_get_active_screen(data->window);
- if (sc->tool_tip && sc->tool_tip->region) {
+ bScreen *screen = WM_window_get_active_screen(data->window);
+ if (screen->tool_tip && screen->tool_tip->region) {
WM_tooltip_refresh(C, data->window);
}
}
@@ -7709,7 +7738,7 @@ void UI_but_tooltip_timer_remove(bContext *C, uiBut *but)
}
static ARegion *ui_but_tooltip_init(
- bContext *C, ARegion *ar, int *pass, double *r_pass_delay, bool *r_exit_on_event)
+ bContext *C, ARegion *region, int *pass, double *r_pass_delay, bool *r_exit_on_event)
{
bool is_label = false;
if (*pass == 1) {
@@ -7718,10 +7747,10 @@ static ARegion *ui_but_tooltip_init(
(*r_pass_delay) = UI_TOOLTIP_DELAY - UI_TOOLTIP_DELAY_LABEL;
}
- uiBut *but = UI_region_active_but_get(ar);
+ uiBut *but = UI_region_active_but_get(region);
*r_exit_on_event = false;
if (but) {
- return UI_tooltip_create_from_button(C, ar, but, is_label);
+ return UI_tooltip_create_from_button(C, region, but, is_label);
}
return NULL;
}
@@ -7741,9 +7770,9 @@ static void button_tooltip_timer_reset(bContext *C, uiBut *but)
WM_tooltip_timer_init_ex(
C, data->window, data->area, data->region, ui_but_tooltip_init, delay);
if (is_label) {
- bScreen *sc = WM_window_get_active_screen(data->window);
- if (sc->tool_tip) {
- sc->tool_tip->pass = 1;
+ bScreen *screen = WM_window_get_active_screen(data->window);
+ if (screen->tool_tip) {
+ screen->tool_tip->pass = 1;
}
}
}
@@ -7937,7 +7966,10 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
ED_region_tag_redraw(data->region);
}
-static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type)
+static void button_activate_init(bContext *C,
+ ARegion *region,
+ uiBut *but,
+ uiButtonActivateType type)
{
uiHandleButtonData *data;
@@ -7946,8 +7978,8 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
data->wm = CTX_wm_manager(C);
data->window = CTX_wm_window(C);
data->area = CTX_wm_area(C);
- BLI_assert(ar != NULL);
- data->region = ar;
+ BLI_assert(region != NULL);
+ data->region = region;
#ifdef USE_CONT_MOUSE_CORRECT
copy_v2_fl(data->ungrab_mval, FLT_MAX);
@@ -8026,11 +8058,11 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
if (UI_but_has_tooltip_label(but)) {
/* Show a label for this button. */
- bScreen *sc = WM_window_get_active_screen(data->window);
+ bScreen *screen = WM_window_get_active_screen(data->window);
if ((PIL_check_seconds_timer() - WM_tooltip_time_closed()) < 0.1) {
- WM_tooltip_immediate_init(C, CTX_wm_window(C), data->area, ar, ui_but_tooltip_init);
- if (sc->tool_tip) {
- sc->tool_tip->pass = 1;
+ WM_tooltip_immediate_init(C, CTX_wm_window(C), data->area, region, ui_but_tooltip_init);
+ if (screen->tool_tip) {
+ screen->tool_tip->pass = 1;
}
}
}
@@ -8039,11 +8071,12 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
static void button_activate_exit(
bContext *C, uiBut *but, uiHandleButtonData *data, const bool mousemove, const bool onfree)
{
+ wmWindow *win = data->window;
uiBlock *block = but->block;
uiBut *bt;
if (but->type == UI_BTYPE_GRIP) {
- WM_cursor_modal_restore(data->window);
+ WM_cursor_modal_restore(win);
}
/* ensure we are in the exit state */
@@ -8160,7 +8193,7 @@ static void button_activate_exit(
* still over a button. We cannot just check for this ourselves because
* at this point the mouse may be over a button in another region */
if (mousemove) {
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
}
}
@@ -8179,16 +8212,16 @@ void ui_but_active_free(const bContext *C, uiBut *but)
}
/* returns the active button with an optional checking function */
-static uiBut *ui_context_button_active(ARegion *ar, bool (*but_check_cb)(uiBut *))
+static uiBut *ui_context_button_active(ARegion *region, bool (*but_check_cb)(uiBut *))
{
uiBut *but_found = NULL;
- while (ar) {
+ while (region) {
uiBlock *block;
uiBut *but, *activebut = NULL;
/* find active button */
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
if (but->active) {
activebut = but;
@@ -8205,8 +8238,8 @@ static uiBut *ui_context_button_active(ARegion *ar, bool (*but_check_cb)(uiBut *
but_found = activebut;
/* recurse into opened menu, like colorpicker case */
- if (data && data->menu && (ar != data->menu->region)) {
- ar = data->menu->region;
+ if (data && data->menu && (region != data->menu->region)) {
+ region = data->menu->region;
}
else {
return but_found;
@@ -8230,19 +8263,37 @@ static uiBut *ui_context_rna_button_active(const bContext *C)
return ui_context_button_active(CTX_wm_region(C), ui_context_rna_button_active_test);
}
-uiBut *UI_context_active_but_get(const struct bContext *C)
+uiBut *UI_context_active_but_get(const bContext *C)
{
return ui_context_button_active(CTX_wm_region(C), NULL);
}
-uiBut *UI_region_active_but_get(ARegion *ar)
+/*
+ * Version of #UI_context_active_get() that uses the result of #CTX_wm_menu()
+ * if set. Does not traverse into parent menus, which may be wanted in some
+ * cases.
+ */
+uiBut *UI_context_active_but_get_respect_menu(const bContext *C)
+{
+ ARegion *ar_menu = CTX_wm_menu(C);
+ return ui_context_button_active(ar_menu ? ar_menu : CTX_wm_region(C), NULL);
+}
+
+uiBut *UI_region_active_but_get(ARegion *region)
{
- return ui_context_button_active(ar, NULL);
+ return ui_context_button_active(region, NULL);
}
-uiBut *UI_region_but_find_rect_over(const ARegion *ar, const rcti *rect_px)
+uiBut *UI_region_but_find_rect_over(const ARegion *region, const rcti *rect_px)
{
- return ui_but_find_rect_over(ar, rect_px);
+ return ui_but_find_rect_over(region, rect_px);
+}
+
+uiBlock *UI_region_block_find_mouse_over(const struct ARegion *region,
+ const int xy[2],
+ bool only_clip)
+{
+ return ui_block_find_mouse_over_ex(region, xy[0], xy[1], only_clip);
}
/**
@@ -8288,16 +8339,16 @@ void UI_context_active_but_prop_handle(bContext *C)
wmOperator *UI_context_active_operator_get(const struct bContext *C)
{
- ARegion *ar_ctx = CTX_wm_region(C);
+ ARegion *region_ctx = CTX_wm_region(C);
uiBlock *block;
/* background mode */
- if (ar_ctx == NULL) {
+ if (region_ctx == NULL) {
return NULL;
}
/* scan active regions ui */
- for (block = ar_ctx->uiblocks.first; block; block = block->next) {
+ for (block = region_ctx->uiblocks.first; block; block = block->next) {
if (block->ui_operator) {
return block->ui_operator;
}
@@ -8305,14 +8356,14 @@ wmOperator *UI_context_active_operator_get(const struct bContext *C)
/* scan popups */
{
- bScreen *sc = CTX_wm_screen(C);
- ARegion *ar;
+ bScreen *screen = CTX_wm_screen(C);
+ ARegion *region;
- for (ar = sc->regionbase.first; ar; ar = ar->next) {
- if (ar == ar_ctx) {
+ for (region = screen->regionbase.first; region; region = region->next) {
+ if (region == region_ctx) {
continue;
}
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
if (block->ui_operator) {
return block->ui_operator;
}
@@ -8327,15 +8378,15 @@ wmOperator *UI_context_active_operator_get(const struct bContext *C)
void UI_context_update_anim_flag(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
uiBlock *block;
uiBut *but, *activebut;
- while (ar) {
+ while (region) {
/* find active button */
activebut = NULL;
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
ui_but_override_flag(but);
@@ -8343,7 +8394,7 @@ void UI_context_update_anim_flag(const bContext *C)
ui_but_anim_decorate_update_from_flag(but);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
if (but->active) {
activebut = but;
@@ -8358,7 +8409,7 @@ void UI_context_update_anim_flag(const bContext *C)
/* always recurse into opened menu, so all buttons update (like colorpicker) */
uiHandleButtonData *data = activebut->active;
if (data && data->menu) {
- ar = data->menu->region;
+ region = data->menu->region;
}
else {
return;
@@ -8377,12 +8428,12 @@ void UI_context_update_anim_flag(const bContext *C)
/** \name Button Activation Handling
* \{ */
-static uiBut *ui_but_find_open_event(ARegion *ar, const wmEvent *event)
+static uiBut *ui_but_find_open_event(ARegion *region, const wmEvent *event)
{
uiBlock *block;
uiBut *but;
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
if (but == event->customdata) {
return but;
@@ -8392,14 +8443,14 @@ static uiBut *ui_but_find_open_event(ARegion *ar, const wmEvent *event)
return NULL;
}
-static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
+static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *region)
{
uiBut *but;
if (event->type == MOUSEMOVE) {
- but = ui_but_find_mouse_over(ar, event);
+ but = ui_but_find_mouse_over(region, event);
if (but) {
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER);
if (event->alt && but->active) {
/* display tooltips if holding alt on mouseover when tooltips are off in prefs */
@@ -8408,9 +8459,9 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
}
}
else if (event->type == EVT_BUT_OPEN) {
- but = ui_but_find_open_event(ar, event);
+ but = ui_but_find_open_event(region, event);
if (but) {
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER);
ui_do_button(C, but->block, but, event);
}
}
@@ -8419,12 +8470,12 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
}
/* exported to interface.c: UI_but_active_only() */
-void ui_but_activate_event(bContext *C, ARegion *ar, uiBut *but)
+void ui_but_activate_event(bContext *C, ARegion *region, uiBut *but)
{
wmWindow *win = CTX_wm_window(C);
wmEvent event;
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER);
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
@@ -8432,7 +8483,10 @@ void ui_but_activate_event(bContext *C, ARegion *ar, uiBut *but)
event.customdata = but;
event.customdatafree = false;
+ ARegion *region_ctx = CTX_wm_region(C);
+ CTX_wm_region_set(C, region);
ui_do_button(C, but->block, but, &event);
+ CTX_wm_region_set(C, region_ctx);
}
/**
@@ -8441,30 +8495,30 @@ void ui_but_activate_event(bContext *C, ARegion *ar, uiBut *but)
* exported so menus can start with a highlighted button,
* even if the mouse isnt over it
*/
-void ui_but_activate_over(bContext *C, ARegion *ar, uiBut *but)
+void ui_but_activate_over(bContext *C, ARegion *region, uiBut *but)
{
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER);
}
void ui_but_execute_begin(struct bContext *UNUSED(C),
- struct ARegion *ar,
+ struct ARegion *region,
uiBut *but,
void **active_back)
{
- BLI_assert(ar != NULL);
- BLI_assert(BLI_findindex(&ar->uiblocks, but->block) != -1);
+ BLI_assert(region != NULL);
+ BLI_assert(BLI_findindex(&region->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;
*active_back = but->active;
data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData_Fake");
but->active = data;
- BLI_assert(ar != NULL);
- data->region = ar;
+ BLI_assert(region != NULL);
+ data->region = region;
}
void ui_but_execute_end(struct bContext *C,
- struct ARegion *UNUSED(ar),
+ struct ARegion *UNUSED(region),
uiBut *but,
void *active_back)
{
@@ -8479,39 +8533,39 @@ void ui_but_execute_end(struct bContext *C,
}
static void ui_handle_button_activate(bContext *C,
- ARegion *ar,
+ ARegion *region,
uiBut *but,
uiButtonActivateType type)
{
uiBut *oldbut;
uiHandleButtonData *data;
- oldbut = ui_region_find_active_but(ar);
+ oldbut = ui_region_find_active_but(region);
if (oldbut) {
data = oldbut->active;
data->cancel = true;
button_activate_exit(C, oldbut, data, false, false);
}
- button_activate_init(C, ar, but, type);
+ button_activate_init(C, region, but, type);
}
/**
* Use for key accelerator or default key to activate the button even if its not active.
*/
-static bool ui_handle_button_activate_by_type(bContext *C, ARegion *ar, uiBut *but)
+static bool ui_handle_button_activate_by_type(bContext *C, ARegion *region, uiBut *but)
{
if (but->type == UI_BTYPE_BUT_MENU) {
/* mainly for operator buttons */
- ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_APPLY);
+ ui_handle_button_activate(C, region, but, BUTTON_ACTIVATE_APPLY);
}
else if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN)) {
/* open sub-menus (like right arrow key) */
- ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_OPEN);
+ ui_handle_button_activate(C, region, but, BUTTON_ACTIVATE_OPEN);
}
else if (but->type == UI_BTYPE_MENU) {
/* activate menu items */
- ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
+ ui_handle_button_activate(C, region, but, BUTTON_ACTIVATE);
}
else {
#ifdef DEBUG
@@ -8566,11 +8620,11 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
uiHandleButtonData *data = but->active;
const uiHandleButtonState state_orig = data->state;
uiBlock *block;
- ARegion *ar;
+ ARegion *region;
int retval;
block = but->block;
- ar = data->region;
+ region = data->region;
retval = WM_UI_HANDLER_CONTINUE;
@@ -8597,7 +8651,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
block->handle->menuretval = UI_RETURN_CANCEL;
}
else if (ui_but_is_editable_as_text(but)) {
- ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_TEXT_EDITING);
+ ui_handle_button_activate(C, region, but, BUTTON_ACTIVATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
}
@@ -8607,13 +8661,13 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
}
#endif
case MOUSEMOVE: {
- uiBut *but_other = ui_but_find_mouse_over(ar, event);
+ uiBut *but_other = ui_but_find_mouse_over(region, event);
bool exit = false;
/* always deactivate button for pie menus,
* else moving to blank space will leave activated */
if ((!ui_block_is_menu(block) || ui_block_is_pie_menu(block)) &&
- !ui_but_contains_point_px(but, ar, event->x, event->y)) {
+ !ui_but_contains_point_px(but, region, event->x, event->y)) {
exit = true;
}
else if (but_other && ui_but_is_editable(but_other) && (but_other != but)) {
@@ -8626,7 +8680,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
}
else if (event->x != event->prevx || event->y != event->prevy) {
/* re-enable tooltip on mouse move */
- ui_blocks_set_tooltips(ar, true);
+ ui_blocks_set_tooltips(region, true);
button_tooltip_timer_reset(C, but);
}
@@ -8638,7 +8692,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
data->autoopentimer = NULL;
- if (ui_but_contains_point_px(but, ar, event->x, event->y) || but->active) {
+ if (ui_but_contains_point_px(but, region, event->x, event->y) || but->active) {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
}
}
@@ -8688,7 +8742,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
case MOUSEMOVE: {
/* deselect the button when moving the mouse away */
/* also de-activate for buttons that only show highlights */
- if (ui_but_contains_point_px(but, ar, event->x, event->y)) {
+ if (ui_but_contains_point_px(but, region, event->x, event->y)) {
/* Drag on a hold button (used in the toolbar) now opens it immediately. */
if (data->hold_action_timer) {
@@ -8751,7 +8805,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
}
}
- bt = ui_but_find_mouse_over(ar, event);
+ bt = ui_but_find_mouse_over(region, event);
if (bt && bt->active != data) {
if (but->type != UI_BTYPE_COLOR) { /* exception */
@@ -8763,7 +8817,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
}
case RIGHTMOUSE: {
if (event->val == KM_PRESS) {
- uiBut *bt = ui_but_find_mouse_over(ar, event);
+ uiBut *bt = ui_but_find_mouse_over(region, event);
if (bt && bt->active == data) {
button_activate_state(C, bt, BUTTON_STATE_HIGHLIGHT);
}
@@ -8812,18 +8866,18 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
/* for jumping to the next button with tab while text editing */
if (post_but) {
- button_activate_init(C, ar, post_but, post_type);
+ button_activate_init(C, region, post_but, post_type);
}
else {
- /* XXX issue is because WM_event_add_mousemove(C) is a bad hack and not reliable,
+ /* XXX issue is because WM_event_add_mousemove(wm) is a bad hack and not reliable,
* if that gets coded better this bypass can go away too.
*
* This is needed to make sure if a button was active,
* it stays active while the mouse is over it.
* This avoids adding mousemoves, see: [#33466] */
- if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT)) {
- if (ui_but_find_mouse_over(ar, event) == but) {
- button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT, BUTTON_STATE_WAIT_DRAG)) {
+ if (ui_but_find_mouse_over(region, event) == but) {
+ button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER);
}
}
}
@@ -8832,7 +8886,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
return retval;
}
-static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar, uiBut *listbox)
+static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *region, uiBut *listbox)
{
uiList *ui_list;
uiListDyn *dyn_data;
@@ -8849,7 +8903,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
mx = event->x;
my = event->y;
- ui_window_to_block(ar, listbox->block, &mx, &my);
+ ui_window_to_block(region, listbox->block, &mx, &my);
/* convert pan to scrollwheel */
if (type == MOUSEPAN) {
@@ -8863,7 +8917,8 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
}
if (val == KM_PRESS) {
- if ((ELEM(type, UPARROWKEY, DOWNARROWKEY) && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) ||
+ if ((ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY) &&
+ !IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) ||
((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->ctrl &&
!IS_EVENT_MOD(event, shift, alt, oskey)))) {
const int value_orig = RNA_property_int_get(&listbox->rnapoin, listbox->rnaprop);
@@ -8872,10 +8927,10 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
/* activate up/down the list */
value = value_orig;
if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) {
- inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? 1 : -1;
+ inc = ELEM(type, EVT_UPARROWKEY, WHEELUPMOUSE) ? 1 : -1;
}
else {
- inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? -1 : 1;
+ inc = ELEM(type, EVT_UPARROWKEY, WHEELUPMOUSE) ? -1 : 1;
}
if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) {
@@ -8957,8 +9012,8 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
}
if (redraw) {
- ED_region_tag_redraw(ar);
- ED_region_tag_refresh_ui(ar);
+ ED_region_tag_redraw(region);
+ ED_region_tag_refresh_ui(region);
}
return retval;
@@ -9086,13 +9141,13 @@ static bool ui_mouse_motion_towards_check(uiBlock *block,
* if this causes problems we could remove it and check on a different fix - campbell */
if (menu->region->next) {
/* am I the last menu (test) */
- ARegion *ar = menu->region->next;
+ ARegion *region = menu->region->next;
do {
- uiBlock *block_iter = ar->uiblocks.first;
+ uiBlock *block_iter = region->uiblocks.first;
if (block_iter && ui_block_is_menu(block_iter)) {
return true;
}
- } while ((ar = ar->next));
+ } while ((region = region->next));
}
/* annoying fix end! */
@@ -9191,27 +9246,30 @@ static char ui_menu_scroll_test(uiBlock *block, int my)
return 0;
}
-static void ui_menu_scroll_apply_offset_y(ARegion *ar, uiBlock *block, float dy)
+static void ui_menu_scroll_apply_offset_y(ARegion *region, uiBlock *block, float dy)
{
BLI_assert(dy != 0.0f);
- if (dy < 0.0f) {
- /* stop at top item, extra 0.5 unit Y makes it snap nicer */
- float ymax = -FLT_MAX;
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
- ymax = max_ff(ymax, bt->rect.ymax);
- }
- if (ymax + dy - UI_UNIT_Y * 0.5f < block->rect.ymax - UI_MENU_SCROLL_PAD) {
- dy = block->rect.ymax - ymax - UI_MENU_SCROLL_PAD;
- }
- }
- else {
- /* stop at bottom item, extra 0.5 unit Y makes it snap nicer */
- float ymin = FLT_MAX;
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
- ymin = min_ff(ymin, bt->rect.ymin);
+
+ if (ui_block_is_menu(block)) {
+ if (dy < 0.0f) {
+ /* Stop at top item, extra 0.5 UI_UNIT_Y makes it snap nicer. */
+ float ymax = -FLT_MAX;
+ LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
+ ymax = max_ff(ymax, bt->rect.ymax);
+ }
+ if (ymax + dy - UI_UNIT_Y * 0.5f < block->rect.ymax - UI_MENU_SCROLL_PAD) {
+ dy = block->rect.ymax - ymax - UI_MENU_SCROLL_PAD;
+ }
}
- if (ymin + dy + UI_UNIT_Y * 0.5f > block->rect.ymin + UI_MENU_SCROLL_PAD) {
- dy = block->rect.ymin - ymin + UI_MENU_SCROLL_PAD;
+ else {
+ /* Stop at bottom item, extra 0.5 UI_UNIT_Y makes it snap nicer. */
+ float ymin = FLT_MAX;
+ LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
+ ymin = min_ff(ymin, bt->rect.ymin);
+ }
+ if (ymin + dy + UI_UNIT_Y * 0.5f > block->rect.ymin + UI_MENU_SCROLL_PAD) {
+ dy = block->rect.ymin - ymin + UI_MENU_SCROLL_PAD;
+ }
}
}
@@ -9219,7 +9277,7 @@ static void ui_menu_scroll_apply_offset_y(ARegion *ar, uiBlock *block, float dy)
block->handle->scrolloffset += dy;
/* apply scroll offset */
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
bt->rect.ymin += dy;
bt->rect.ymax += dy;
}
@@ -9227,11 +9285,11 @@ static void ui_menu_scroll_apply_offset_y(ARegion *ar, uiBlock *block, float dy)
/* set flags again */
ui_popup_block_scrolltest(block);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
/** Scroll to activated button. */
-static bool ui_menu_scroll_to_but(ARegion *ar, uiBlock *block, uiBut *but_target)
+static bool ui_menu_scroll_to_but(ARegion *region, uiBlock *block, uiBut *but_target)
{
float dy = 0.0;
if (block->flag & UI_BLOCK_CLIPTOP) {
@@ -9245,14 +9303,14 @@ static bool ui_menu_scroll_to_but(ARegion *ar, uiBlock *block, uiBut *but_target
}
}
if (dy != 0.0f) {
- ui_menu_scroll_apply_offset_y(ar, block, dy);
+ ui_menu_scroll_apply_offset_y(region, block, dy);
return true;
}
return false;
}
/** Scroll to y location (in block space, see #ui_window_to_block). */
-static bool ui_menu_scroll_to_y(ARegion *ar, uiBlock *block, int y)
+static bool ui_menu_scroll_to_y(ARegion *region, uiBlock *block, int y)
{
const char test = ui_menu_scroll_test(block, y);
float dy = 0.0f;
@@ -9263,13 +9321,13 @@ static bool ui_menu_scroll_to_y(ARegion *ar, uiBlock *block, int y)
dy = UI_UNIT_Y; /* scroll to the bottom */
}
if (dy != 0.0f) {
- ui_menu_scroll_apply_offset_y(ar, block, dy);
+ ui_menu_scroll_apply_offset_y(region, block, dy);
return true;
}
return false;
}
-static bool ui_menu_scroll_step(ARegion *ar, uiBlock *block, const int scroll_dir)
+static bool ui_menu_scroll_step(ARegion *region, uiBlock *block, const int scroll_dir)
{
int my;
if (scroll_dir == 1) {
@@ -9289,7 +9347,7 @@ static bool ui_menu_scroll_step(ARegion *ar, uiBlock *block, const int scroll_di
return false;
}
- return ui_menu_scroll_to_y(ar, block, my);
+ return ui_menu_scroll_to_y(region, block, my);
}
/** \} */
@@ -9298,9 +9356,9 @@ static bool ui_menu_scroll_step(ARegion *ar, uiBlock *block, const int scroll_di
/** \name Menu Event Handling
* \{ */
-static void ui_region_auto_open_clear(ARegion *ar)
+static void ui_region_auto_open_clear(ARegion *region)
{
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
block->auto_open = false;
}
}
@@ -9332,8 +9390,8 @@ static bool ui_menu_pass_event_to_parent_if_nonactive(uiPopupBlockHandle *menu,
static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
{
- ARegion *ar = menu->region;
- uiBut *but = ui_region_find_active_but(ar);
+ ARegion *region = menu->region;
+ uiBut *but = ui_region_find_active_but(region);
int retval;
if (but) {
@@ -9342,6 +9400,11 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
if (event->val == KM_RELEASE) {
/* pass, needed so we can exit active menu-items when click-dragging out of them */
}
+ else if (but->type == UI_BTYPE_SEARCH_MENU) {
+ /* Pass, needed so search popup can have RMB context menu.
+ * This may be useful for other interactions which happen in the search popup
+ * without being directly over the search button. */
+ }
else if (!ui_block_is_menu(but->block) || ui_block_is_pie_menu(but->block)) {
/* pass, skip for dialogs */
}
@@ -9378,7 +9441,7 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
}
}
else {
- retval = ui_handle_button_over(C, event, ar);
+ retval = ui_handle_button_over(C, event, region);
}
return retval;
@@ -9419,28 +9482,28 @@ static int ui_handle_menu_event(bContext *C,
const bool is_parent_menu,
const bool is_floating)
{
- ARegion *ar;
+ ARegion *region;
uiBlock *block;
uiBut *but;
int mx, my, retval;
bool inside;
bool inside_title; /* check for title dragging */
- ar = menu->region;
- block = ar->uiblocks.first;
+ region = menu->region;
+ block = region->uiblocks.first;
retval = WM_UI_HANDLER_CONTINUE;
mx = event->x;
my = event->y;
- ui_window_to_block(ar, block, &mx, &my);
+ ui_window_to_block(region, block, &mx, &my);
/* check if mouse is inside block */
inside = BLI_rctf_isect_pt(&block->rect, mx, my);
inside_title = inside && ((my + (UI_UNIT_Y * 1.5f)) > block->rect.ymax);
/* if there's an active modal button, don't check events or outside, except for search menu */
- but = ui_region_find_active_but(ar);
+ but = ui_region_find_active_but(region);
#ifdef USE_DRAG_POPUP
if (menu->is_grab) {
@@ -9457,7 +9520,7 @@ static int ui_handle_menu_event(bContext *C,
add_v2_v2v2_int(menu->popup_create_vars.event_xy, menu->popup_create_vars.event_xy, mdiff);
- ui_popup_translate(ar, mdiff);
+ ui_popup_translate(region, mdiff);
}
return retval;
@@ -9475,7 +9538,7 @@ static int ui_handle_menu_event(bContext *C,
}
else if (event->type == TIMER) {
if (event->customdata == menu->scrolltimer) {
- ui_menu_scroll_to_y(ar, block, my);
+ ui_menu_scroll_to_y(region, block, my);
}
}
else {
@@ -9506,7 +9569,8 @@ static int ui_handle_menu_event(bContext *C,
/* Closing sub-levels of pull-downs.
*
* The actual event is handled by the button under the cursor.
- * This is done so we can right click on menu items even when they have sub-menus open. */
+ * This is done so we can right click on menu items even when they have sub-menus open.
+ */
case RIGHTMOUSE:
if (inside == false) {
if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
@@ -9526,7 +9590,7 @@ static int ui_handle_menu_event(bContext *C,
break;
/* Closing sub-levels of pull-downs. */
- case LEFTARROWKEY:
+ case EVT_LEFTARROWKEY:
if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
if (block->saferct.first) {
menu->menuretval = UI_RETURN_OUT;
@@ -9537,14 +9601,14 @@ static int ui_handle_menu_event(bContext *C,
break;
/* Opening sub-levels of pull-downs. */
- case RIGHTARROWKEY:
+ case EVT_RIGHTARROWKEY:
if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval)) {
break;
}
- but = ui_region_find_active_but(ar);
+ but = ui_region_find_active_but(region);
if (!but) {
/* no item active, we make first active */
@@ -9557,7 +9621,7 @@ static int ui_handle_menu_event(bContext *C,
}
if (but && ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN)) {
- ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_OPEN);
+ ui_handle_button_activate(C, region, but, BUTTON_ACTIVATE_OPEN);
}
}
@@ -9581,24 +9645,24 @@ static int ui_handle_menu_event(bContext *C,
if (type != MOUSEPAN) {
const int scroll_dir = (type == WHEELUPMOUSE) ? 1 : -1;
- if (ui_menu_scroll_step(ar, block, scroll_dir)) {
+ if (ui_menu_scroll_step(region, block, scroll_dir)) {
if (but) {
but->active->cancel = true;
button_activate_exit(C, but, but->active, false, false);
}
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
}
}
break;
}
ATTR_FALLTHROUGH;
}
- case UPARROWKEY:
- case DOWNARROWKEY:
- case PAGEUPKEY:
- case PAGEDOWNKEY:
- case HOMEKEY:
- case ENDKEY:
+ case EVT_UPARROWKEY:
+ case EVT_DOWNARROWKEY:
+ case EVT_PAGEUPKEY:
+ case EVT_PAGEDOWNKEY:
+ case EVT_HOMEKEY:
+ case EVT_ENDKEY:
/* arrowkeys: only handle for block_loop blocks */
if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
/* pass */
@@ -9617,13 +9681,13 @@ static int ui_handle_menu_event(bContext *C,
uiMenuScrollType scrolltype;
bool ui_block_flipped = (block->flag & UI_BLOCK_IS_FLIP) != 0;
- if (ELEM(type, PAGEUPKEY, HOMEKEY)) {
+ if (ELEM(type, EVT_PAGEUPKEY, EVT_HOMEKEY)) {
scrolltype = ui_block_flipped ? MENU_SCROLL_TOP : MENU_SCROLL_BOTTOM;
}
- else if (ELEM(type, PAGEDOWNKEY, ENDKEY)) {
+ else if (ELEM(type, EVT_PAGEDOWNKEY, EVT_ENDKEY)) {
scrolltype = ui_block_flipped ? MENU_SCROLL_BOTTOM : MENU_SCROLL_TOP;
}
- else if (ELEM(type, UPARROWKEY, WHEELUPMOUSE)) {
+ else if (ELEM(type, EVT_UPARROWKEY, WHEELUPMOUSE)) {
scrolltype = ui_block_flipped ? MENU_SCROLL_UP : MENU_SCROLL_DOWN;
}
else {
@@ -9638,20 +9702,14 @@ static int ui_handle_menu_event(bContext *C,
ui_mouse_motion_keynav_init(&menu->keynav_state, event);
#endif
- but = ui_region_find_active_but(ar);
+ but = ui_region_find_active_but(region);
if (but) {
/* Apply scroll operation. */
if (scrolltype == MENU_SCROLL_DOWN) {
but = ui_but_next(but);
- if (but == NULL) {
- but = ui_but_first(block);
- }
}
else if (scrolltype == MENU_SCROLL_UP) {
but = ui_but_prev(but);
- if (but == NULL) {
- but = ui_but_last(block);
- }
}
else if (scrolltype == MENU_SCROLL_TOP) {
but = ui_but_first(block);
@@ -9661,9 +9719,23 @@ static int ui_handle_menu_event(bContext *C,
}
}
+ if (!but) {
+ /* wrap button or no active button*/
+ uiBut *but_wrap = NULL;
+ if (ELEM(scrolltype, MENU_SCROLL_UP, MENU_SCROLL_BOTTOM)) {
+ but_wrap = ui_but_last(block);
+ }
+ else if (ELEM(scrolltype, MENU_SCROLL_DOWN, MENU_SCROLL_TOP)) {
+ but_wrap = ui_but_first(block);
+ }
+ if (but_wrap) {
+ but = but_wrap;
+ }
+ }
+
if (but) {
- ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
- ui_menu_scroll_to_but(ar, block, but);
+ ui_handle_button_activate(C, region, but, BUTTON_ACTIVATE);
+ ui_menu_scroll_to_but(region, block, but);
}
}
@@ -9672,60 +9744,60 @@ static int ui_handle_menu_event(bContext *C,
break;
- case ONEKEY:
- case PAD1:
+ case EVT_ONEKEY:
+ case EVT_PAD1:
act = 1;
ATTR_FALLTHROUGH;
- case TWOKEY:
- case PAD2:
+ case EVT_TWOKEY:
+ case EVT_PAD2:
if (act == 0) {
act = 2;
}
ATTR_FALLTHROUGH;
- case THREEKEY:
- case PAD3:
+ case EVT_THREEKEY:
+ case EVT_PAD3:
if (act == 0) {
act = 3;
}
ATTR_FALLTHROUGH;
- case FOURKEY:
- case PAD4:
+ case EVT_FOURKEY:
+ case EVT_PAD4:
if (act == 0) {
act = 4;
}
ATTR_FALLTHROUGH;
- case FIVEKEY:
- case PAD5:
+ case EVT_FIVEKEY:
+ case EVT_PAD5:
if (act == 0) {
act = 5;
}
ATTR_FALLTHROUGH;
- case SIXKEY:
- case PAD6:
+ case EVT_SIXKEY:
+ case EVT_PAD6:
if (act == 0) {
act = 6;
}
ATTR_FALLTHROUGH;
- case SEVENKEY:
- case PAD7:
+ case EVT_SEVENKEY:
+ case EVT_PAD7:
if (act == 0) {
act = 7;
}
ATTR_FALLTHROUGH;
- case EIGHTKEY:
- case PAD8:
+ case EVT_EIGHTKEY:
+ case EVT_PAD8:
if (act == 0) {
act = 8;
}
ATTR_FALLTHROUGH;
- case NINEKEY:
- case PAD9:
+ case EVT_NINEKEY:
+ case EVT_PAD9:
if (act == 0) {
act = 9;
}
ATTR_FALLTHROUGH;
- case ZEROKEY:
- case PAD0:
+ case EVT_ZEROKEY:
+ case EVT_PAD0:
if (act == 0) {
act = 10;
}
@@ -9745,7 +9817,11 @@ static int ui_handle_menu_event(bContext *C,
for (but = block->buttons.first; but; but = but->next) {
bool doit = false;
- if (!ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) {
+ if (!ELEM(but->type,
+ UI_BTYPE_LABEL,
+ UI_BTYPE_SEPR,
+ UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_IMAGE)) {
count++;
}
@@ -9776,7 +9852,7 @@ static int ui_handle_menu_event(bContext *C,
activate = BUTTON_ACTIVATE_APPLY;
}
- ui_handle_button_activate(C, ar, but, activate);
+ ui_handle_button_activate(C, region, but, activate);
break;
}
}
@@ -9786,32 +9862,32 @@ static int ui_handle_menu_event(bContext *C,
break;
/* Handle keystrokes on menu items */
- case AKEY:
- case BKEY:
- case CKEY:
- case DKEY:
- case EKEY:
- case FKEY:
- case GKEY:
- case HKEY:
- case IKEY:
- case JKEY:
- case KKEY:
- case LKEY:
- case MKEY:
- case NKEY:
- case OKEY:
- case PKEY:
- case QKEY:
- case RKEY:
- case SKEY:
- case TKEY:
- case UKEY:
- case VKEY:
- case WKEY:
- case XKEY:
- case YKEY:
- case ZKEY: {
+ case EVT_AKEY:
+ case EVT_BKEY:
+ case EVT_CKEY:
+ case EVT_DKEY:
+ case EVT_EKEY:
+ case EVT_FKEY:
+ case EVT_GKEY:
+ case EVT_HKEY:
+ case EVT_IKEY:
+ case EVT_JKEY:
+ case EVT_KKEY:
+ case EVT_LKEY:
+ case EVT_MKEY:
+ case EVT_NKEY:
+ case EVT_OKEY:
+ case EVT_PKEY:
+ case EVT_QKEY:
+ case EVT_RKEY:
+ case EVT_SKEY:
+ case EVT_TKEY:
+ case EVT_UKEY:
+ case EVT_VKEY:
+ case EVT_WKEY:
+ case EVT_XKEY:
+ case EVT_YKEY:
+ case EVT_ZKEY: {
if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
!IS_EVENT_MOD(event, shift, ctrl, oskey)) {
if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval)) {
@@ -9821,10 +9897,10 @@ 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, ar, but);
+ UI_but_execute(C, region, but);
}
else {
- ui_handle_button_activate_by_type(C, ar, but);
+ ui_handle_button_activate_by_type(C, region, but);
}
break;
}
@@ -9893,23 +9969,23 @@ static int ui_handle_menu_event(bContext *C,
retval = WM_UI_HANDLER_BREAK;
}
#endif
- else if (event->type == ESCKEY && event->val == KM_PRESS) {
+ else if (event->type == EVT_ESCKEY && event->val == KM_PRESS) {
/* Escape cancels this and all preceding menus. */
menu->menuretval = UI_RETURN_CANCEL;
}
- else if (ELEM(event->type, RETKEY, PADENTER) && event->val == KM_PRESS) {
+ else if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER) && event->val == KM_PRESS) {
uiBut *but_default = ui_region_find_first_but_test_flag(
- ar, UI_BUT_ACTIVE_DEFAULT, UI_HIDDEN);
+ region, 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, ar, but_default);
+ UI_but_execute(C, region, but_default);
}
else {
- ui_handle_button_activate_by_type(C, ar, but_default);
+ ui_handle_button_activate_by_type(C, region, but_default);
}
}
else {
- uiBut *but_active = ui_region_find_active_but(ar);
+ uiBut *but_active = ui_region_find_active_but(region);
/* enter will always close this block, we let the event
* get handled by the button if it is activated, otherwise we cancel */
@@ -9921,7 +9997,7 @@ static int ui_handle_menu_event(bContext *C,
#ifdef USE_DRAG_POPUP
else if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) &&
(inside && is_floating && inside_title)) {
- if (!but || !ui_but_contains_point_px(but, ar, event->x, event->y)) {
+ if (!but || !ui_but_contains_point_px(but, region, event->x, event->y)) {
if (but) {
UI_but_tooltip_timer_remove(C, but);
}
@@ -10016,16 +10092,16 @@ static int ui_handle_menu_return_submenu(bContext *C,
const wmEvent *event,
uiPopupBlockHandle *menu)
{
- ARegion *ar;
+ ARegion *region;
uiBut *but;
uiBlock *block;
uiHandleButtonData *data;
uiPopupBlockHandle *submenu;
- ar = menu->region;
- block = ar->uiblocks.first;
+ region = menu->region;
+ block = region->uiblocks.first;
- but = ui_region_find_active_but(ar);
+ but = ui_region_find_active_but(region);
BLI_assert(but);
@@ -10149,7 +10225,7 @@ static int ui_but_pie_button_activate(bContext *C, uiBut *but, uiPopupBlockHandl
static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
{
- ARegion *ar;
+ ARegion *region;
uiBlock *block;
uiBut *but;
float event_xy[2];
@@ -10167,13 +10243,13 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
retval = WM_UI_HANDLER_CONTINUE;
}
- ar = menu->region;
- block = ar->uiblocks.first;
+ region = menu->region;
+ block = region->uiblocks.first;
is_click_style = (block->pie_data.flags & UI_PIE_CLICK_STYLE);
/* if there's an active modal button, don't check events or outside, except for search menu */
- but = ui_region_find_active_but(ar);
+ but = ui_region_find_active_but(region);
if (menu->scrolltimer == NULL) {
menu->scrolltimer = WM_event_add_timer(
@@ -10186,7 +10262,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
event_xy[0] = event->x;
event_xy[1] = event->y;
- ui_window_to_block_fl(ar, block, &event_xy[0], &event_xy[1]);
+ ui_window_to_block_fl(region, block, &event_xy[0], &event_xy[1]);
/* Distance from initial point. */
dist = ui_block_calc_pie_segment(block, event_xy);
@@ -10236,7 +10312,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
}
block->pie_data.alphafac = fac;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
@@ -10270,7 +10346,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
}
/* why redraw here? It's simple, we are getting many double click events here.
* Those operate like mouse move events almost */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
else {
if ((duration < 0.01 * U.pie_tap_timeout) &&
@@ -10316,7 +10392,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
ui_handle_menu_button(C, event, menu);
/* mouse move should always refresh the area for pie menus */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case LEFTMOUSE:
@@ -10330,37 +10406,37 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
}
break;
- case ESCKEY:
+ case EVT_ESCKEY:
case RIGHTMOUSE:
menu->menuretval = UI_RETURN_CANCEL;
break;
- case AKEY:
- case BKEY:
- case CKEY:
- case DKEY:
- case EKEY:
- case FKEY:
- case GKEY:
- case HKEY:
- case IKEY:
- case JKEY:
- case KKEY:
- case LKEY:
- case MKEY:
- case NKEY:
- case OKEY:
- case PKEY:
- case QKEY:
- case RKEY:
- case SKEY:
- case TKEY:
- case UKEY:
- case VKEY:
- case WKEY:
- case XKEY:
- case YKEY:
- case ZKEY: {
+ case EVT_AKEY:
+ case EVT_BKEY:
+ case EVT_CKEY:
+ case EVT_DKEY:
+ case EVT_EKEY:
+ case EVT_FKEY:
+ case EVT_GKEY:
+ case EVT_HKEY:
+ case EVT_IKEY:
+ case EVT_JKEY:
+ case EVT_KKEY:
+ case EVT_LKEY:
+ case EVT_MKEY:
+ case EVT_NKEY:
+ case EVT_OKEY:
+ case EVT_PKEY:
+ case EVT_QKEY:
+ case EVT_RKEY:
+ case EVT_SKEY:
+ case EVT_TKEY:
+ case EVT_UKEY:
+ case EVT_VKEY:
+ case EVT_WKEY:
+ case EVT_XKEY:
+ case EVT_YKEY:
+ case EVT_ZKEY: {
if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
!IS_EVENT_MOD(event, shift, ctrl, oskey)) {
for (but = block->buttons.first; but; but = but->next) {
@@ -10373,8 +10449,8 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
}
#define CASE_NUM_TO_DIR(n, d) \
- case (ZEROKEY + n): \
- case (PAD0 + n): { \
+ case (EVT_ZEROKEY + n): \
+ case (EVT_PAD0 + n): { \
if (num_dir == UI_RADIAL_NONE) \
num_dir = d; \
} \
@@ -10535,26 +10611,26 @@ void UI_popup_menu_retval_set(const uiBlock *block, const int retval, const bool
static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
- ARegion *ar;
+ ARegion *region;
uiBut *but, *listbox;
int retval;
/* here we handle buttons at the region level, non-modal */
- ar = CTX_wm_region(C);
+ region = CTX_wm_region(C);
retval = WM_UI_HANDLER_CONTINUE;
- if (ar == NULL || BLI_listbase_is_empty(&ar->uiblocks)) {
+ if (region == NULL || BLI_listbase_is_empty(&region->uiblocks)) {
return retval;
}
/* either handle events for already activated button or try to activate */
- but = ui_region_find_active_but(ar);
- listbox = ui_list_find_mouse_over(ar, event);
+ but = ui_region_find_active_but(region);
+ listbox = ui_list_find_mouse_over(region, event);
- retval = ui_handler_panel_region(C, event, ar, listbox ? listbox : but);
+ retval = ui_handler_panel_region(C, event, region, listbox ? listbox : but);
if (retval == WM_UI_HANDLER_CONTINUE && listbox) {
- retval = ui_handle_list_event(C, event, ar, listbox);
+ retval = ui_handle_list_event(C, event, region, listbox);
/* interactions with the listbox should disable tips */
if (retval == WM_UI_HANDLER_BREAK) {
@@ -10569,13 +10645,13 @@ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(use
retval = ui_handle_button_event(C, event, but);
}
else {
- retval = ui_handle_button_over(C, event, ar);
+ retval = ui_handle_button_over(C, event, region);
}
}
/* re-enable tooltips */
if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) {
- ui_blocks_set_tooltips(ar, true);
+ ui_blocks_set_tooltips(region, true);
}
/* delayed apply callbacks */
@@ -10586,25 +10662,25 @@ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(use
static void ui_region_handler_remove(bContext *C, void *UNUSED(userdata))
{
- bScreen *sc;
- ARegion *ar;
+ bScreen *screen;
+ ARegion *region;
- ar = CTX_wm_region(C);
- if (ar == NULL) {
+ region = CTX_wm_region(C);
+ if (region == NULL) {
return;
}
- UI_blocklist_free(C, &ar->uiblocks);
+ UI_blocklist_free(C, &region->uiblocks);
- sc = CTX_wm_screen(C);
- if (sc == NULL) {
+ screen = CTX_wm_screen(C);
+ if (screen == NULL) {
return;
}
/* delayed apply callbacks, but not for screen level regions, those
* we rather do at the very end after closing them all, which will
* be done in ui_region_handler/window */
- if (BLI_findindex(&sc->regionbase, ar) == -1) {
+ if (BLI_findindex(&screen->regionbase, region) == -1) {
ui_apply_but_funcs_after(C);
}
}
@@ -10614,11 +10690,11 @@ static void ui_region_handler_remove(bContext *C, void *UNUSED(userdata))
static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
ARegion *menu_region = CTX_wm_menu(C);
- ARegion *ar = menu_region ? menu_region : CTX_wm_region(C);
+ ARegion *region = menu_region ? menu_region : CTX_wm_region(C);
uiBut *but;
int retval = WM_UI_HANDLER_CONTINUE;
- but = ui_region_find_active_but(ar);
+ but = ui_region_find_active_but(region);
if (but) {
bScreen *screen = CTX_wm_screen(C);
@@ -10635,7 +10711,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
/* make sure mouse isn't inside another menu (see T43247) */
(ui_screen_region_find_mouse_over(screen, event) == NULL) &&
(ELEM(but->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER, UI_BTYPE_MENU)) &&
- (but_other = ui_but_find_mouse_over(ar, event)) && (but != but_other) &&
+ (but_other = ui_but_find_mouse_over(region, event)) && (but != but_other) &&
(ELEM(but_other->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER, UI_BTYPE_MENU)) &&
/* Hover-opening menu's doesn't work well for buttons over one another
* along the same axis the menu is opening on (see T71719). */
@@ -10646,7 +10722,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
/* 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) {
- ui_handle_button_activate(C, ar, but_other, BUTTON_ACTIVATE_OVER);
+ ui_handle_button_activate(C, region, but_other, BUTTON_ACTIVATE_OVER);
button_activate_state(C, but_other, BUTTON_STATE_MENU_OPEN);
retval = WM_UI_HANDLER_BREAK;
}
@@ -10677,7 +10753,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
/* re-enable tooltips */
if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) {
- ui_blocks_set_tooltips(ar, true);
+ ui_blocks_set_tooltips(region, true);
}
if (but && but->active && but->active->menu) {
@@ -10762,15 +10838,12 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata)
if (temp.popup_func) {
temp.popup_func(C, temp.popup_arg, temp.retvalue);
}
- if (temp.optype) {
- WM_operator_name_call_ptr(C, temp.optype, temp.opcontext, NULL);
- }
}
else if (temp.cancel_func) {
temp.cancel_func(C, temp.popup_arg);
}
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(win);
}
else {
/* re-enable tooltips */
@@ -10859,14 +10932,14 @@ void UI_popup_handlers_remove_all(bContext *C, ListBase *handlers)
}
bool UI_textbutton_activate_rna(const bContext *C,
- ARegion *ar,
+ ARegion *region,
const void *rna_poin_data,
const char *rna_prop_id)
{
uiBlock *block;
uiBut *but = NULL;
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
if (but->type == UI_BTYPE_TEXT) {
if (but->rnaprop && but->rnapoin.data == rna_poin_data) {
@@ -10882,7 +10955,7 @@ bool UI_textbutton_activate_rna(const bContext *C,
}
if (but) {
- UI_but_active_only(C, ar, block, but);
+ UI_but_active_only(C, region, block, but);
return true;
}
else {
@@ -10892,11 +10965,11 @@ bool UI_textbutton_activate_rna(const bContext *C,
bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
uiBlock *block;
uiBut *but = NULL;
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
if (but == actbut && but->type == UI_BTYPE_TEXT) {
break;
@@ -10909,7 +10982,7 @@ bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
}
if (but) {
- UI_but_active_only(C, ar, block, but);
+ UI_but_active_only(C, region, block, but);
return true;
}
else {
@@ -10928,9 +11001,8 @@ void UI_screen_free_active_but(const bContext *C, bScreen *screen)
{
wmWindow *win = CTX_wm_window(C);
- ED_screen_areas_iter(win, screen, area)
- {
- for (ARegion *region = area->regionbase.first; region; region = region->next) {
+ ED_screen_areas_iter (win, screen, area) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
uiBut *but = ui_region_find_active_but(region);
if (but) {
uiHandleButtonData *data = but->active;
@@ -10949,8 +11021,8 @@ void UI_screen_free_active_but(const bContext *C, bScreen *screen)
/* called in region context */
bool UI_but_active_drop_name(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
- uiBut *but = ui_region_find_active_but(ar);
+ ARegion *region = CTX_wm_region(C);
+ uiBut *but = ui_region_find_active_but(region);
if (but) {
if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
@@ -10963,10 +11035,10 @@ bool UI_but_active_drop_name(bContext *C)
bool UI_but_active_drop_color(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- if (ar) {
- uiBut *but = ui_region_find_active_but(ar);
+ if (region) {
+ uiBut *but = ui_region_find_active_but(region);
if (but && but->type == UI_BTYPE_COLOR) {
return true;
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 41606fce915..c94a95890c0 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -27,16 +27,16 @@
#include "MEM_guardedalloc.h"
-#include "GPU_matrix.h"
#include "GPU_batch.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "GPU_state.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
-#include "BLI_math_vector.h"
#include "BLI_math_color_blend.h"
+#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
@@ -45,16 +45,14 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "DNA_workspace_types.h"
#include "RNA_access.h"
-#include "RNA_enum_types.h"
+#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_paint.h"
#include "BKE_icons.h"
-#include "BKE_appdir.h"
+#include "BKE_paint.h"
#include "BKE_studiolight.h"
#include "IMB_imbuf.h"
@@ -63,10 +61,6 @@
#include "BIF_glutil.h"
-#include "DEG_depsgraph.h"
-
-#include "DRW_engine.h"
-
#include "ED_datafiles.h"
#include "ED_keyframes_draw.h"
#include "ED_render.h"
@@ -119,6 +113,7 @@ typedef struct DrawInfo {
} vector;
struct {
ImBuf *image_cache;
+ bool inverted;
} geom;
struct {
IconImage *image;
@@ -566,14 +561,14 @@ static DrawInfo *g_di_event_list = NULL;
int UI_icon_from_event_type(short event_type, short event_value)
{
- if (event_type == RIGHTSHIFTKEY) {
- event_type = LEFTSHIFTKEY;
+ if (event_type == EVT_RIGHTSHIFTKEY) {
+ event_type = EVT_LEFTSHIFTKEY;
}
- else if (event_type == RIGHTCTRLKEY) {
- event_type = LEFTCTRLKEY;
+ else if (event_type == EVT_RIGHTCTRLKEY) {
+ event_type = EVT_LEFTCTRLKEY;
}
- else if (event_type == RIGHTALTKEY) {
- event_type = LEFTALTKEY;
+ else if (event_type == EVT_RIGHTALTKEY) {
+ event_type = EVT_LEFTALTKEY;
}
else if (event_type == EVT_TWEAK_L) {
event_type = LEFTMOUSE;
@@ -647,54 +642,54 @@ static void init_event_icons(void)
const int w = 16; /* DUMMY */
- INIT_EVENT_ICON(ICON_EVENT_A, AKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_B, BKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_C, CKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_D, DKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_E, EKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F, FKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_G, GKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_H, HKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_I, IKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_J, JKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_K, KKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_L, LKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_M, MKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_N, NKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_O, OKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_P, PKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_Q, QKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_R, RKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_S, SKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_T, TKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_U, UKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_V, VKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_W, WKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_X, XKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_Y, YKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_Z, ZKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_SHIFT, LEFTSHIFTKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_CTRL, LEFTCTRLKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_ALT, LEFTALTKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_OS, OSKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F1, F1KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F2, F2KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F3, F3KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F4, F4KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F5, F5KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F6, F6KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F7, F7KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F8, F8KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F9, F9KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F10, F10KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F11, F11KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_F12, F12KEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_ESC, ESCKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_TAB, TABKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_PAGEUP, PAGEUPKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_PAGEDOWN, PAGEDOWNKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_RETURN, RETKEY, KM_ANY);
- INIT_EVENT_ICON(ICON_EVENT_SPACEKEY, SPACEKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_A, EVT_AKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_B, EVT_BKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_C, EVT_CKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_D, EVT_DKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_E, EVT_EKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F, EVT_FKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_G, EVT_GKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_H, EVT_HKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_I, EVT_IKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_J, EVT_JKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_K, EVT_KKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_L, EVT_LKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_M, EVT_MKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_N, EVT_NKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_O, EVT_OKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_P, EVT_PKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_Q, EVT_QKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_R, EVT_RKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_S, EVT_SKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_T, EVT_TKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_U, EVT_UKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_V, EVT_VKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_W, EVT_WKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_X, EVT_XKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_Y, EVT_YKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_Z, EVT_ZKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_SHIFT, EVT_LEFTSHIFTKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_CTRL, EVT_LEFTCTRLKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_ALT, EVT_LEFTALTKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_OS, EVT_OSKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F1, EVT_F1KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F2, EVT_F2KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F3, EVT_F3KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F4, EVT_F4KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F5, EVT_F5KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F6, EVT_F6KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F7, EVT_F7KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F8, EVT_F8KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F9, EVT_F9KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F10, EVT_F10KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F11, EVT_F11KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F12, EVT_F12KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_ESC, EVT_ESCKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_TAB, EVT_TABKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_PAGEUP, EVT_PAGEUPKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_PAGEDOWN, EVT_PAGEDOWNKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_RETURN, EVT_RETKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_SPACEKEY, EVT_SPACEKEY, KM_ANY);
g_di_event_list = di_next;
@@ -758,11 +753,11 @@ static ImBuf *create_mono_icon_with_border(ImBuf *buf,
// blur alpha channel
const int write_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx;
float alpha_accum = 0.0;
- unsigned int alpha_samples = 0;
+ uint alpha_samples = 0;
for (int ax = asx; ax < aex; ax++) {
for (int ay = asy; ay < aey; ay++) {
const int offset_read = (sy + ay) * buf->x + (sx + ax);
- unsigned int color_read = buf->rect[offset_read];
+ uint color_read = buf->rect[offset_read];
const float alpha_read = ((color_read & 0xff000000) >> 24) / 255.0;
alpha_accum += alpha_read;
alpha_samples += 1;
@@ -781,8 +776,8 @@ static ImBuf *create_mono_icon_with_border(ImBuf *buf,
const float border_srgb[4] = {
0, 0, 0, MIN2(1.0, blurred_alpha * border_sharpness) * border_intensity};
- const unsigned int color_read = buf->rect[offset_write];
- const unsigned char *orig_color = (unsigned char *)&color_read;
+ const uint color_read = buf->rect[offset_write];
+ const uchar *orig_color = (uchar *)&color_read;
float border_rgba[4];
float orig_rgba[4];
@@ -794,8 +789,8 @@ static ImBuf *create_mono_icon_with_border(ImBuf *buf,
blend_color_interpolate_float(dest_rgba, orig_rgba, border_rgba, 1.0 - orig_rgba[3]);
linearrgb_to_srgb_v4(dest_srgb, dest_rgba);
- unsigned int alpha_mask = ((unsigned int)(dest_srgb[3] * 255)) << 24;
- unsigned int cpack = rgb_to_cpack(dest_srgb[0], dest_srgb[1], dest_srgb[2]) | alpha_mask;
+ uint alpha_mask = ((uint)(dest_srgb[3] * 255)) << 24;
+ uint cpack = rgb_to_cpack(dest_srgb[0], dest_srgb[1], dest_srgb[2]) | alpha_mask;
result->rect[offset_write] = cpack;
}
}
@@ -1128,8 +1123,8 @@ void UI_icons_free(void)
#ifndef WITH_HEADLESS
free_icons_textures();
free_iconfile_list(&iconfilelist);
- BKE_icons_free();
#endif
+ BKE_icons_free();
}
void UI_icons_free_drawinfo(void *drawinfo)
@@ -1833,15 +1828,23 @@ static void icon_draw_size(float x,
}
#endif
+ /* If the theme is light, we will adjust the icon colors. */
+ const bool invert = (rgb_to_grayscale_byte(btheme->tui.wcol_toolbar_item.inner) > 128);
+ const bool geom_inverted = di->data.geom.inverted;
+
/* This could re-generate often if rendered at different sizes in the one interface.
* TODO(campbell): support caching multiple sizes. */
ImBuf *ibuf = di->data.geom.image_cache;
- if ((ibuf == NULL) || (ibuf->x != w) || (ibuf->y != h)) {
+ if ((ibuf == NULL) || (ibuf->x != w) || (ibuf->y != h) || (invert != geom_inverted)) {
if (ibuf) {
IMB_freeImBuf(ibuf);
}
+ if (invert != geom_inverted) {
+ BKE_icon_geom_invert_lightness(icon->obj);
+ }
ibuf = BKE_icon_geom_rasterize(icon->obj, w, h);
di->data.geom.image_cache = ibuf;
+ di->data.geom.inverted = invert;
}
GPU_blend_set_func_separate(
@@ -1883,7 +1886,7 @@ static void icon_draw_size(float x,
mul_v4_fl(color, alpha);
float border_outset = 0.0;
- unsigned int border_texel = 0;
+ uint border_texel = 0;
#ifndef WITH_HEADLESS
if (with_border) {
const float scale = (float)ICON_GRID_W / (float)ICON_DEFAULT_WIDTH;
@@ -2006,8 +2009,8 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
Object *ob = CTX_data_active_object(C);
const EnumPropertyItem *items = NULL;
ePaintMode paint_mode = PAINT_MODE_INVALID;
- ScrArea *sa = CTX_wm_area(C);
- char space_type = sa->spacetype;
+ ScrArea *area = CTX_wm_area(C);
+ char space_type = area->spacetype;
/* Fallback to 3D view. */
if (space_type == SPACE_PROPERTIES) {
space_type = SPACE_VIEW3D;
@@ -2032,8 +2035,8 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
}
}
else if (space_type == SPACE_IMAGE) {
- if (sa->spacetype == space_type) {
- const SpaceImage *sima = sa->spacedata.first;
+ if (area->spacetype == space_type) {
+ const SpaceImage *sima = area->spacedata.first;
if (sima->mode == SI_MODE_PAINT) {
paint_mode = PAINT_MODE_TEXTURE_2D;
}
@@ -2041,7 +2044,10 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
}
/* reset the icon */
- if ((ob != NULL) && (ob->mode & OB_MODE_PAINT_GPENCIL) && (br->gpencil_settings != NULL)) {
+ if ((ob != NULL) &&
+ (ob->mode & (OB_MODE_PAINT_GPENCIL | OB_MODE_VERTEX_GPENCIL | OB_MODE_SCULPT_GPENCIL |
+ OB_MODE_WEIGHT_GPENCIL)) &&
+ (br->gpencil_settings != NULL)) {
switch (br->gpencil_settings->icon_id) {
case GP_BRUSH_ICON_PENCIL:
br->id.icon_id = ICON_GPBRUSH_PENCIL;
@@ -2079,6 +2085,54 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
case GP_BRUSH_ICON_ERASE_STROKE:
br->id.icon_id = ICON_GPBRUSH_ERASE_STROKE;
break;
+ case GP_BRUSH_ICON_TINT:
+ br->id.icon_id = ICON_BRUSH_TEXDRAW;
+ break;
+ case GP_BRUSH_ICON_VERTEX_DRAW:
+ br->id.icon_id = ICON_BRUSH_MIX;
+ break;
+ case GP_BRUSH_ICON_VERTEX_BLUR:
+ br->id.icon_id = ICON_BRUSH_BLUR;
+ break;
+ case GP_BRUSH_ICON_VERTEX_AVERAGE:
+ br->id.icon_id = ICON_BRUSH_BLUR;
+ break;
+ case GP_BRUSH_ICON_VERTEX_SMEAR:
+ br->id.icon_id = ICON_BRUSH_BLUR;
+ break;
+ case GP_BRUSH_ICON_VERTEX_REPLACE:
+ br->id.icon_id = ICON_BRUSH_MIX;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_SMOOTH:
+ br->id.icon_id = ICON_GPBRUSH_SMOOTH;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_THICKNESS:
+ br->id.icon_id = ICON_GPBRUSH_THICKNESS;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_STRENGTH:
+ br->id.icon_id = ICON_GPBRUSH_STRENGTH;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_RANDOMIZE:
+ br->id.icon_id = ICON_GPBRUSH_RANDOMIZE;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_GRAB:
+ br->id.icon_id = ICON_GPBRUSH_GRAB;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_PUSH:
+ br->id.icon_id = ICON_GPBRUSH_PUSH;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_TWIST:
+ br->id.icon_id = ICON_GPBRUSH_TWIST;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_PINCH:
+ br->id.icon_id = ICON_GPBRUSH_PINCH;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_CLONE:
+ br->id.icon_id = ICON_GPBRUSH_CLONE;
+ break;
+ case GP_BRUSH_ICON_GPBRUSH_WEIGHT:
+ br->id.icon_id = ICON_GPBRUSH_WEIGHT;
+ break;
default:
br->id.icon_id = ICON_GPBRUSH_PEN;
break;
@@ -2256,10 +2310,19 @@ int UI_idcode_icon_get(const int idcode)
return ICON_TEXT;
case ID_VF:
return ICON_FONT_DATA;
+ case ID_HA:
+ return ICON_HAIR_DATA;
+ case ID_PT:
+ return ICON_POINTCLOUD_DATA;
+ case ID_VO:
+ return ICON_VOLUME_DATA;
case ID_WO:
return ICON_WORLD_DATA;
case ID_WS:
return ICON_WORKSPACE;
+ case ID_SIM:
+ /* TODO: Use correct icon. */
+ return ICON_PHYSICS;
default:
return ICON_NONE;
}
@@ -2302,3 +2365,25 @@ void UI_icon_draw_ex(float x,
mono_color,
mono_border);
}
+
+/* ********** Alert Icons ********** */
+
+ImBuf *UI_alert_image(eAlertIcon icon)
+{
+#ifdef WITH_HEADLESS
+ return NULL;
+#else
+ const int ALERT_IMG_SIZE = 256;
+ icon = MIN2(icon, ALERT_ICON_MAX - 1);
+ const int left = icon * ALERT_IMG_SIZE;
+ const rcti crop = {left, left + ALERT_IMG_SIZE - 1, 0, ALERT_IMG_SIZE - 1};
+ ImBuf *ibuf = IMB_ibImageFromMemory((const uchar *)datatoc_alert_icons_png,
+ datatoc_alert_icons_png_size,
+ IB_rect,
+ NULL,
+ "alert_icon");
+ IMB_rect_crop(ibuf, &crop);
+ IMB_premultiply_alpha(ibuf);
+ return ibuf;
+#endif
+}
diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c
index 3cc7aaddf38..fed29571185 100644
--- a/source/blender/editors/interface/interface_icons_event.c
+++ b/source/blender/editors/interface/interface_icons_event.c
@@ -34,8 +34,8 @@
#include "GPU_state.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
@@ -48,8 +48,8 @@
#include "RNA_access.h"
#include "RNA_enum_types.h"
-#include "BKE_icons.h"
#include "BKE_appdir.h"
+#include "BKE_icons.h"
#include "BKE_studiolight.h"
#include "IMB_imbuf.h"
@@ -74,8 +74,10 @@
#include "interface_intern.h"
-static void icon_draw_rect_input_text(
- const rctf *rect, const float color[4], const char *str, int font_size)
+static void icon_draw_rect_input_text(const rctf *rect,
+ const float color[4],
+ const char *str,
+ int font_size)
{
BLF_batch_draw_flush();
const int font_id = BLF_default();
@@ -140,19 +142,19 @@ void icon_draw_rect_input(float x,
.ymax = y + h,
};
- if ((event_type >= AKEY) && (event_type <= ZKEY)) {
- char str[2] = {'A' + (event_type - AKEY), '\0'};
+ if ((event_type >= EVT_AKEY) && (event_type <= EVT_ZKEY)) {
+ char str[2] = {'A' + (event_type - EVT_AKEY), '\0'};
icon_draw_rect_input_text(&rect, color, str, 13);
}
- else if ((event_type >= F1KEY) && (event_type <= F12KEY)) {
+ else if ((event_type >= EVT_F1KEY) && (event_type <= EVT_F12KEY)) {
char str[4];
- SNPRINTF(str, "F%d", 1 + (event_type - F1KEY));
- icon_draw_rect_input_text(&rect, color, str, event_type > F9KEY ? 8 : 10);
+ SNPRINTF(str, "F%d", 1 + (event_type - EVT_F1KEY));
+ icon_draw_rect_input_text(&rect, color, str, event_type > EVT_F9KEY ? 8 : 10);
}
- else if (event_type == LEFTSHIFTKEY) {
+ else if (event_type == EVT_LEFTSHIFTKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x87, 0xa7, 0x0});
}
- else if (event_type == LEFTCTRLKEY) {
+ else if (event_type == EVT_LEFTCTRLKEY) {
if (platform == MACOS) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8c, 0x83, 0x0});
}
@@ -160,7 +162,7 @@ void icon_draw_rect_input(float x,
icon_draw_rect_input_text(&rect, color, "Ctrl", 9);
}
}
- else if (event_type == LEFTALTKEY) {
+ else if (event_type == EVT_LEFTALTKEY) {
if (platform == MACOS) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8c, 0xa5, 0x0});
}
@@ -168,7 +170,7 @@ void icon_draw_rect_input(float x,
icon_draw_rect_input_text(&rect, color, "Alt", 10);
}
}
- else if (event_type == OSKEY) {
+ else if (event_type == EVT_OSKEY) {
if (platform == MACOS) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8c, 0x98, 0x0});
}
@@ -179,22 +181,22 @@ void icon_draw_rect_input(float x,
icon_draw_rect_input_text(&rect, color, "OS", 10);
}
}
- else if (event_type == DELKEY) {
+ else if (event_type == EVT_DELKEY) {
icon_draw_rect_input_text(&rect, color, "Del", 9);
}
- else if (event_type == TABKEY) {
+ else if (event_type == EVT_TABKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0xad, 0xbe, 0x0});
}
- else if (event_type == HOMEKEY) {
+ else if (event_type == EVT_HOMEKEY) {
icon_draw_rect_input_text(&rect, color, "Home", 6);
}
- else if (event_type == ENDKEY) {
+ else if (event_type == EVT_ENDKEY) {
icon_draw_rect_input_text(&rect, color, "End", 8);
}
- else if (event_type == RETKEY) {
+ else if (event_type == EVT_RETKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8f, 0x8e, 0x0});
}
- else if (event_type == ESCKEY) {
+ else if (event_type == EVT_ESCKEY) {
if (platform == MACOS) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x8e, 0x8b, 0x0});
}
@@ -202,26 +204,25 @@ void icon_draw_rect_input(float x,
icon_draw_rect_input_text(&rect, color, "Esc", 8);
}
}
- else if (event_type == PAGEUPKEY) {
+ else if (event_type == EVT_PAGEUPKEY) {
icon_draw_rect_input_text(&rect, color, (const char[]){'P', 0xe2, 0x86, 0x91, 0x0}, 8);
}
- else if (event_type == PAGEDOWNKEY) {
- icon_draw_rect_input_text(
- &rect, color, (const char[]){'P', 0xe2, 0x86, 0x93, 0x0}, 8);
+ else if (event_type == EVT_PAGEDOWNKEY) {
+ icon_draw_rect_input_text(&rect, color, (const char[]){'P', 0xe2, 0x86, 0x93, 0x0}, 8);
}
- else if (event_type == LEFTARROWKEY) {
+ else if (event_type == EVT_LEFTARROWKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x86, 0x90, 0x0});
}
- else if (event_type == UPARROWKEY) {
+ else if (event_type == EVT_UPARROWKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x86, 0x91, 0x0});
}
- else if (event_type == RIGHTARROWKEY) {
+ else if (event_type == EVT_RIGHTARROWKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x86, 0x92, 0x0});
}
- else if (event_type == DOWNARROWKEY) {
+ else if (event_type == EVT_DOWNARROWKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x86, 0x93, 0x0});
}
- else if (event_type == SPACEKEY) {
+ else if (event_type == EVT_SPACEKEY) {
icon_draw_rect_input_symbol(&rect, color, (const char[]){0xe2, 0x90, 0xa3, 0x0});
}
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 3fe2750e070..3748dbab519 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -25,9 +25,12 @@
#define __INTERFACE_INTERN_H__
#include "BLI_compiler_attrs.h"
-#include "UI_resources.h"
-#include "RNA_types.h"
+#include "BLI_rect.h"
+
#include "DNA_listBase.h"
+#include "RNA_types.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
struct ARegion;
struct ID;
@@ -38,6 +41,7 @@ struct bContextStore;
struct uiHandleButtonData;
struct uiLayout;
struct uiStyle;
+struct uiUndoStack_Text;
struct uiWidgetColors;
struct wmEvent;
struct wmKeyConfig;
@@ -144,6 +148,17 @@ enum {
/* max amount of items a radial menu (pie menu) can contain */
#define PIE_MAX_ITEMS 8
+struct uiButSearchData {
+ uiButSearchCreateFn create_fn;
+ uiButSearchUpdateFn update_fn;
+ void *arg;
+ uiButSearchArgFreeFn arg_free_fn;
+ uiButSearchContextMenuFn context_menu_fn;
+ uiButSearchTooltipFn tooltip_fn;
+
+ const char *sep_string;
+};
+
struct uiBut {
struct uiBut *next, *prev;
int flag, drawflag;
@@ -200,10 +215,7 @@ struct uiBut {
uiButCompleteFunc autocomplete_func;
void *autofunc_arg;
- uiButSearchCreateFunc search_create_func;
- uiButSearchFunc search_func;
- bool free_search_arg;
- void *search_arg;
+ struct uiButSearchData *search;
uiButHandleRenameFunc rename_func;
void *rename_arg1;
@@ -343,7 +355,7 @@ struct uiBlock {
uiBlock *next, *prev;
ListBase buttons;
- Panel *panel;
+ struct Panel *panel;
uiBlock *oldblock;
ListBase butstore; /* UI_butstore_* runtime function */
@@ -456,23 +468,31 @@ typedef struct uiSafetyRct {
void ui_fontscale(short *points, float aspect);
-extern void ui_block_to_window_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
-extern void ui_block_to_window(const struct ARegion *ar, uiBlock *block, int *x, int *y);
-extern void ui_block_to_window_rctf(const struct ARegion *ar,
+extern void ui_block_to_window_fl(const struct ARegion *region,
+ uiBlock *block,
+ float *x,
+ float *y);
+extern void ui_block_to_window(const struct ARegion *region, uiBlock *block, int *x, int *y);
+extern void ui_block_to_window_rctf(const struct ARegion *region,
uiBlock *block,
rctf *rct_dst,
const rctf *rct_src);
-extern float ui_block_to_window_scale(const struct ARegion *ar, uiBlock *block);
-extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
-extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y);
-extern void ui_window_to_block_rctf(const struct ARegion *ar,
+extern float ui_block_to_window_scale(const struct ARegion *region, uiBlock *block);
+extern void ui_window_to_block_fl(const struct ARegion *region,
+ uiBlock *block,
+ float *x,
+ float *y);
+extern void ui_window_to_block(const struct ARegion *region, uiBlock *block, int *x, int *y);
+extern void ui_window_to_block_rctf(const struct ARegion *region,
uiBlock *block,
rctf *rct_dst,
const rctf *rct_src);
-extern void ui_window_to_region(const ARegion *ar, int *x, int *y);
-extern void ui_window_to_region_rcti(const ARegion *ar, rcti *rect_dst, const rcti *rct_src);
-extern void ui_region_to_window(const struct ARegion *ar, int *x, int *y);
-extern void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rect);
+extern void ui_window_to_region(const struct ARegion *region, int *x, int *y);
+extern void ui_window_to_region_rcti(const struct ARegion *region,
+ rcti *rect_dst,
+ const rcti *rct_src);
+extern void ui_region_to_window(const struct ARegion *region, int *x, int *y);
+extern void ui_region_winrct_get_no_margin(const struct ARegion *region, struct rcti *r_rect);
extern double ui_but_value_get(uiBut *but);
extern void ui_but_value_set(uiBut *but, double value);
@@ -558,7 +578,7 @@ struct uiPopupBlockCreate {
int event_xy[2];
/* when popup is initialized from a button */
- ARegion *butregion;
+ struct ARegion *butregion;
uiBut *but;
};
@@ -589,10 +609,8 @@ struct uiPopupBlockHandle {
/* for operator popups */
struct wmOperator *popup_op;
- struct wmOperatorType *optype;
- ScrArea *ctx_area;
- ARegion *ctx_region;
- int opcontext;
+ struct ScrArea *ctx_area;
+ struct ARegion *ctx_region;
/* return values */
int butretval;
@@ -640,18 +658,27 @@ ColorPicker *ui_block_colorpicker_create(struct uiBlock *block);
/* interface_region_search.c */
/* Searchbox for string button */
-ARegion *ui_searchbox_create_generic(struct bContext *C, struct ARegion *butregion, uiBut *but);
-ARegion *ui_searchbox_create_operator(struct bContext *C, struct ARegion *butregion, uiBut *but);
-bool ui_searchbox_inside(struct ARegion *ar, int x, int y);
-int ui_searchbox_find_index(struct ARegion *ar, const char *name);
-void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, const bool reset);
-int ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str);
-void ui_searchbox_event(struct bContext *C,
- struct ARegion *ar,
+struct ARegion *ui_searchbox_create_generic(struct bContext *C,
+ struct ARegion *butregion,
+ uiBut *but);
+struct ARegion *ui_searchbox_create_operator(struct bContext *C,
+ struct ARegion *butregion,
+ uiBut *but);
+struct ARegion *ui_searchbox_create_menu(struct bContext *C,
+ struct ARegion *butregion,
+ uiBut *but);
+
+bool ui_searchbox_inside(struct ARegion *region, int x, int y);
+int ui_searchbox_find_index(struct ARegion *region, const char *name);
+void ui_searchbox_update(struct bContext *C, struct ARegion *region, uiBut *but, const bool reset);
+int ui_searchbox_autocomplete(struct bContext *C, struct ARegion *region, uiBut *but, char *str);
+bool ui_searchbox_event(struct bContext *C,
+ struct ARegion *region,
uiBut *but,
+ struct ARegion *butregion,
const struct wmEvent *event);
-bool ui_searchbox_apply(uiBut *but, struct ARegion *ar);
-void ui_searchbox_free(struct bContext *C, struct ARegion *ar);
+bool ui_searchbox_apply(uiBut *but, struct ARegion *region);
+void ui_searchbox_free(struct bContext *C, struct ARegion *region);
void ui_but_search_refresh(uiBut *but);
/* interface_region_menu_popup.c */
@@ -662,7 +689,7 @@ void ui_popup_menu_memory_set(uiBlock *block, struct uiBut *but);
uiBlock *ui_popup_block_refresh(struct bContext *C,
uiPopupBlockHandle *handle,
- ARegion *butregion,
+ struct ARegion *butregion,
uiBut *but);
uiPopupBlockHandle *ui_popup_block_create(struct bContext *C,
@@ -689,14 +716,14 @@ uiPopupBlockHandle *ui_popover_panel_create(struct bContext *C,
void ui_pie_menu_level_create(uiBlock *block,
struct wmOperatorType *ot,
const char *propname,
- IDProperty *properties,
+ struct IDProperty *properties,
const EnumPropertyItem *items,
int totitem,
int context,
int flag);
/* interface_region_popup.c */
-void ui_popup_translate(struct ARegion *ar, const int mdiff[2]);
+void ui_popup_translate(struct ARegion *region, const int mdiff[2]);
void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
void ui_popup_block_scrolltest(struct uiBlock *block);
@@ -705,7 +732,7 @@ void ui_popup_block_scrolltest(struct uiBlock *block);
/* interface_panel.c */
extern int ui_handler_panel_region(struct bContext *C,
const struct wmEvent *event,
- struct ARegion *ar,
+ struct ARegion *region,
const uiBut *active_but);
extern void ui_draw_aligned_panel(struct uiStyle *style,
uiBlock *block,
@@ -723,50 +750,60 @@ void ui_draw_but_TAB_outline(const rcti *rect,
float rad,
uchar highlight[3],
uchar highlight_fade[3]);
-void ui_draw_but_HISTOGRAM(ARegion *ar,
+void ui_draw_but_HISTOGRAM(struct ARegion *region,
uiBut *but,
const struct uiWidgetColors *wcol,
const rcti *rect);
-void ui_draw_but_WAVEFORM(ARegion *ar,
+void ui_draw_but_WAVEFORM(struct ARegion *region,
uiBut *but,
const struct uiWidgetColors *wcol,
const rcti *rect);
-void ui_draw_but_VECTORSCOPE(ARegion *ar,
+void ui_draw_but_VECTORSCOPE(struct ARegion *region,
uiBut *but,
const struct uiWidgetColors *wcol,
const rcti *rect);
void ui_draw_but_COLORBAND(uiBut *but, const struct uiWidgetColors *wcol, const rcti *rect);
void ui_draw_but_UNITVEC(uiBut *but, const struct uiWidgetColors *wcol, const rcti *rect);
-void ui_draw_but_CURVE(ARegion *ar,
+void ui_draw_but_CURVE(struct ARegion *region,
uiBut *but,
const struct uiWidgetColors *wcol,
const rcti *rect);
-void ui_draw_but_CURVEPROFILE(ARegion *ar,
+void ui_draw_but_CURVEPROFILE(struct ARegion *region,
uiBut *but,
const struct uiWidgetColors *wcol,
const rcti *rect);
-void ui_draw_but_IMAGE(ARegion *ar,
+void ui_draw_but_IMAGE(struct ARegion *region,
uiBut *but,
const struct uiWidgetColors *wcol,
const rcti *rect);
-void ui_draw_but_TRACKPREVIEW(ARegion *ar,
+void ui_draw_but_TRACKPREVIEW(struct ARegion *region,
uiBut *but,
const struct uiWidgetColors *wcol,
const rcti *rect);
+/* interface_undo.c */
+struct uiUndoStack_Text *ui_textedit_undo_stack_create(void);
+void ui_textedit_undo_stack_destroy(struct uiUndoStack_Text *undo_stack);
+void ui_textedit_undo_push(struct uiUndoStack_Text *undo_stack,
+ const char *text,
+ int cursor_index);
+const char *ui_textedit_undo(struct uiUndoStack_Text *undo_stack,
+ int direction,
+ int *r_cursor_index);
+
/* interface_handlers.c */
PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot,
int opcontext,
bool create_props);
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
-extern void ui_but_activate_event(struct bContext *C, struct ARegion *ar, uiBut *but);
-extern void ui_but_activate_over(struct bContext *C, struct ARegion *ar, uiBut *but);
+extern void ui_but_activate_event(struct bContext *C, struct ARegion *region, uiBut *but);
+extern void ui_but_activate_over(struct bContext *C, struct ARegion *region, uiBut *but);
extern void ui_but_execute_begin(struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
uiBut *but,
void **active_back);
extern void ui_but_execute_end(struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
uiBut *but,
void *active_back);
extern void ui_but_active_free(const struct bContext *C, uiBut *but);
@@ -780,6 +817,11 @@ float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]);
void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip);
void ui_but_clipboard_free(void);
+bool ui_but_rna_equals(const uiBut *a, const uiBut *b);
+bool ui_but_rna_equals_ex(const uiBut *but,
+ const PointerRNA *ptr,
+ const PropertyRNA *prop,
+ int index);
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
@@ -826,23 +868,30 @@ struct GPUBatch *ui_batch_roundbox_shadow_get(void);
void ui_draw_anti_tria_rect(const rctf *rect, char dir, const float color[4]);
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
-void ui_draw_popover_back(ARegion *ar, struct uiStyle *style, uiBlock *block, rcti *rect);
+void ui_draw_popover_back(struct ARegion *region,
+ struct uiStyle *style,
+ uiBlock *block,
+ rcti *rect);
void ui_draw_pie_center(uiBlock *block);
const struct uiWidgetColors *ui_tooltip_get_theme(void);
void ui_draw_widget_menu_back_color(const rcti *rect, bool use_shadow, const float color[4]);
void ui_draw_widget_menu_back(const rcti *rect, bool use_shadow);
-void ui_draw_tooltip_background(struct uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
+void ui_draw_tooltip_background(const struct uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
-extern void ui_draw_but(
- const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
+extern void ui_draw_but(const struct bContext *C,
+ struct ARegion *region,
+ struct uiStyle *style,
+ uiBut *but,
+ rcti *rect);
void ui_draw_menu_item(const struct uiFontStyle *fstyle,
rcti *rect,
const char *name,
int iconid,
int state,
- bool use_sep);
+ bool use_sep,
+ int *r_xmax);
void ui_draw_preview_item(
const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
@@ -884,8 +933,8 @@ void ui_item_paneltype_func(struct bContext *C, struct uiLayout *layout, void *a
/* interface_align.c */
bool ui_but_can_align(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
-int ui_but_align_opposite_to_area_align_get(const ARegion *ar) ATTR_WARN_UNUSED_RESULT;
-void ui_block_align_calc(uiBlock *block, const ARegion *region);
+int ui_but_align_opposite_to_area_align_get(const struct ARegion *region) ATTR_WARN_UNUSED_RESULT;
+void ui_block_align_calc(uiBlock *block, const struct ARegion *region);
/* interface_anim.c */
void ui_but_anim_flag(uiBut *but, float cfra);
@@ -906,6 +955,7 @@ bool ui_but_is_toggle(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
bool ui_but_is_interactive(const uiBut *but, const bool labeledit) ATTR_WARN_UNUSED_RESULT;
bool ui_but_is_popover_once_compat(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
bool ui_but_has_array_value(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
+int ui_but_icon(const uiBut *but);
void ui_but_pie_dir(RadialDirection dir, float vec[2]);
bool ui_but_is_cursor_warp(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
@@ -913,24 +963,24 @@ bool ui_but_is_cursor_warp(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
bool ui_but_contains_pt(const uiBut *but, float mx, float my) ATTR_WARN_UNUSED_RESULT;
bool ui_but_contains_rect(const uiBut *but, const rctf *rect);
bool ui_but_contains_point_px_icon(const uiBut *but,
- struct ARegion *ar,
+ struct ARegion *region,
const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
-bool ui_but_contains_point_px(const uiBut *but, const struct ARegion *ar, int x, int y)
+bool ui_but_contains_point_px(const uiBut *but, const struct ARegion *region, int x, int y)
ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_list_find_mouse_over(struct ARegion *ar,
+uiBut *ui_list_find_mouse_over(struct ARegion *region,
const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_but_find_mouse_over_ex(struct ARegion *ar,
+uiBut *ui_but_find_mouse_over_ex(struct ARegion *region,
const int x,
const int y,
const bool labeledit) ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_but_find_mouse_over(struct ARegion *ar,
+uiBut *ui_but_find_mouse_over(struct ARegion *region,
const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_but_find_rect_over(const struct ARegion *ar,
+uiBut *ui_but_find_rect_over(const struct ARegion *region,
const rcti *rect_px) ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_list_find_mouse_over_ex(struct ARegion *ar, int x, int y) ATTR_WARN_UNUSED_RESULT;
+uiBut *ui_list_find_mouse_over_ex(struct ARegion *region, int x, int y) ATTR_WARN_UNUSED_RESULT;
bool ui_but_contains_password(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
@@ -944,17 +994,32 @@ bool ui_block_is_popover(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
bool ui_block_is_popup_any(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_region_find_first_but_test_flag(struct ARegion *ar, int flag_include, int flag_exclude);
-uiBut *ui_region_find_active_but(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
-bool ui_region_contains_point_px(const struct ARegion *ar, int x, int y) ATTR_WARN_UNUSED_RESULT;
-bool ui_region_contains_rect_px(const struct ARegion *ar, const rcti *rect_px);
-
-ARegion *ui_screen_region_find_mouse_over_ex(bScreen *screen, int x, int y);
-ARegion *ui_screen_region_find_mouse_over(bScreen *screen, const struct wmEvent *event);
+uiBlock *ui_block_find_mouse_over_ex(const struct ARegion *region,
+ const int x,
+ const int y,
+ bool only_clip);
+uiBlock *ui_block_find_mouse_over(const struct ARegion *region,
+ const struct wmEvent *event,
+ bool only_clip);
+
+uiBut *ui_region_find_first_but_test_flag(struct ARegion *region,
+ int flag_include,
+ int flag_exclude);
+uiBut *ui_region_find_active_but(struct ARegion *region) ATTR_WARN_UNUSED_RESULT;
+bool ui_region_contains_point_px(const struct ARegion *region,
+ int x,
+ int y) ATTR_WARN_UNUSED_RESULT;
+bool ui_region_contains_rect_px(const struct ARegion *region, const rcti *rect_px);
+
+struct ARegion *ui_screen_region_find_mouse_over_ex(struct bScreen *screen, int x, int y);
+struct ARegion *ui_screen_region_find_mouse_over(struct bScreen *screen,
+ const struct wmEvent *event);
/* interface_context_menu.c */
bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but);
-void ui_popup_context_menu_for_panel(struct bContext *C, struct ARegion *ar, struct Panel *pa);
+void ui_popup_context_menu_for_panel(struct bContext *C,
+ struct ARegion *region,
+ struct Panel *panel);
/* interface_eyedropper.c */
struct wmKeyMap *eyedropper_modal_keymap(struct wmKeyConfig *keyconf);
@@ -980,9 +1045,10 @@ void UI_OT_eyedropper_driver(struct wmOperatorType *ot);
void UI_OT_eyedropper_gpencil_color(struct wmOperatorType *ot);
/* interface_util.c */
+bool ui_str_has_word_prefix(const char *haystack, const char *needle, size_t needle_len);
/**
- * For use with #ui_rna_collection_search_cb.
+ * For use with #ui_rna_collection_search_update_fn.
*/
typedef struct uiRNACollectionSearch {
PointerRNA target_ptr;
@@ -991,12 +1057,16 @@ typedef struct uiRNACollectionSearch {
PointerRNA search_ptr;
PropertyRNA *search_prop;
- bool *but_changed; /* pointer to uiBut.changed */
+ uiBut *search_but;
+ /* Let UI_butstore_ API update search_but pointer above over redraws. */
+ uiButStore *butstore;
+ /* Block has to be stored for freeing butstore (uiBut.block doesn't work with undo). */
+ uiBlock *butstore_block;
} uiRNACollectionSearch;
-void ui_rna_collection_search_cb(const struct bContext *C,
- void *arg,
- const char *str,
- uiSearchItems *items);
+void ui_rna_collection_search_update_fn(const struct bContext *C,
+ void *arg,
+ const char *str,
+ uiSearchItems *items);
/* interface_ops.c */
bool ui_jump_to_target_button_poll(struct bContext *C);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 64c0e11976b..884e43b4026 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -18,32 +18,32 @@
* \ingroup edinterface
*/
+#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
-#include "DNA_screen_types.h"
#include "DNA_armature_types.h"
+#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "BLI_alloca.h"
#include "BLI_listbase.h"
-#include "BLI_string.h"
+#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLI_math.h"
#include "BLT_translation.h"
+#include "BKE_anim_data.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_screen.h"
-#include "BKE_animsys.h"
#include "RNA_access.h"
@@ -75,7 +75,7 @@
} \
(void)0
-#define UI_ITEM_PROP_SEP_DIVIDE 0.5f
+#define UI_ITEM_PROP_SEP_DIVIDE 0.4f
/* uiLayoutRoot */
@@ -91,7 +91,7 @@ typedef struct uiLayoutRoot {
uiMenuHandleFunc handlefunc;
void *argv;
- uiStyle *style;
+ const uiStyle *style;
uiBlock *block;
uiLayout *layout;
} uiLayoutRoot;
@@ -135,10 +135,11 @@ enum {
UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
UI_ITEM_PROP_SEP = 1 << 3,
+ UI_ITEM_INSIDE_PROP_SEP = 1 << 4,
/* Show an icon button next to each property (to set keyframes, show status).
* Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */
- UI_ITEM_PROP_DECORATE = 1 << 4,
- UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 5,
+ UI_ITEM_PROP_DECORATE = 1 << 5,
+ UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 6,
};
typedef struct uiButtonItem {
@@ -151,8 +152,11 @@ struct uiLayout {
uiLayoutRoot *root;
bContextStore *context;
+ uiLayout *parent;
ListBase items;
+ char heading[UI_MAX_NAME_STR];
+
/** Sub layout to add child items, if not the layout itself. */
uiLayout *child_items_layout;
@@ -499,7 +503,7 @@ static void ui_item_array(uiLayout *layout,
bool compact,
bool show_text)
{
- uiStyle *style = layout->root->style;
+ const uiStyle *style = layout->root->style;
uiBut *but;
PropertyType type;
PropertySubType subtype;
@@ -534,7 +538,7 @@ static void ui_item_array(uiLayout *layout,
buth = unit;
if (ptr->type == &RNA_Armature) {
- bArmature *arm = (bArmature *)ptr->data;
+ bArmature *arm = ptr->data;
layer_used = arm->layer_used;
@@ -945,19 +949,25 @@ static uiBut *ui_item_with_label(uiLayout *layout,
PropertyType type;
PropertySubType subtype;
int prop_but_width = w_hint;
+#ifdef UI_PROP_DECORATE
+ uiLayout *layout_prop_decorate = NULL;
const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
+#endif
/* Always align item with label since text is already given enough space not to overlap. */
sub = uiLayoutRow(layout, true);
UI_block_layout_set_current(block, sub);
+#ifdef UI_PROP_DECORATE
if (name[0]) {
- int w_label;
-
if (use_prop_sep) {
- w_label = (int)((w_hint * 2) * UI_ITEM_PROP_SEP_DIVIDE);
+ layout_prop_decorate = uiItemL_respect_property_split(layout, name, 0);
}
- else {
+ else
+#endif
+ {
+ int w_label;
+
if (ui_layout_variable_size(layout)) {
/* w_hint is width for label in this case.
* Use a default width for property button(s) */
@@ -967,13 +977,7 @@ static uiBut *ui_item_with_label(uiLayout *layout,
else {
w_label = w_hint / 3;
}
- }
-
- uiBut *but_label = uiDefBut(
- block, UI_BTYPE_LABEL, 0, name, x, y, w_label, h, NULL, 0.0, 0.0, 0, 0, "");
- if (use_prop_sep) {
- but_label->drawflag |= UI_BUT_TEXT_RIGHT;
- but_label->drawflag &= ~UI_BUT_TEXT_LEFT;
+ uiDefBut(block, UI_BTYPE_LABEL, 0, name, x, y, w_label, h, NULL, 0.0, 0.0, 0, 0, "");
}
}
@@ -1053,7 +1057,7 @@ static uiBut *ui_item_with_label(uiLayout *layout,
if (layout->item.flag & UI_ITEM_PROP_SEP) {
if ((layout->item.flag & UI_ITEM_PROP_DECORATE) &&
(layout->item.flag & UI_ITEM_PROP_DECORATE_NO_PAD) == 0) {
- uiItemL(sub, NULL, ICON_BLANK1);
+ uiItemL(layout_prop_decorate ? layout_prop_decorate : sub, NULL, ICON_BLANK1);
}
}
#endif /* UI_PROP_DECORATE */
@@ -1067,7 +1071,7 @@ void UI_context_active_but_prop_get_filebrowser(const bContext *C,
PropertyRNA **r_prop,
bool *r_is_undo)
{
- ARegion *ar = CTX_wm_menu(C) ? CTX_wm_menu(C) : CTX_wm_region(C);
+ ARegion *region = CTX_wm_menu(C) ? CTX_wm_menu(C) : CTX_wm_region(C);
uiBlock *block;
uiBut *but, *prevbut = NULL;
@@ -1075,11 +1079,11 @@ void UI_context_active_but_prop_get_filebrowser(const bContext *C,
*r_prop = NULL;
*r_is_undo = false;
- if (!ar) {
+ if (!region) {
return;
}
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
if (but && but->rnapoin.data) {
if (RNA_property_type(but->rnaprop) == PROP_STRING) {
@@ -1780,6 +1784,7 @@ static void ui_item_rna_size(uiLayout *layout,
PropertyType type;
PropertySubType subtype;
int len, w = 0, h;
+ bool is_checkbox_only = false;
/* arbitrary extended width by type */
type = RNA_property_type(prop);
@@ -1791,6 +1796,10 @@ static void ui_item_rna_size(uiLayout *layout,
name = "non-empty text";
}
else if (type == PROP_BOOLEAN) {
+ if (icon == ICON_NONE) {
+ /* Exception for checkboxes, they need a little less space to align nicely. */
+ is_checkbox_only = true;
+ }
icon = ICON_DOT;
}
else if (type == PROP_ENUM) {
@@ -1850,6 +1859,9 @@ static void ui_item_rna_size(uiLayout *layout,
if (type == PROP_BOOLEAN && name[0]) {
w += UI_UNIT_X / 5;
}
+ else if (is_checkbox_only) {
+ w -= UI_UNIT_X / 4;
+ }
else if (type == PROP_ENUM && !icon_only) {
w += UI_UNIT_X / 4;
}
@@ -1862,6 +1874,78 @@ static void ui_item_rna_size(uiLayout *layout,
*r_h = h;
}
+static bool ui_item_rna_is_expand(PropertyRNA *prop, int index, int item_flag)
+{
+ const bool is_array = RNA_property_array_check(prop);
+ const int subtype = RNA_property_subtype(prop);
+ return is_array && (index == RNA_NO_INDEX) &&
+ ((item_flag & UI_ITEM_R_EXPAND) ||
+ !ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION));
+}
+
+/**
+ * Find first layout ancestor (or self) with a heading set.
+ *
+ * \returns the layout to add the heading to as fallback (i.e. if it can't be placed in a split
+ * layout). Its #uiLayout.heading member can be cleared to mark the heading as added (so
+ * it's not added multiple times). Returns a pointer to the heading
+ */
+static uiLayout *ui_layout_heading_find(uiLayout *cur_layout)
+{
+ for (uiLayout *parent = cur_layout; parent; parent = parent->parent) {
+ if (parent->heading[0]) {
+ return parent;
+ }
+ }
+
+ return NULL;
+}
+
+static void ui_layout_heading_label_add(uiLayout *layout,
+ uiLayout *heading_layout,
+ bool right_align,
+ bool respect_prop_split)
+{
+ const int prev_alignment = layout->alignment;
+
+ if (right_align) {
+ uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_RIGHT);
+ }
+
+ if (respect_prop_split) {
+ uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE);
+ }
+ else {
+ uiItemL(layout, heading_layout->heading, ICON_NONE);
+ }
+ /* After adding the heading label, we have to mark it somehow as added, so it's not added again
+ * for other items in this layout. For now just clear it. */
+ heading_layout->heading[0] = '\0';
+
+ layout->alignment = prev_alignment;
+}
+
+/**
+ * Hack to add further items in a row into the second part of the split layout, so the label part
+ * keeps a fixed size.
+ * \return The layout to place further items in for the split layout.
+ */
+static uiLayout *ui_item_prop_split_layout_hack(uiLayout *layout_parent, uiLayout *layout_split)
+{
+ /* Tag item as using property split layout, this is inherited to children so they can get special
+ * treatment if needed. */
+ layout_parent->item.flag |= UI_ITEM_INSIDE_PROP_SEP;
+
+ if (layout_parent->item.type == ITEM_LAYOUT_ROW) {
+ /* Prevent further splits within the row. */
+ uiLayoutSetPropSep(layout_parent, false);
+
+ layout_parent->child_items_layout = uiLayoutRow(layout_split, true);
+ return layout_parent->child_items_layout;
+ }
+ return layout_split;
+}
+
void uiItemFullR(uiLayout *layout,
PointerRNA *ptr,
PropertyRNA *prop,
@@ -1874,13 +1958,18 @@ void uiItemFullR(uiLayout *layout,
uiBlock *block = layout->root->block;
char namestr[UI_MAX_NAME_STR];
const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
-
- /* By default 'use_prop_sep' uses a separate column for labels.
- * This is an exception for check-boxes otherwise only the small checkbox region is clickable.
+ const bool inside_prop_sep = ((layout->item.flag & UI_ITEM_INSIDE_PROP_SEP) != 0);
+ /* Columns can define a heading to insert. If the first item added to a split layout doesn't have
+ * a label to display in the first column, the heading is inserted there. Otherwise it's inserted
+ * as a new row before the first item. */
+ uiLayout *heading_layout = ui_layout_heading_find(layout);
+ /* Although checkboxes use the split layout, they are an exception and should only place their
+ * label in the second column, to not make that almost empty.
*
* Keep using 'use_prop_sep' instead of disabling it entirely because
* we need the ability to have decorators still. */
bool use_prop_sep_split_label = use_prop_sep;
+ bool use_split_empty_name = (flag & UI_ITEM_R_SPLIT_EMPTY_NAME);
#ifdef UI_PROP_DECORATE
struct {
@@ -1991,6 +2080,9 @@ void uiItemFullR(uiLayout *layout,
if (use_prop_sep) {
if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
use_prop_sep_split_label = false;
+ /* For check-boxes we make an exception: We allow showing them in a split row even without
+ * label. It typically relates to its neighbor items, so no need for an extra label. */
+ use_split_empty_name = true;
}
}
#endif
@@ -2017,6 +2109,7 @@ void uiItemFullR(uiLayout *layout,
/* Split the label / property. */
uiLayout *layout_parent = layout;
+
if (use_prop_sep) {
uiLayout *layout_row = NULL;
#ifdef UI_PROP_DECORATE
@@ -2027,21 +2120,26 @@ void uiItemFullR(uiLayout *layout,
}
#endif /* UI_PROP_DECORATE */
- if ((name[0] == '\0') || (use_prop_sep_split_label == false)) {
+ if ((name[0] == '\0') && !use_split_empty_name) {
/* Ensure we get a column when text is not set. */
layout = uiLayoutColumn(layout_row ? layout_row : layout, true);
layout->space = 0;
+ if (heading_layout) {
+ ui_layout_heading_label_add(layout, heading_layout, false, false);
+ }
}
else {
- const PropertySubType subtype = RNA_property_subtype(prop);
uiLayout *layout_split = uiLayoutSplit(
layout_row ? layout_row : layout, UI_ITEM_PROP_SEP_DIVIDE, true);
+ bool label_added = false;
layout_split->space = 0;
uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
layout_sub->space = 0;
- if ((index == RNA_NO_INDEX && is_array) &&
- ((!expand && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)) == 0)) {
+ if (!use_prop_sep_split_label) {
+ /* Pass */
+ }
+ else if (ui_item_rna_is_expand(prop, index, flag)) {
char name_with_suffix[UI_MAX_DRAW_STR + 2];
char str[2] = {'\0'};
for (int a = 0; a < len; a++) {
@@ -2070,6 +2168,8 @@ void uiItemFullR(uiLayout *layout,
"");
but->drawflag |= UI_BUT_TEXT_RIGHT;
but->drawflag &= ~UI_BUT_TEXT_LEFT;
+
+ label_added = true;
}
}
else {
@@ -2078,16 +2178,17 @@ void uiItemFullR(uiLayout *layout,
block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
but->drawflag |= UI_BUT_TEXT_RIGHT;
but->drawflag &= ~UI_BUT_TEXT_LEFT;
+
+ label_added = true;
}
}
- /* Hack to add further items in a row into the second part of
- * the split layout, so the label part keeps a fixed size. */
- if (layout_parent && layout_parent->item.type == ITEM_LAYOUT_ROW) {
- layout_split = uiLayoutRow(layout_split, true);
- layout_parent->child_items_layout = layout_split;
+ if (!label_added && heading_layout) {
+ ui_layout_heading_label_add(layout_sub, heading_layout, true, false);
}
+ layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split);
+
/* Watch out! We can only write into the new layout now. */
if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) {
/* Expanded enums each have their own name. */
@@ -2102,7 +2203,9 @@ void uiItemFullR(uiLayout *layout,
}
}
else {
- name = "";
+ if (use_prop_sep_split_label) {
+ name = "";
+ }
layout = uiLayoutColumn(layout_split, true);
}
layout->space = 0;
@@ -2121,9 +2224,20 @@ void uiItemFullR(uiLayout *layout,
#endif /* UI_PROP_DECORATE */
}
/* End split. */
+ else if (heading_layout) {
+ /* Could not add heading to split layout, fallback to inserting it to the layout with the
+ * heading itself. */
+ ui_layout_heading_label_add(heading_layout, heading_layout, false, false);
+ }
/* array property */
if (index == RNA_NO_INDEX && is_array) {
+ if (inside_prop_sep) {
+ /* Within a split row, add array items to a column so they match the column layout of
+ * previous items (e.g. transform vector with lock icon for each item). */
+ layout = uiLayoutColumn(layout, true);
+ }
+
ui_item_array(layout,
block,
name,
@@ -2183,7 +2297,11 @@ void uiItemFullR(uiLayout *layout,
}
if (flag & UI_ITEM_R_CHECKBOX_INVERT) {
- if (ELEM(but->type, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N)) {
+ if (ELEM(but->type,
+ UI_BTYPE_CHECKBOX,
+ UI_BTYPE_CHECKBOX_N,
+ UI_BTYPE_ICON_TOGGLE,
+ UI_BTYPE_ICON_TOGGLE_N)) {
but->drawflag |= UI_BUT_CHECKBOX_INVERT;
}
}
@@ -2199,12 +2317,6 @@ void uiItemFullR(uiLayout *layout,
if (layout->activate_init) {
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
}
-
- if (use_prop_sep && (use_prop_sep_split_label == false)) {
- /* When the button uses it's own text right align it. */
- but->drawflag |= UI_BUT_TEXT_RIGHT;
- but->drawflag &= ~UI_BUT_TEXT_LEFT;
- }
}
/* The resulting button may have the icon set since boolean button drawing
@@ -2227,50 +2339,21 @@ void uiItemFullR(uiLayout *layout,
#ifdef UI_PROP_DECORATE
if (ui_decorate.use_prop_decorate) {
- const bool is_anim = RNA_property_animateable(ptr, prop);
uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first;
+ const bool use_blank_decorator = (flag & UI_ITEM_R_FORCE_BLANK_DECORATE);
uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false);
layout_col->space = 0;
layout_col->emboss = UI_EMBOSS_NONE;
+
int i;
for (i = 0; i < ui_decorate.len && but_decorate; i++) {
+ PointerRNA *ptr_dec = use_blank_decorator ? NULL : &but_decorate->rnapoin;
+ PropertyRNA *prop_dec = use_blank_decorator ? NULL : but_decorate->rnaprop;
+
/* The icons are set in 'ui_but_anim_flag' */
- if (is_anim) {
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_DOT,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- TIP_("Animate property"));
- UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL);
- but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK;
- }
- else {
- /* We may show other information here in future, for now use empty space. */
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_BLANK1,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- "");
- but->flag |= UI_BUT_DISABLED;
- }
+ uiItemDecoratorR_prop(layout_col, ptr_dec, prop_dec, but_decorate->rnaindex);
+ but = block->buttons.last;
+
/* Order the decorator after the button we decorate, this is used so we can always
* do a quick lookup. */
BLI_remlink(&block->buttons, but);
@@ -2325,7 +2408,7 @@ void uiItemFullR_with_popover(uiLayout *layout,
uiItemFullR(layout, ptr, prop, index, value, flag, name, icon);
but = but->next;
while (but) {
- if (but->rnaprop == prop && but->type == UI_BTYPE_MENU) {
+ if (but->rnaprop == prop && ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_COLOR)) {
ui_but_rna_menu_convert_to_panel_type(but, panel_type);
break;
}
@@ -2562,6 +2645,13 @@ static void search_id_collection(StructRNA *ptype, PointerRNA *r_ptr, PropertyRN
RNA_STRUCT_END;
}
+static void ui_rna_collection_search_arg_free_fn(void *ptr)
+{
+ uiRNACollectionSearch *coll_search = ptr;
+ UI_butstore_free(coll_search->butstore_block, coll_search->butstore);
+ MEM_freeN(ptr);
+}
+
void ui_but_add_search(
uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
{
@@ -2594,7 +2684,10 @@ void ui_but_add_search(
coll_search->target_prop = prop;
coll_search->search_ptr = *searchptr;
coll_search->search_prop = searchprop;
- coll_search->but_changed = &but->changed;
+ coll_search->search_but = but;
+ coll_search->butstore_block = but->block;
+ coll_search->butstore = UI_butstore_create(coll_search->butstore_block);
+ UI_butstore_register(coll_search->butstore, &coll_search->search_but);
if (RNA_property_type(prop) == PROP_ENUM) {
/* XXX, this will have a menu string,
@@ -2604,9 +2697,9 @@ void ui_but_add_search(
UI_but_func_search_set(but,
ui_searchbox_create_generic,
- ui_rna_collection_search_cb,
+ ui_rna_collection_search_update_fn,
coll_search,
- true,
+ ui_rna_collection_search_arg_free_fn,
NULL,
NULL);
}
@@ -2733,6 +2826,7 @@ static uiBut *ui_item_menu(uiLayout *layout,
bool force_menu)
{
uiBlock *block = layout->root->block;
+ uiLayout *heading_layout = ui_layout_heading_find(layout);
uiBut *but;
int w, h;
@@ -2762,12 +2856,16 @@ static uiBut *ui_item_menu(uiLayout *layout,
}
}
+ if (heading_layout) {
+ ui_layout_heading_label_add(layout, heading_layout, true, true);
+ }
+
if (name[0] && icon) {
but = uiDefIconTextMenuBut(block, func, arg, icon, name, 0, 0, w, h, tip);
}
else if (icon) {
but = uiDefIconMenuBut(block, func, arg, icon, 0, 0, w, h, tip);
- if (force_menu) {
+ if (force_menu && name[0]) {
UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
}
}
@@ -2835,6 +2933,91 @@ void uiItemMContents(uiLayout *layout, const char *menuname)
UI_menutype_draw(C, mt, layout);
}
+/**
+ * Insert a decorator item for a button with the same property as \a prop.
+ * To force inserting a blank dummy element, NULL can be passed for \a ptr and \a prop.
+ */
+void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+ uiBlock *block = layout->root->block;
+ uiBut *but = NULL;
+
+ uiLayout *col;
+ UI_block_layout_set_current(block, layout);
+ col = uiLayoutColumn(layout, false);
+ col->space = 0;
+ col->emboss = UI_EMBOSS_NONE;
+
+ if (ELEM(NULL, ptr, prop) || !RNA_property_animateable(ptr, prop)) {
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ "");
+ but->flag |= UI_BUT_DISABLED;
+ return;
+ }
+
+ const bool is_expand = ui_item_rna_is_expand(prop, index, 0);
+ const bool is_array = RNA_property_array_check(prop);
+
+ /* Loop for the array-case, but only do in case of an expanded array. */
+ for (int i = 0; i < (is_expand ? RNA_property_array_length(ptr, prop) : 1); i++) {
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_DOT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Animate property"));
+ UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL);
+ but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK;
+ /* Reusing RNA search members, setting actual RNA data has many side-effects. */
+ but->rnasearchpoin = *ptr;
+ but->rnasearchprop = prop;
+ /* ui_def_but_rna() sets non-array buttons to have a RNA index of 0. */
+ but->custom_data = POINTER_FROM_INT((!is_array || is_expand) ? i : index);
+ }
+}
+
+/**
+ * Insert a decorator item for a button with the same property as \a prop.
+ * To force inserting a blank dummy element, NULL can be passed for \a ptr and \a propname.
+ */
+void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index)
+{
+ PropertyRNA *prop = NULL;
+
+ if (ptr && propname) {
+ /* validate arguments */
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ ui_item_disabled(layout, propname);
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+ }
+
+ /* ptr and prop are allowed to be NULL here. */
+ uiItemDecoratorR_prop(layout, ptr, prop, index);
+}
+
/* popover */
void uiItemPopoverPanel_ptr(
uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon)
@@ -2893,7 +3076,7 @@ void uiItemPopoverPanelFromGroup(uiLayout *layout,
return;
}
- for (PanelType *pt = art->paneltypes.first; pt; pt = pt->next) {
+ LISTBASE_FOREACH (PanelType *, pt, &art->paneltypes) {
/* Causes too many panels, check context. */
if (pt->parent_id[0] == '\0') {
if (/* (*context == '\0') || */ STREQ(pt->context, context)) {
@@ -2957,34 +3140,61 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
return but;
}
+void uiItemL_ex(
+ uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert)
+{
+ uiBut *but = uiItemL_(layout, name, icon);
+
+ if (highlight) {
+ /* TODO: add another flag for this. */
+ UI_but_flag_enable(but, UI_SELECT_DRAW);
+ }
+
+ if (redalert) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+}
+
void uiItemL(uiLayout *layout, const char *name, int icon)
{
uiItemL_(layout, name, icon);
}
/**
- * Helper to add a label, which handles logic for split property layout if needed.
- *
- * Normally, we handle the split layout in #uiItemFullR(), but there are other cases where we may
- * want to use the logic. For those this helper was added, although it will likely have to be
- * extended to support more cases.
- * Ideally, #uiItemFullR() could just call this, but it currently has too many special needs.
- *
- * \return the layout to place the item(s) associated to the label in.
+ * Normally, we handle the split layout in #uiItemFullR(), but there are other cases where the
+ * logic is needed. Ideally, #uiItemFullR() could just call this, but it currently has too many
+ * special needs.
+ */
+uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout)
+{
+ uiPropertySplitWrapper split_wrapper = {NULL};
+
+ uiLayout *layout_row = uiLayoutRow(parent_layout, true);
+ uiLayout *layout_split = uiLayoutSplit(layout_row, UI_ITEM_PROP_SEP_DIVIDE, true);
+
+ layout_split->space = 0;
+ split_wrapper.label_column = uiLayoutColumn(layout_split, true);
+ split_wrapper.label_column->alignment = UI_LAYOUT_ALIGN_RIGHT;
+ split_wrapper.property_row = ui_item_prop_split_layout_hack(parent_layout, layout_split);
+ split_wrapper.decorate_column = uiLayoutColumn(layout_row, true);
+
+ return split_wrapper;
+}
+
+/*
+ * Helper to add a label and creates a property split layout if needed.
*/
uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon)
{
if (layout->item.flag & UI_ITEM_PROP_SEP) {
- uiLayout *layout_split = uiLayoutSplit(layout, UI_ITEM_PROP_SEP_DIVIDE, true);
- uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
-
- layout_split->space = layout_sub->space = layout->space = 0;
- layout_sub->alignment = UI_LAYOUT_ALIGN_RIGHT;
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(layout);
+ /* Further items added to 'layout' will automatically be added to split_wrapper.property_row */
- uiItemL_(layout_sub, text, icon);
+ uiItemL_(split_wrapper.label_column, text, icon);
+ UI_block_layout_set_current(block, split_wrapper.property_row);
- /* Give caller a new sub-row to place items in. */
- return uiLayoutRow(layout_split, true);
+ return split_wrapper.decorate_column;
}
else {
char namestr[UI_MAX_NAME_STR];
@@ -3688,7 +3898,7 @@ static void ui_litem_layout_root(uiLayout *litem)
/* box layout */
static void ui_litem_estimate_box(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
ui_litem_estimate_column(litem, true);
@@ -3703,7 +3913,7 @@ static void ui_litem_estimate_box(uiLayout *litem)
static void ui_litem_layout_box(uiLayout *litem)
{
uiLayoutItemBx *box = (uiLayoutItemBx *)litem;
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiBut *but;
int w, h;
@@ -3748,7 +3958,7 @@ static void ui_litem_layout_box(uiLayout *litem)
/* multi-column layout, automatically flowing to the next */
static void ui_litem_estimate_column_flow(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
uiItem *item;
int col, x, y, emh, emy, miny, itemw, itemh, maxw = 0;
@@ -3813,7 +4023,7 @@ static void ui_litem_estimate_column_flow(uiLayout *litem)
static void ui_litem_layout_column_flow(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem;
uiItem *item;
int col, x, y, w, emh, emy, miny, itemw, itemh;
@@ -4052,7 +4262,7 @@ static void ui_litem_grid_flow_compute(ListBase *items,
static void ui_litem_estimate_grid_flow(uiLayout *litem)
{
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
const int space_x = style->columnspace;
@@ -4180,7 +4390,7 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem)
static void ui_litem_layout_grid_flow(uiLayout *litem)
{
int i;
- uiStyle *style = litem->root->style;
+ const uiStyle *style = litem->root->style;
uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
uiItem *item;
@@ -4425,13 +4635,24 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali
litem->redalert = layout->redalert;
litem->w = layout->w;
litem->emboss = layout->emboss;
- litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE));
+ litem->item.flag = (layout->item.flag &
+ (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE | UI_ITEM_INSIDE_PROP_SEP));
if (layout->child_items_layout) {
BLI_addtail(&layout->child_items_layout->items, litem);
+ litem->parent = layout->child_items_layout;
}
else {
BLI_addtail(&layout->items, litem);
+ litem->parent = layout;
+ }
+}
+
+static void ui_layout_heading_set(uiLayout *layout, const char *heading)
+{
+ BLI_assert(layout->heading[0] == '\0');
+ if (heading) {
+ STRNCPY(layout->heading, heading);
}
}
@@ -4451,6 +4672,16 @@ uiLayout *uiLayoutRow(uiLayout *layout, bool align)
return litem;
}
+/**
+ * See #uiLayoutColumnWithHeading().
+ */
+uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
+{
+ uiLayout *litem = uiLayoutRow(layout, align);
+ ui_layout_heading_set(litem, heading);
+ return litem;
+}
+
uiLayout *uiLayoutColumn(uiLayout *layout, bool align)
{
uiLayout *litem;
@@ -4466,6 +4697,19 @@ uiLayout *uiLayoutColumn(uiLayout *layout, bool align)
return litem;
}
+/**
+ * Variant of #uiLayoutColumn() that sets a heading label for the layout if the first item is
+ * added through #uiItemFullR(). If split layout is used and the item has no string to add to the
+ * first split-column, the heading is added there instead. Otherwise the heading inserted with a
+ * new row.
+ */
+uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading)
+{
+ uiLayout *litem = uiLayoutColumn(layout, align);
+ ui_layout_heading_set(litem, heading);
+ return litem;
+}
+
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align)
{
uiLayoutItemFlow *flow;
@@ -5073,8 +5317,15 @@ static void ui_layout_add_padding_button(uiLayoutRoot *root)
}
}
-uiLayout *UI_block_layout(
- uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, uiStyle *style)
+uiLayout *UI_block_layout(uiBlock *block,
+ int dir,
+ int type,
+ int x,
+ int y,
+ int size,
+ int em,
+ int padding,
+ const uiStyle *style)
{
uiLayout *layout;
uiLayoutRoot *root;
@@ -5326,7 +5577,7 @@ static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout,
MEM_freeN(panel);
/* Draw child panels. */
- for (LinkData *link = pt->children.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &pt->children) {
PanelType *child_pt = link->data;
if (child_pt->poll == NULL || child_pt->poll(C, child_pt)) {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index cc677f8f7cb..909da434554 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -26,9 +26,9 @@
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
+#include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */
#include "DNA_screen_types.h"
#include "DNA_text_types.h"
-#include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */
#include "BLI_blenlib.h"
#include "BLI_math_color.h"
@@ -40,8 +40,8 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_screen.h"
@@ -69,9 +69,9 @@
#include "ED_keyframing.h"
/* only for UI_OT_editsource */
-#include "ED_screen.h"
#include "BKE_main.h"
#include "BLI_ghash.h"
+#include "ED_screen.h"
/* -------------------------------------------------------------------- */
/** \name Copy Data Path Operator
@@ -650,7 +650,7 @@ static int override_remove_button_exec(bContext *C, wmOperator *op)
bool is_strict_find;
/* Remove override operation for given item,
* add singular operations for the other items as needed. */
- IDOverrideLibraryPropertyOperation *opop = BKE_override_library_property_operation_find(
+ IDOverrideLibraryPropertyOperation *opop = BKE_lib_override_library_property_operation_find(
oprop, NULL, NULL, index, index, false, &is_strict_find);
BLI_assert(opop != NULL);
if (!is_strict_find) {
@@ -659,22 +659,22 @@ static int override_remove_button_exec(bContext *C, wmOperator *op)
* before removing generic one. */
for (int idx = RNA_property_array_length(&ptr, prop); idx--;) {
if (idx != index) {
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
}
}
}
- BKE_override_library_property_operation_delete(oprop, opop);
+ BKE_lib_override_library_property_operation_delete(oprop, opop);
if (!is_template) {
RNA_property_copy(bmain, &ptr, &src, prop, index);
}
if (BLI_listbase_is_empty(&oprop->operations)) {
- BKE_override_library_property_delete(id->override_library, oprop);
+ BKE_lib_override_library_property_delete(id->override_library, oprop);
}
}
else {
/* Just remove whole generic override operation of this property. */
- BKE_override_library_property_delete(id->override_library, oprop);
+ BKE_lib_override_library_property_delete(id->override_library, oprop);
if (!is_template) {
RNA_property_copy(bmain, &ptr, &src, prop, -1);
}
@@ -735,6 +735,8 @@ bool UI_context_copy_to_selected_list(bContext *C,
{
*r_use_path_from_id = false;
*r_path = NULL;
+ /* special case for bone constraints */
+ char *path_from_bone = NULL;
/* PropertyGroup objects don't have a reference to the struct that actually owns
* them, so it is normally necessary to do a brute force search to find it. This
@@ -792,11 +794,28 @@ bool UI_context_copy_to_selected_list(bContext *C,
ui_context_selected_bones_via_pose(C, r_lb);
}
else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
- *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+ /* Special case when we do this for 'Sequence.lock'.
+ * (if the sequence is locked, it wont be in "selected_editable_sequences"). */
+ const char *prop_id = RNA_property_identifier(prop);
+ if (STREQ(prop_id, "lock")) {
+ *r_lb = CTX_data_collection_get(C, "selected_sequences");
+ }
+ else {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+ }
}
else if (RNA_struct_is_a(ptr->type, &RNA_FCurve)) {
*r_lb = CTX_data_collection_get(C, "selected_editable_fcurves");
}
+ else if (RNA_struct_is_a(ptr->type, &RNA_NlaStrip)) {
+ *r_lb = CTX_data_collection_get(C, "selected_nla_strips");
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Constraint) &&
+ (path_from_bone = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_PoseBone)) !=
+ NULL) {
+ *r_lb = CTX_data_collection_get(C, "selected_pose_bones");
+ *r_path = path_from_bone;
+ }
else if (RNA_struct_is_a(ptr->type, &RNA_Node) || RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
ListBase lb = {NULL, NULL};
char *path = NULL;
@@ -893,7 +912,15 @@ bool UI_context_copy_to_selected_list(bContext *C,
/* Try to recursively find an RNA_Sequence ancestor,
* to handle situations like T41062... */
if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) {
- *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+ /* Special case when we do this for 'Sequence.lock'.
+ * (if the sequence is locked, it wont be in "selected_editable_sequences"). */
+ const char *prop_id = RNA_property_identifier(prop);
+ if (STREQ(prop_id, "lock")) {
+ *r_lb = CTX_data_collection_get(C, "selected_sequences");
+ }
+ else {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+ }
}
}
return (*r_path != NULL);
@@ -1108,8 +1135,9 @@ static bool jump_to_target_button(bContext *C, bool poll)
else if (type == PROP_STRING) {
const uiBut *but = UI_context_active_but_get(C);
- if (but->type == UI_BTYPE_SEARCH_MENU && but->search_func == ui_rna_collection_search_cb) {
- uiRNACollectionSearch *coll_search = but->search_arg;
+ if (but->type == UI_BTYPE_SEARCH_MENU && but->search &&
+ but->search->update_fn == ui_rna_collection_search_update_fn) {
+ uiRNACollectionSearch *coll_search = but->search->arg;
char str_buf[MAXBONENAME];
char *str_ptr = RNA_property_string_get_alloc(&ptr, prop, str_buf, sizeof(str_buf), NULL);
@@ -1227,7 +1255,7 @@ static bool ui_editsource_uibut_match(uiBut *but_a, uiBut *but_b)
void UI_editsource_active_but_test(uiBut *but)
{
- extern void PyC_FileAndNum_Safe(const char **filename, int *lineno);
+ extern void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno);
struct uiEditSourceButStore *but_store = MEM_callocN(sizeof(uiEditSourceButStore), __func__);
@@ -1281,9 +1309,9 @@ static int editsource_text_edit(bContext *C,
else {
/* naughty!, find text area to set, not good behavior
* but since this is a dev tool lets allow it - campbell */
- ScrArea *sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TEXT, 0);
- if (sa) {
- SpaceText *st = sa->spacedata.first;
+ ScrArea *area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TEXT, 0);
+ if (area) {
+ SpaceText *st = area->spacedata.first;
st->text = text;
}
else {
@@ -1305,7 +1333,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
GHashIterator ghi;
struct uiEditSourceButStore *but_store = NULL;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
int ret;
/* needed else the active button does not get tested */
@@ -1317,9 +1345,9 @@ static int editsource_exec(bContext *C, wmOperator *op)
ui_editsource_active_but_set(but);
/* redraw and get active button python info */
- ED_region_do_layout(C, ar);
- ED_region_do_draw(C, ar);
- ar->do_draw = false;
+ ED_region_do_layout(C, region);
+ ED_region_do_draw(C, region);
+ region->do_draw = false;
for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
BLI_ghashIterator_done(&ghi) == false;
@@ -1593,22 +1621,23 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
static int ui_button_press_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
const bool skip_depressed = RNA_boolean_get(op->ptr, "skip_depressed");
- ARegion *ar_prev = CTX_wm_region(C);
- ARegion *ar = sc ? BKE_screen_find_region_xy(sc, RGN_TYPE_ANY, event->x, event->y) : NULL;
+ ARegion *region_prev = CTX_wm_region(C);
+ ARegion *region = screen ? BKE_screen_find_region_xy(screen, RGN_TYPE_ANY, event->x, event->y) :
+ NULL;
- if (ar == NULL) {
- ar = ar_prev;
+ if (region == NULL) {
+ region = region_prev;
}
- if (ar == NULL) {
+ if (region == NULL) {
return OPERATOR_PASS_THROUGH;
}
- CTX_wm_region_set(C, ar);
+ CTX_wm_region_set(C, region);
uiBut *but = UI_context_active_but_get(C);
- CTX_wm_region_set(C, ar_prev);
+ CTX_wm_region_set(C, region_prev);
if (but == NULL) {
return OPERATOR_PASS_THROUGH;
@@ -1621,11 +1650,11 @@ 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, ar, but);
+ UI_but_execute(C, region, but);
but->optype = but_optype;
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
return OPERATOR_FINISHED;
}
@@ -1650,7 +1679,7 @@ static void UI_OT_button_execute(wmOperatorType *ot)
static int button_string_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- uiBut *but = UI_context_active_but_get(C);
+ uiBut *but = UI_context_active_but_get_respect_menu(C);
if (but) {
ui_but_active_string_clear_and_exit(C, but);
@@ -1679,20 +1708,20 @@ static void UI_OT_button_string_clear(wmOperatorType *ot)
bool UI_drop_color_poll(struct bContext *C,
wmDrag *drag,
const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
/* should only return true for regions that include buttons, for now
* return true always */
if (drag->type == WM_DRAG_COLOR) {
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
if (UI_but_active_drop_color(C)) {
return 1;
}
if (sima && (sima->mode == SI_MODE_PAINT) && sima->image &&
- (ar && ar->regiontype == RGN_TYPE_WINDOW)) {
+ (region && region->regiontype == RGN_TYPE_WINDOW)) {
return 1;
}
}
@@ -1710,7 +1739,7 @@ void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
uiBut *but = NULL;
float color[4];
bool gamma;
@@ -1720,7 +1749,7 @@ static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* find button under mouse, check if it has RNA color property and
* if it does copy the data */
- but = ui_region_find_active_but(ar);
+ but = ui_region_find_active_but(region);
if (but && but->type == UI_BTYPE_COLOR && but->rnaprop) {
const int color_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
@@ -1754,7 +1783,7 @@ static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_imapaint_bucket_fill(C, color, op, event->mval);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index cc1b7187e45..04179721305 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -24,10 +24,10 @@
/* a full doc with API notes can be found in
* bf-blender/trunk/blender/doc/guides/interface_API.txt */
+#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
#include "MEM_guardedalloc.h"
@@ -51,12 +51,14 @@
#include "ED_screen.h"
-#include "UI_view2d.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
+#include "GPU_batch_presets.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "GPU_state.h"
#include "interface_intern.h"
@@ -100,13 +102,14 @@ typedef struct uiHandlePanelData {
double starttime;
/* dragging */
+ bool is_drag_drop;
int startx, starty;
int startofsx, startofsy;
int startsizex, startsizey;
} uiHandlePanelData;
-static int get_panel_real_size_y(const Panel *pa);
-static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state);
+static int get_panel_real_size_y(const Panel *panel);
+static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state);
static void panel_title_color_get(bool show_background, uchar color[4])
{
@@ -131,21 +134,21 @@ typedef enum eSpaceButtons_Align {
BUT_AUTO = 2,
} eSpaceButtons_Align;
-static int panel_aligned(const ScrArea *sa, const ARegion *ar)
+static int panel_aligned(const ScrArea *area, const ARegion *region)
{
- if (sa->spacetype == SPACE_PROPERTIES && ar->regiontype == RGN_TYPE_WINDOW) {
+ if (area->spacetype == SPACE_PROPERTIES && region->regiontype == RGN_TYPE_WINDOW) {
return BUT_VERTICAL;
}
- else if (sa->spacetype == SPACE_USERPREF && ar->regiontype == RGN_TYPE_WINDOW) {
+ else if (area->spacetype == SPACE_USERPREF && region->regiontype == RGN_TYPE_WINDOW) {
return BUT_VERTICAL;
}
- else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) {
+ else if (area->spacetype == SPACE_FILE && region->regiontype == RGN_TYPE_CHANNELS) {
return BUT_VERTICAL;
}
- else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW) {
+ else if (area->spacetype == SPACE_IMAGE && region->regiontype == RGN_TYPE_PREVIEW) {
return BUT_VERTICAL;
}
- else if (ELEM(ar->regiontype,
+ else if (ELEM(region->regiontype,
RGN_TYPE_UI,
RGN_TYPE_TOOLS,
RGN_TYPE_TOOL_PROPS,
@@ -160,71 +163,71 @@ static int panel_aligned(const ScrArea *sa, const ARegion *ar)
static bool panel_active_animation_changed(ListBase *lb, Panel **pa_animation, bool *no_animation)
{
- for (Panel *pa = lb->first; pa; pa = pa->next) {
+ LISTBASE_FOREACH (Panel *, panel, lb) {
/* Detect panel active flag changes. */
- if (!(pa->type && pa->type->parent)) {
- if ((pa->runtime_flag & PNL_WAS_ACTIVE) && !(pa->runtime_flag & PNL_ACTIVE)) {
+ if (!(panel->type && panel->type->parent)) {
+ if ((panel->runtime_flag & PNL_WAS_ACTIVE) && !(panel->runtime_flag & PNL_ACTIVE)) {
return true;
}
- if (!(pa->runtime_flag & PNL_WAS_ACTIVE) && (pa->runtime_flag & PNL_ACTIVE)) {
+ if (!(panel->runtime_flag & PNL_WAS_ACTIVE) && (panel->runtime_flag & PNL_ACTIVE)) {
return true;
}
}
- if ((pa->runtime_flag & PNL_ACTIVE) && !(pa->flag & PNL_CLOSED)) {
- if (panel_active_animation_changed(&pa->children, pa_animation, no_animation)) {
+ if ((panel->runtime_flag & PNL_ACTIVE) && !(panel->flag & PNL_CLOSED)) {
+ if (panel_active_animation_changed(&panel->children, pa_animation, no_animation)) {
return true;
}
}
/* Detect animation. */
- if (pa->activedata) {
- uiHandlePanelData *data = pa->activedata;
+ if (panel->activedata) {
+ uiHandlePanelData *data = panel->activedata;
if (data->state == PANEL_STATE_ANIMATION) {
- *pa_animation = pa;
+ *pa_animation = panel;
}
else {
/* Don't animate while handling other interaction. */
*no_animation = true;
}
}
- if ((pa->runtime_flag & PNL_ANIM_ALIGN) && !(*pa_animation)) {
- *pa_animation = pa;
+ if ((panel->runtime_flag & PNL_ANIM_ALIGN) && !(*pa_animation)) {
+ *pa_animation = panel;
}
}
return false;
}
-static bool panels_need_realign(ScrArea *sa, ARegion *ar, Panel **r_pa_animate)
+static bool panels_need_realign(ScrArea *area, ARegion *region, Panel **r_panel_animation)
{
- *r_pa_animate = NULL;
+ *r_panel_animation = NULL;
- if (sa->spacetype == SPACE_PROPERTIES && ar->regiontype == RGN_TYPE_WINDOW) {
- SpaceProperties *sbuts = sa->spacedata.first;
+ if (area->spacetype == SPACE_PROPERTIES && region->regiontype == RGN_TYPE_WINDOW) {
+ SpaceProperties *sbuts = area->spacedata.first;
if (sbuts->mainbo != sbuts->mainb) {
return true;
}
}
- else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW) {
+ else if (area->spacetype == SPACE_IMAGE && region->regiontype == RGN_TYPE_PREVIEW) {
return true;
}
- else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) {
+ else if (area->spacetype == SPACE_FILE && region->regiontype == RGN_TYPE_CHANNELS) {
return true;
}
/* Detect if a panel was added or removed. */
- Panel *pa_animation = NULL;
+ Panel *panel_animation = NULL;
bool no_animation = false;
- if (panel_active_animation_changed(&ar->panels, &pa_animation, &no_animation)) {
+ if (panel_active_animation_changed(&region->panels, &panel_animation, &no_animation)) {
return true;
}
/* Detect panel marked for animation, if we're not already animating. */
- if (pa_animation) {
+ if (panel_animation) {
if (!no_animation) {
- *r_pa_animate = pa_animation;
+ *r_panel_animation = panel_animation;
}
return true;
}
@@ -234,24 +237,24 @@ static bool panels_need_realign(ScrArea *sa, ARegion *ar, Panel **r_pa_animate)
/****************************** panels ******************************/
-static void panels_collapse_all(ScrArea *sa, ARegion *ar, const Panel *from_pa)
+static void panels_collapse_all(ScrArea *area, ARegion *region, const Panel *from_panel)
{
- const bool has_category_tabs = UI_panel_category_is_visible(ar);
- const char *category = has_category_tabs ? UI_panel_category_active_get(ar, false) : NULL;
- const int flag = ((panel_aligned(sa, ar) == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY);
- const PanelType *from_pt = from_pa->type;
- Panel *pa;
+ const bool has_category_tabs = UI_panel_category_is_visible(region);
+ const char *category = has_category_tabs ? UI_panel_category_active_get(region, false) : NULL;
+ const int flag = ((panel_aligned(area, region) == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY);
+ const PanelType *from_pt = from_panel->type;
+ Panel *panel;
- for (pa = ar->panels.first; pa; pa = pa->next) {
- PanelType *pt = pa->type;
+ for (panel = region->panels.first; panel; panel = panel->next) {
+ PanelType *pt = panel->type;
/* close panels with headers in the same context */
if (pt && from_pt && !(pt->flag & PNL_NO_HEADER)) {
if (!pt->context[0] || !from_pt->context[0] || STREQ(pt->context, from_pt->context)) {
- if ((pa->flag & PNL_PIN) || !category || !pt->category[0] ||
+ if ((panel->flag & PNL_PIN) || !category || !pt->category[0] ||
STREQ(pt->category, category)) {
- pa->flag &= ~PNL_CLOSED;
- pa->flag |= flag;
+ panel->flag &= ~PNL_CLOSED;
+ panel->flag |= flag;
}
}
}
@@ -260,117 +263,123 @@ static void panels_collapse_all(ScrArea *sa, ARegion *ar, const Panel *from_pa)
Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt)
{
- Panel *pa;
+ Panel *panel;
const char *idname = pt->idname;
- for (pa = lb->first; pa; pa = pa->next) {
- if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
- return pa;
+ for (panel = lb->first; panel; panel = panel->next) {
+ if (STREQLEN(panel->panelname, idname, sizeof(panel->panelname))) {
+ return panel;
}
}
return NULL;
}
/**
- * \note \a pa should be return value from #UI_panel_find_by_type and can be NULL.
+ * \note \a panel should be return value from #UI_panel_find_by_type and can be NULL.
*/
-Panel *UI_panel_begin(
- ScrArea *sa, ARegion *ar, ListBase *lb, uiBlock *block, PanelType *pt, Panel *pa, bool *r_open)
-{
- Panel *palast, *panext;
+Panel *UI_panel_begin(ScrArea *area,
+ ARegion *region,
+ ListBase *lb,
+ uiBlock *block,
+ PanelType *pt,
+ Panel *panel,
+ bool *r_open)
+{
+ Panel *panel_last, *panel_next;
const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
const char *idname = pt->idname;
- const bool newpanel = (pa == NULL);
- int align = panel_aligned(sa, ar);
+ const bool newpanel = (panel == NULL);
+ int align = panel_aligned(area, region);
if (!newpanel) {
- pa->type = pt;
+ panel->type = pt;
}
else {
/* new panel */
- pa = MEM_callocN(sizeof(Panel), "new panel");
- pa->type = pt;
- BLI_strncpy(pa->panelname, idname, sizeof(pa->panelname));
+ panel = MEM_callocN(sizeof(Panel), "new panel");
+ panel->type = pt;
+ BLI_strncpy(panel->panelname, idname, sizeof(panel->panelname));
if (pt->flag & PNL_DEFAULT_CLOSED) {
if (align == BUT_VERTICAL) {
- pa->flag |= PNL_CLOSEDY;
+ panel->flag |= PNL_CLOSEDY;
}
else {
- pa->flag |= PNL_CLOSEDX;
+ panel->flag |= PNL_CLOSEDX;
}
}
- pa->ofsx = 0;
- pa->ofsy = 0;
- pa->sizex = 0;
- pa->sizey = 0;
- pa->blocksizex = 0;
- pa->blocksizey = 0;
- pa->runtime_flag |= PNL_NEW_ADDED;
+ panel->ofsx = 0;
+ panel->ofsy = 0;
+ panel->sizex = 0;
+ panel->sizey = 0;
+ panel->blocksizex = 0;
+ panel->blocksizey = 0;
+ panel->runtime_flag |= PNL_NEW_ADDED;
- BLI_addtail(lb, pa);
+ BLI_addtail(lb, panel);
}
/* Do not allow closed panels without headers! Else user could get "disappeared" UI! */
- if ((pt->flag & PNL_NO_HEADER) && (pa->flag & PNL_CLOSED)) {
- pa->flag &= ~PNL_CLOSED;
+ if ((pt->flag & PNL_NO_HEADER) && (panel->flag & PNL_CLOSED)) {
+ panel->flag &= ~PNL_CLOSED;
/* Force update of panels' positions! */
- pa->sizex = 0;
- pa->sizey = 0;
- pa->blocksizex = 0;
- pa->blocksizey = 0;
+ panel->sizex = 0;
+ panel->sizey = 0;
+ panel->blocksizex = 0;
+ panel->blocksizey = 0;
}
- BLI_strncpy(pa->drawname, drawname, sizeof(pa->drawname));
+ BLI_strncpy(panel->drawname, drawname, sizeof(panel->drawname));
/* if a new panel is added, we insert it right after the panel
* that was last added. this way new panels are inserted in the
* right place between versions */
- for (palast = lb->first; palast; palast = palast->next) {
- if (palast->runtime_flag & PNL_LAST_ADDED) {
- BLI_remlink(lb, pa);
- BLI_insertlinkafter(lb, palast, pa);
+ for (panel_last = lb->first; panel_last; panel_last = panel_last->next) {
+ if (panel_last->runtime_flag & PNL_LAST_ADDED) {
+ BLI_remlink(lb, panel);
+ BLI_insertlinkafter(lb, panel_last, panel);
break;
}
}
if (newpanel) {
- pa->sortorder = (palast) ? palast->sortorder + 1 : 0;
+ panel->sortorder = (panel_last) ? panel_last->sortorder + 1 : 0;
- for (panext = lb->first; panext; panext = panext->next) {
- if (panext != pa && panext->sortorder >= pa->sortorder) {
- panext->sortorder++;
+ for (panel_next = lb->first; panel_next; panel_next = panel_next->next) {
+ if (panel_next != panel && panel_next->sortorder >= panel->sortorder) {
+ panel_next->sortorder++;
}
}
}
- if (palast) {
- palast->runtime_flag &= ~PNL_LAST_ADDED;
+ if (panel_last) {
+ panel_last->runtime_flag &= ~PNL_LAST_ADDED;
}
/* assign to block */
- block->panel = pa;
- pa->runtime_flag |= PNL_ACTIVE | PNL_LAST_ADDED;
- if (ar->alignment == RGN_ALIGN_FLOAT) {
+ block->panel = panel;
+ panel->runtime_flag |= PNL_ACTIVE | PNL_LAST_ADDED;
+ if (region->alignment == RGN_ALIGN_FLOAT) {
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
}
*r_open = false;
- if (pa->flag & PNL_CLOSED) {
- return pa;
+ if (panel->flag & PNL_CLOSED) {
+ return panel;
}
*r_open = true;
- return pa;
+ return panel;
}
-static float panel_region_offset_x_get(const ARegion *ar, int align)
+static float panel_region_offset_x_get(const ARegion *region, int align)
{
- if (UI_panel_category_is_visible(ar)) {
- if (align == BUT_VERTICAL && (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) != RGN_ALIGN_RIGHT)) {
+ if (UI_panel_category_is_visible(region)) {
+ if (align == BUT_VERTICAL &&
+ (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) != RGN_ALIGN_RIGHT)) {
return UI_PANEL_CATEGORY_MARGIN_WIDTH;
}
}
@@ -379,16 +388,16 @@ static float panel_region_offset_x_get(const ARegion *ar, int align)
}
void UI_panel_end(
- const ScrArea *sa, const ARegion *ar, uiBlock *block, int width, int height, bool open)
+ const ScrArea *area, const ARegion *region, uiBlock *block, int width, int height, bool open)
{
- Panel *pa = block->panel;
+ Panel *panel = block->panel;
/* Set panel size excluding children. */
- pa->blocksizex = width;
- pa->blocksizey = height;
+ panel->blocksizex = width;
+ panel->blocksizey = height;
/* Compute total panel size including children. */
- for (Panel *pachild = pa->children.first; pachild; pachild = pachild->next) {
+ LISTBASE_FOREACH (Panel *, pachild, &panel->children) {
if (pachild->runtime_flag & PNL_ACTIVE) {
width = max_ii(width, pachild->sizex);
height += get_panel_real_size_y(pachild);
@@ -396,46 +405,47 @@ void UI_panel_end(
}
/* Update total panel size. */
- if (pa->runtime_flag & PNL_NEW_ADDED) {
- pa->runtime_flag &= ~PNL_NEW_ADDED;
- pa->sizex = width;
- pa->sizey = height;
+ if (panel->runtime_flag & PNL_NEW_ADDED) {
+ panel->runtime_flag &= ~PNL_NEW_ADDED;
+ panel->sizex = width;
+ panel->sizey = height;
}
else {
- int old_sizex = pa->sizex, old_sizey = pa->sizey;
- int old_region_ofsx = pa->runtime.region_ofsx;
+ int old_sizex = panel->sizex, old_sizey = panel->sizey;
+ int old_region_ofsx = panel->runtime.region_ofsx;
/* update width/height if non-zero */
if (width != 0) {
- pa->sizex = width;
+ panel->sizex = width;
}
if (height != 0 || open) {
- pa->sizey = height;
+ panel->sizey = height;
}
/* check if we need to do an animation */
- if (pa->sizex != old_sizex || pa->sizey != old_sizey) {
- pa->runtime_flag |= PNL_ANIM_ALIGN;
- pa->ofsy += old_sizey - pa->sizey;
+ if (panel->sizex != old_sizex || panel->sizey != old_sizey) {
+ panel->runtime_flag |= PNL_ANIM_ALIGN;
+ panel->ofsy += old_sizey - panel->sizey;
}
- int align = panel_aligned(sa, ar);
- if (old_region_ofsx != panel_region_offset_x_get(ar, align)) {
- pa->runtime_flag |= PNL_ANIM_ALIGN;
+ int align = panel_aligned(area, region);
+ panel->runtime.region_ofsx = panel_region_offset_x_get(region, align);
+ if (old_region_ofsx != panel->runtime.region_ofsx) {
+ panel->runtime_flag |= PNL_ANIM_ALIGN;
}
}
}
static void ui_offset_panel_block(uiBlock *block)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
/* compute bounds and offset */
ui_block_bounds_calc(block);
int ofsy = block->panel->sizey - style->panelspace;
- for (uiBut *but = block->buttons.first; but; but = but->next) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
but->rect.ymin += ofsy;
but->rect.ymax += ofsy;
}
@@ -538,59 +548,6 @@ static void ui_draw_panel_scalewidget(uint pos, const rcti *rect)
GPU_blend(false);
}
-static void immRectf_tris_color_ex(
- uint pos, float x1, float y1, float x2, float y2, uint col, const float color[3])
-{
- immAttr4fv(col, color);
- immVertex2f(pos, x1, y1);
- immAttr4fv(col, color);
- immVertex2f(pos, x2, y1);
- immAttr4fv(col, color);
- immVertex2f(pos, x2, y2);
-
- immAttr4fv(col, color);
- immVertex2f(pos, x1, y1);
- immAttr4fv(col, color);
- immVertex2f(pos, x2, y2);
- immAttr4fv(col, color);
- immVertex2f(pos, x1, y2);
-}
-
-static void ui_draw_panel_dragwidget(uint pos, uint col, const rctf *rect)
-{
- float col_high[4], col_dark[4];
- const int col_tint = 84;
-
- const int px = (int)U.pixelsize;
- const int px_zoom = max_ii(round_fl_to_int(BLI_rctf_size_y(rect) / 22.0f), 1);
-
- const int box_margin = max_ii(round_fl_to_int((float)(px_zoom * 2.0f)), px);
- const int box_size = max_ii(round_fl_to_int((BLI_rctf_size_y(rect) / 8.0f) - px), px);
-
- const int x_min = rect->xmin;
- const int y_min = rect->ymin;
- const int y_ofs = max_ii(round_fl_to_int(BLI_rctf_size_y(rect) / 2.5f), px);
- const int x_ofs = y_ofs;
- int i_x, i_y;
-
- UI_GetThemeColorShade4fv(TH_PANEL_HEADER, col_tint, col_high);
- UI_GetThemeColorShade4fv(TH_PANEL_BACK, -col_tint, col_dark);
-
- /* draw multiple boxes */
- immBegin(GPU_PRIM_TRIS, 4 * 2 * (6 * 2));
- for (i_x = 0; i_x < 4; i_x++) {
- for (i_y = 0; i_y < 2; i_y++) {
- const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin));
- const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin));
-
- immRectf_tris_color_ex(
- pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom, col, col_dark);
- immRectf_tris_color_ex(pos, x_co - box_size, y_co, x_co, y_co + box_size, col, col_high);
- }
- }
- immEnd();
-}
-
/* For button layout next to label. */
void UI_panel_label_offset(uiBlock *block, int *r_x, int *r_y)
{
@@ -749,24 +706,27 @@ void ui_draw_aligned_panel(uiStyle *style,
ui_draw_aligned_panel_header(style, block, &titlerect, 'h', show_background);
if (show_drag) {
- uint col;
- GPUVertFormat *format = immVertexFormat();
- pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-
/* itemrect smaller */
+ const float scale = 0.7;
itemrect.xmax = headrect.xmax - (0.2f * UI_UNIT_X);
itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect);
itemrect.ymin = headrect.ymin;
itemrect.ymax = headrect.ymax;
+ BLI_rctf_scale(&itemrect, scale);
- BLI_rctf_scale(&itemrect, 0.7f);
- immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- ui_draw_panel_dragwidget(pos, col, &itemrect);
- immUnbindProgram();
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(itemrect.xmin, itemrect.ymin);
+
+ const int col_tint = 84;
+ float col_high[4], col_dark[4];
+ UI_GetThemeColorShade4fv(TH_PANEL_HEADER, col_tint, col_high);
+ UI_GetThemeColorShade4fv(TH_PANEL_BACK, -col_tint, col_dark);
- /* Restore format for the following draws. */
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUBatch *batch = GPU_batch_preset_panel_drag_widget(
+ U.pixelsize, col_high, col_dark, BLI_rcti_size_y(&headrect) * scale);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_FLAT_COLOR);
+ GPU_batch_draw(batch);
+ GPU_matrix_pop();
}
}
@@ -784,7 +744,7 @@ void ui_draw_aligned_panel(uiStyle *style,
/* an open panel */
else {
/* in some occasions, draw a border */
- if (panel->flag & PNL_SELECT) {
+ if (panel->flag & PNL_SELECT && !is_subpanel) {
if (panel->control & UI_PNL_SOLID) {
UI_draw_roundbox_corner_set(UI_CNR_ALL);
}
@@ -861,64 +821,74 @@ void ui_draw_aligned_panel(uiStyle *style,
/************************** panel alignment *************************/
-static int get_panel_header(const Panel *pa)
+static int get_panel_header(const Panel *panel)
{
- if (pa->type && (pa->type->flag & PNL_NO_HEADER)) {
+ if (panel->type && (panel->type->flag & PNL_NO_HEADER)) {
return 0;
}
return PNL_HEADER;
}
-static int get_panel_size_y(const Panel *pa)
+static int get_panel_size_y(const Panel *panel)
{
- if (pa->type && (pa->type->flag & PNL_NO_HEADER)) {
- return pa->sizey;
+ if (panel->type && (panel->type->flag & PNL_NO_HEADER)) {
+ return panel->sizey;
}
- return PNL_HEADER + pa->sizey;
+ return PNL_HEADER + panel->sizey;
}
-static int get_panel_real_size_y(const Panel *pa)
+static int get_panel_real_size_y(const Panel *panel)
{
- int sizey = (pa->flag & PNL_CLOSED) ? 0 : pa->sizey;
+ int sizey = (panel->flag & PNL_CLOSED) ? 0 : panel->sizey;
- if (pa->type && (pa->type->flag & PNL_NO_HEADER)) {
+ if (panel->type && (panel->type->flag & PNL_NO_HEADER)) {
return sizey;
}
return PNL_HEADER + sizey;
}
-int UI_panel_size_y(const Panel *pa)
+int UI_panel_size_y(const Panel *panel)
{
- return get_panel_real_size_y(pa);
+ return get_panel_real_size_y(panel);
}
/* this function is needed because uiBlock and Panel itself don't
* change sizey or location when closed */
-static int get_panel_real_ofsy(Panel *pa)
+static int get_panel_real_ofsy(Panel *panel)
{
- if (pa->flag & PNL_CLOSEDY) {
- return pa->ofsy + pa->sizey;
+ if (panel->flag & PNL_CLOSEDY) {
+ return panel->ofsy + panel->sizey;
}
else {
- return pa->ofsy;
+ return panel->ofsy;
}
}
-static int get_panel_real_ofsx(Panel *pa)
+static int get_panel_real_ofsx(Panel *panel)
{
- if (pa->flag & PNL_CLOSEDX) {
- return pa->ofsx + get_panel_header(pa);
+ if (panel->flag & PNL_CLOSEDX) {
+ return panel->ofsx + get_panel_header(panel);
}
else {
- return pa->ofsx + pa->sizex;
+ return panel->ofsx + panel->sizex;
}
}
+bool UI_panel_is_dragging(const struct Panel *panel)
+{
+ uiHandlePanelData *data = panel->activedata;
+ if (!data) {
+ return false;
+ }
+
+ return data->is_drag_drop;
+}
+
typedef struct PanelSort {
- Panel *pa, *orig;
+ Panel *panel, *orig;
} PanelSort;
/**
@@ -933,16 +903,16 @@ static int find_leftmost_panel(const void *a1, const void *a2)
{
const PanelSort *ps1 = a1, *ps2 = a2;
- if (ps1->pa->ofsx > ps2->pa->ofsx) {
+ if (ps1->panel->ofsx > ps2->panel->ofsx) {
return 1;
}
- else if (ps1->pa->ofsx < ps2->pa->ofsx) {
+ else if (ps1->panel->ofsx < ps2->panel->ofsx) {
return -1;
}
- else if (ps1->pa->sortorder > ps2->pa->sortorder) {
+ else if (ps1->panel->sortorder > ps2->panel->sortorder) {
return 1;
}
- else if (ps1->pa->sortorder < ps2->pa->sortorder) {
+ else if (ps1->panel->sortorder < ps2->panel->sortorder) {
return -1;
}
@@ -955,26 +925,26 @@ static int find_highest_panel(const void *a1, const void *a2)
/* stick uppermost header-less panels to the top of the region -
* prevent them from being sorted (multiple header-less panels have to be sorted though) */
- if (ps1->pa->type->flag & PNL_NO_HEADER && ps2->pa->type->flag & PNL_NO_HEADER) {
+ if (ps1->panel->type->flag & PNL_NO_HEADER && ps2->panel->type->flag & PNL_NO_HEADER) {
/* skip and check for ofs and sortorder below */
}
- else if (ps1->pa->type->flag & PNL_NO_HEADER) {
+ else if (ps1->panel->type->flag & PNL_NO_HEADER) {
return -1;
}
- else if (ps2->pa->type->flag & PNL_NO_HEADER) {
+ else if (ps2->panel->type->flag & PNL_NO_HEADER) {
return 1;
}
- if (ps1->pa->ofsy + ps1->pa->sizey < ps2->pa->ofsy + ps2->pa->sizey) {
+ if (ps1->panel->ofsy + ps1->panel->sizey < ps2->panel->ofsy + ps2->panel->sizey) {
return 1;
}
- else if (ps1->pa->ofsy + ps1->pa->sizey > ps2->pa->ofsy + ps2->pa->sizey) {
+ else if (ps1->panel->ofsy + ps1->panel->sizey > ps2->panel->ofsy + ps2->panel->sizey) {
return -1;
}
- else if (ps1->pa->sortorder > ps2->pa->sortorder) {
+ else if (ps1->panel->sortorder > ps2->panel->sortorder) {
return 1;
}
- else if (ps1->pa->sortorder < ps2->pa->sortorder) {
+ else if (ps1->panel->sortorder < ps2->panel->sortorder) {
return -1;
}
@@ -985,24 +955,24 @@ static int compare_panel(const void *a1, const void *a2)
{
const PanelSort *ps1 = a1, *ps2 = a2;
- if (ps1->pa->sortorder > ps2->pa->sortorder) {
+ if (ps1->panel->sortorder > ps2->panel->sortorder) {
return 1;
}
- else if (ps1->pa->sortorder < ps2->pa->sortorder) {
+ else if (ps1->panel->sortorder < ps2->panel->sortorder) {
return -1;
}
return 0;
}
-static void align_sub_panels(Panel *pa)
+static void align_sub_panels(Panel *panel)
{
/* Position sub panels. */
- int ofsy = get_panel_real_ofsy(pa) + pa->sizey - pa->blocksizey;
+ int ofsy = panel->ofsy + panel->sizey - panel->blocksizey;
- for (Panel *pachild = pa->children.first; pachild; pachild = pachild->next) {
+ LISTBASE_FOREACH (Panel *, pachild, &panel->children) {
if (pachild->runtime_flag & PNL_ACTIVE) {
- pachild->ofsx = pa->ofsx;
+ pachild->ofsx = panel->ofsx;
pachild->ofsy = ofsy - get_panel_size_y(pachild);
ofsy -= get_panel_real_size_y(pachild);
@@ -1015,17 +985,17 @@ static void align_sub_panels(Panel *pa)
/* this doesn't draw */
/* returns 1 when it did something */
-static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bool drag)
+static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, const bool drag)
{
- Panel *pa;
+ Panel *panel;
PanelSort *ps, *panelsort, *psnext;
int a, tot = 0;
bool done;
- int align = panel_aligned(sa, ar);
+ int align = panel_aligned(area, region);
/* count active, not tabbed panels */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ACTIVE) {
+ for (panel = region->panels.first; panel; panel = panel->next) {
+ if (panel->runtime_flag & PNL_ACTIVE) {
tot++;
}
}
@@ -1035,13 +1005,13 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
}
/* extra; change close direction? */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ACTIVE) {
- if ((pa->flag & PNL_CLOSEDX) && (align == BUT_VERTICAL)) {
- pa->flag ^= PNL_CLOSED;
+ for (panel = region->panels.first; panel; panel = panel->next) {
+ if (panel->runtime_flag & PNL_ACTIVE) {
+ if ((panel->flag & PNL_CLOSEDX) && (align == BUT_VERTICAL)) {
+ panel->flag ^= PNL_CLOSED;
}
- else if ((pa->flag & PNL_CLOSEDY) && (align == BUT_HORIZONTAL)) {
- pa->flag ^= PNL_CLOSED;
+ else if ((panel->flag & PNL_CLOSEDY) && (align == BUT_HORIZONTAL)) {
+ panel->flag ^= PNL_CLOSED;
}
}
}
@@ -1050,10 +1020,10 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
panelsort = MEM_callocN(tot * sizeof(PanelSort), "panelsort");
ps = panelsort;
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ACTIVE) {
- ps->pa = MEM_dupallocN(pa);
- ps->orig = pa;
+ for (panel = region->panels.first; panel; panel = panel->next) {
+ if (panel->runtime_flag & PNL_ACTIVE) {
+ ps->panel = MEM_dupallocN(panel);
+ ps->orig = panel;
ps++;
}
}
@@ -1078,21 +1048,22 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
/* no smart other default start loc! this keeps switching f5/f6/etc compatible */
ps = panelsort;
- ps->pa->runtime.region_ofsx = panel_region_offset_x_get(ar, align);
- ps->pa->ofsx = 0;
- ps->pa->ofsy = -get_panel_size_y(ps->pa);
- ps->pa->ofsx += ps->pa->runtime.region_ofsx;
+ ps->panel->runtime.region_ofsx = panel_region_offset_x_get(region, align);
+ ps->panel->ofsx = 0;
+ ps->panel->ofsy = -get_panel_size_y(ps->panel);
+ ps->panel->ofsx += ps->panel->runtime.region_ofsx;
for (a = 0; a < tot - 1; a++, ps++) {
psnext = ps + 1;
if (align == BUT_VERTICAL) {
- psnext->pa->ofsx = ps->pa->ofsx;
- psnext->pa->ofsy = get_panel_real_ofsy(ps->pa) - get_panel_size_y(psnext->pa);
+ psnext->panel->ofsx = ps->panel->ofsx;
+ psnext->panel->ofsy = get_panel_real_ofsy(ps->panel) - get_panel_size_y(psnext->panel);
}
else {
- psnext->pa->ofsx = get_panel_real_ofsx(ps->pa);
- psnext->pa->ofsy = ps->pa->ofsy + get_panel_size_y(ps->pa) - get_panel_size_y(psnext->pa);
+ psnext->panel->ofsx = get_panel_real_ofsx(ps->panel);
+ psnext->panel->ofsy = ps->panel->ofsy + get_panel_size_y(ps->panel) -
+ get_panel_size_y(psnext->panel);
}
}
@@ -1100,11 +1071,11 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
done = false;
ps = panelsort;
for (a = 0; a < tot; a++, ps++) {
- if ((ps->pa->flag & PNL_SELECT) == 0) {
- if ((ps->orig->ofsx != ps->pa->ofsx) || (ps->orig->ofsy != ps->pa->ofsy)) {
- ps->orig->ofsx = round_fl_to_int(fac * (float)ps->pa->ofsx +
+ if ((ps->panel->flag & PNL_SELECT) == 0) {
+ if ((ps->orig->ofsx != ps->panel->ofsx) || (ps->orig->ofsy != ps->panel->ofsy)) {
+ ps->orig->ofsx = round_fl_to_int(fac * (float)ps->panel->ofsx +
(1.0f - fac) * (float)ps->orig->ofsx);
- ps->orig->ofsy = round_fl_to_int(fac * (float)ps->pa->ofsy +
+ ps->orig->ofsy = round_fl_to_int(fac * (float)ps->panel->ofsy +
(1.0f - fac) * (float)ps->orig->ofsy);
done = true;
}
@@ -1112,42 +1083,42 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
}
/* set locations for tabbed and sub panels */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ACTIVE) {
- if (pa->children.first) {
- align_sub_panels(pa);
+ for (panel = region->panels.first; panel; panel = panel->next) {
+ if (panel->runtime_flag & PNL_ACTIVE) {
+ if (panel->children.first) {
+ align_sub_panels(panel);
}
}
}
/* free panelsort array */
for (ps = panelsort, a = 0; a < tot; a++, ps++) {
- MEM_freeN(ps->pa);
+ MEM_freeN(ps->panel);
}
MEM_freeN(panelsort);
return done;
}
-static void ui_panels_size(ScrArea *sa, ARegion *ar, int *r_x, int *r_y)
+static void ui_panels_size(ScrArea *area, ARegion *region, int *r_x, int *r_y)
{
- Panel *pa;
- int align = panel_aligned(sa, ar);
+ Panel *panel;
+ int align = panel_aligned(area, region);
int sizex = 0;
int sizey = 0;
/* compute size taken up by panels, for setting in view2d */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ACTIVE) {
+ for (panel = region->panels.first; panel; panel = panel->next) {
+ if (panel->runtime_flag & PNL_ACTIVE) {
int pa_sizex, pa_sizey;
if (align == BUT_VERTICAL) {
- pa_sizex = pa->ofsx + pa->sizex;
- pa_sizey = get_panel_real_ofsy(pa);
+ pa_sizex = panel->ofsx + panel->sizex;
+ pa_sizey = get_panel_real_ofsy(panel);
}
else {
- pa_sizex = get_panel_real_ofsx(pa) + pa->sizex;
- pa_sizey = pa->ofsy + get_panel_size_y(pa);
+ pa_sizex = get_panel_real_ofsx(panel) + panel->sizex;
+ pa_sizey = panel->ofsy + get_panel_size_y(panel);
}
sizex = max_ii(sizex, pa_sizex);
@@ -1169,16 +1140,16 @@ static void ui_panels_size(ScrArea *sa, ARegion *ar, int *r_x, int *r_y)
static void ui_do_animate(const bContext *C, Panel *panel)
{
uiHandlePanelData *data = panel->activedata;
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
float fac;
fac = (PIL_check_seconds_timer() - data->starttime) / ANIMATION_TIME;
fac = min_ff(sqrtf(fac), 1.0f);
/* for max 1 second, interpolate positions */
- if (uiAlignPanelStep(sa, ar, fac, false)) {
- ED_region_tag_redraw(ar);
+ if (uiAlignPanelStep(area, region, fac, false)) {
+ ED_region_tag_redraw(region);
}
else {
fac = 1.0f;
@@ -1194,95 +1165,95 @@ static void panel_list_clear_active(ListBase *lb)
{
/* set all panels as inactive, so that at the end we know
* which ones were used */
- for (Panel *pa = lb->first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ACTIVE) {
- pa->runtime_flag = PNL_WAS_ACTIVE;
+ LISTBASE_FOREACH (Panel *, panel, lb) {
+ if (panel->runtime_flag & PNL_ACTIVE) {
+ panel->runtime_flag = PNL_WAS_ACTIVE;
}
else {
- pa->runtime_flag = 0;
+ panel->runtime_flag = 0;
}
- panel_list_clear_active(&pa->children);
+ panel_list_clear_active(&panel->children);
}
}
-void UI_panels_begin(const bContext *UNUSED(C), ARegion *ar)
+void UI_panels_begin(const bContext *UNUSED(C), ARegion *region)
{
- panel_list_clear_active(&ar->panels);
+ panel_list_clear_active(&region->panels);
}
/* only draws blocks with panels */
-void UI_panels_end(const bContext *C, ARegion *ar, int *r_x, int *r_y)
+void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
uiBlock *block;
- Panel *pa, *firstpa;
+ Panel *panel, *panel_first;
/* offset contents */
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
if (block->active && block->panel) {
ui_offset_panel_block(block);
}
}
/* re-align, possibly with animation */
- if (panels_need_realign(sa, ar, &pa)) {
- if (pa) {
- panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
+ if (panels_need_realign(area, region, &panel)) {
+ if (panel) {
+ panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
}
else {
- uiAlignPanelStep(sa, ar, 1.0, false);
+ uiAlignPanelStep(area, region, 1.0, false);
}
}
/* tag first panel */
- firstpa = NULL;
- for (block = ar->uiblocks.first; block; block = block->next) {
+ panel_first = NULL;
+ for (block = region->uiblocks.first; block; block = block->next) {
if (block->active && block->panel) {
- if (!firstpa || block->panel->sortorder < firstpa->sortorder) {
- firstpa = block->panel;
+ if (!panel_first || block->panel->sortorder < panel_first->sortorder) {
+ panel_first = block->panel;
}
}
}
- if (firstpa) {
- firstpa->runtime_flag |= PNL_FIRST;
+ if (panel_first) {
+ panel_first->runtime_flag |= PNL_FIRST;
}
/* compute size taken up by panel */
- ui_panels_size(sa, ar, r_x, r_y);
+ ui_panels_size(area, region, r_x, r_y);
}
-void UI_panels_draw(const bContext *C, ARegion *ar)
+void UI_panels_draw(const bContext *C, ARegion *region)
{
uiBlock *block;
- if (ar->alignment != RGN_ALIGN_FLOAT) {
+ if (region->alignment != RGN_ALIGN_FLOAT) {
UI_ThemeClearColor(TH_BACK);
}
/* Draw panels, selected on top. Also in reverse order, because
* UI blocks are added in reverse order and we need child panels
* to draw on top. */
- for (block = ar->uiblocks.last; block; block = block->prev) {
+ for (block = region->uiblocks.last; block; block = block->prev) {
if (block->active && block->panel && !(block->panel->flag & PNL_SELECT)) {
UI_block_draw(C, block);
}
}
- for (block = ar->uiblocks.last; block; block = block->prev) {
+ for (block = region->uiblocks.last; block; block = block->prev) {
if (block->active && block->panel && (block->panel->flag & PNL_SELECT)) {
UI_block_draw(C, block);
}
}
}
-void UI_panels_scale(ARegion *ar, float new_width)
+void UI_panels_scale(ARegion *region, float new_width)
{
uiBlock *block;
uiBut *but;
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
if (block->panel) {
float fac = new_width / (float)block->panel->sizex;
block->panel->sizex = new_width;
@@ -1297,22 +1268,22 @@ void UI_panels_scale(ARegion *ar, float new_width)
/* ------------ panel merging ---------------- */
-static void check_panel_overlap(ARegion *ar, Panel *panel)
+static void check_panel_overlap(ARegion *region, Panel *panel)
{
- Panel *pa;
+ Panel *panel_list;
/* also called with (panel == NULL) for clear */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- pa->flag &= ~PNL_OVERLAP;
- if (panel && (pa != panel)) {
- if (pa->runtime_flag & PNL_ACTIVE) {
+ for (panel_list = region->panels.first; panel_list; panel_list = panel_list->next) {
+ panel_list->flag &= ~PNL_OVERLAP;
+ if (panel && (panel_list != panel)) {
+ if (panel_list->runtime_flag & PNL_ACTIVE) {
float safex = 0.2, safey = 0.2;
- if (pa->flag & PNL_CLOSEDX) {
+ if (panel_list->flag & PNL_CLOSEDX) {
safex = 0.05;
}
- else if (pa->flag & PNL_CLOSEDY) {
+ else if (panel_list->flag & PNL_CLOSEDY) {
safey = 0.05;
}
else if (panel->flag & PNL_CLOSEDX) {
@@ -1322,11 +1293,12 @@ static void check_panel_overlap(ARegion *ar, Panel *panel)
safey = 0.05;
}
- if (pa->ofsx > panel->ofsx - safex * panel->sizex) {
- if (pa->ofsx + pa->sizex < panel->ofsx + (1.0f + safex) * panel->sizex) {
- if (pa->ofsy > panel->ofsy - safey * panel->sizey) {
- if (pa->ofsy + pa->sizey < panel->ofsy + (1.0f + safey) * panel->sizey) {
- pa->flag |= PNL_OVERLAP;
+ if (panel_list->ofsx > panel->ofsx - safex * panel->sizex) {
+ if (panel_list->ofsx + panel_list->sizex < panel->ofsx + (1.0f + safex) * panel->sizex) {
+ if (panel_list->ofsy > panel->ofsy - safey * panel->sizey) {
+ if (panel_list->ofsy + panel_list->sizey <
+ panel->ofsy + (1.0f + safey) * panel->sizey) {
+ panel_list->flag |= PNL_OVERLAP;
}
}
}
@@ -1341,20 +1313,20 @@ static void check_panel_overlap(ARegion *ar, Panel *panel)
static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
{
uiHandlePanelData *data = panel->activedata;
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- short align = panel_aligned(sa, ar), dx = 0, dy = 0;
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ short align = panel_aligned(area, region), dx = 0, dy = 0;
/* first clip for window, no dragging outside */
- if (!BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) {
+ if (!BLI_rcti_isect_pt_v(&region->winrct, &event->x)) {
return;
}
dx = (event->x - data->startx) & ~(PNL_GRID - 1);
dy = (event->y - data->starty) & ~(PNL_GRID - 1);
- dx *= (float)BLI_rctf_size_x(&ar->v2d.cur) / (float)BLI_rcti_size_x(&ar->winrct);
- dy *= (float)BLI_rctf_size_y(&ar->v2d.cur) / (float)BLI_rcti_size_y(&ar->winrct);
+ dx *= (float)BLI_rctf_size_x(&region->v2d.cur) / (float)BLI_rcti_size_x(&region->winrct);
+ dy *= (float)BLI_rctf_size_y(&region->v2d.cur) / (float)BLI_rcti_size_y(&region->winrct);
if (data->state == PANEL_STATE_DRAG_SCALE) {
panel->sizex = MAX2(data->startsizex + dx, UI_PANEL_MINX);
@@ -1372,25 +1344,25 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
panel->ofsx = data->startofsx + dx;
panel->ofsy = data->startofsy + dy;
- check_panel_overlap(ar, panel);
+ check_panel_overlap(region, panel);
if (align) {
- uiAlignPanelStep(sa, ar, 0.2, true);
+ uiAlignPanelStep(area, region, 0.2, true);
}
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
/******************* region level panel interaction *****************/
static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block,
- const Panel *pa,
+ const Panel *panel,
const int mx,
const int my)
{
/* open panel */
- if (pa->flag & PNL_CLOSEDX) {
+ if (panel->flag & PNL_CLOSEDX) {
if ((block->rect.xmin <= mx) && (block->rect.xmin + PNL_HEADER >= mx)) {
return PANEL_MOUSE_INSIDE_HEADER;
}
@@ -1403,8 +1375,8 @@ static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block,
return PANEL_MOUSE_INSIDE_HEADER;
}
/* open panel */
- else if (!(pa->flag & PNL_CLOSEDY)) {
- if (pa->control & UI_PNL_SCALE) {
+ else if (!(panel->flag & PNL_CLOSEDY)) {
+ if (panel->control & UI_PNL_SCALE) {
if (block->rect.xmax - PNL_HEADER <= mx) {
if (block->rect.ymin + PNL_HEADER >= my) {
return PANEL_MOUSE_INSIDE_SCALE;
@@ -1435,22 +1407,22 @@ static void ui_panel_drag_collapse(bContext *C,
uiPanelDragCollapseHandle *dragcol_data,
const int xy_dst[2])
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
uiBlock *block;
- Panel *pa;
+ Panel *panel;
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
float xy_a_block[2] = {UNPACK2(dragcol_data->xy_init)};
float xy_b_block[2] = {UNPACK2(xy_dst)};
rctf rect = block->rect;
int oldflag;
- const bool is_horizontal = (panel_aligned(sa, ar) == BUT_HORIZONTAL);
+ const bool is_horizontal = (panel_aligned(area, region) == BUT_HORIZONTAL);
- if ((pa = block->panel) == 0 || (pa->type && (pa->type->flag & PNL_NO_HEADER))) {
+ if ((panel = block->panel) == 0 || (panel->type && (panel->type->flag & PNL_NO_HEADER))) {
continue;
}
- oldflag = pa->flag;
+ oldflag = panel->flag;
/* lock one axis */
if (is_horizontal) {
@@ -1461,13 +1433,13 @@ static void ui_panel_drag_collapse(bContext *C,
}
/* use cursor coords in block space */
- ui_window_to_block_fl(ar, block, &xy_a_block[0], &xy_a_block[1]);
- ui_window_to_block_fl(ar, block, &xy_b_block[0], &xy_b_block[1]);
+ ui_window_to_block_fl(region, block, &xy_a_block[0], &xy_a_block[1]);
+ ui_window_to_block_fl(region, block, &xy_b_block[0], &xy_b_block[1]);
/* set up rect to match header size */
rect.ymin = rect.ymax;
rect.ymax = rect.ymin + PNL_HEADER;
- if (pa->flag & PNL_CLOSEDX) {
+ if (panel->flag & PNL_CLOSEDX) {
rect.xmax = rect.xmin + PNL_HEADER;
}
@@ -1475,16 +1447,16 @@ static void ui_panel_drag_collapse(bContext *C,
if (BLI_rctf_isect_segment(&rect, xy_a_block, xy_b_block)) {
/* force panel to close */
if (dragcol_data->was_first_open == true) {
- pa->flag |= (is_horizontal ? PNL_CLOSEDX : PNL_CLOSEDY);
+ panel->flag |= (is_horizontal ? PNL_CLOSEDX : PNL_CLOSEDY);
}
/* force panel to open */
else {
- pa->flag &= ~PNL_CLOSED;
+ panel->flag &= ~PNL_CLOSED;
}
- /* if pa->flag has changed this means a panel was opened/closed here */
- if (pa->flag != oldflag) {
- panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
+ /* if panel->flag has changed this means a panel was opened/closed here */
+ if (panel->flag != oldflag) {
+ panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
}
}
}
@@ -1547,18 +1519,19 @@ static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was
static void ui_handle_panel_header(
const bContext *C, uiBlock *block, int mx, int my, int event, short ctrl, short shift)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
#ifdef USE_PIN_HIDDEN
- const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->type->parent == NULL) &&
- (block->panel->flag & PNL_PIN);
+ const bool show_pin = UI_panel_category_is_visible(region) &&
+ (block->panel->type->parent == NULL) && (block->panel->flag & PNL_PIN);
#else
- const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->type->parent == NULL);
+ const bool show_pin = UI_panel_category_is_visible(region) &&
+ (block->panel->type->parent == NULL);
#endif
const bool is_subpanel = (block->panel->type && block->panel->type->parent);
const bool show_drag = !is_subpanel;
- int align = panel_aligned(sa, ar), button = 0;
+ int align = panel_aligned(area, region), button = 0;
rctf rect_drag, rect_pin;
float rect_leftmost;
@@ -1577,13 +1550,13 @@ static void ui_handle_panel_header(
/* XXX weak code, currently it assumes layout style for location of widgets */
/* check open/collapsed button */
- if (event == RETKEY) {
+ if (event == EVT_RETKEY) {
button = 1;
}
- else if (event == AKEY) {
+ else if (event == EVT_AKEY) {
button = 1;
}
- else if (ELEM(event, 0, RETKEY, LEFTMOUSE) && shift) {
+ else if (ELEM(event, 0, EVT_RETKEY, LEFTMOUSE) && shift) {
if (block->panel->type->parent == NULL) {
block->panel->flag ^= PNL_PIN;
button = 2;
@@ -1609,14 +1582,17 @@ static void ui_handle_panel_header(
if (button) {
if (button == 2) { /* close */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
else { /* collapse */
if (ctrl) {
- panels_collapse_all(sa, ar, block->panel);
+ /* Only collapse all for parent panels. */
+ if (block->panel->type != NULL && block->panel->type->parent == NULL) {
+ panels_collapse_all(area, region, block->panel);
- /* reset the view - we don't want to display a view without content */
- UI_view2d_offset(&ar->v2d, 0.0f, 1.0f);
+ /* reset the view - we don't want to display a view without content */
+ UI_view2d_offset(&region->v2d, 0.0f, 1.0f);
+ }
}
if (block->panel->flag & PNL_CLOSED) {
@@ -1657,42 +1633,44 @@ static void ui_handle_panel_header(
/* FIXME: this doesn't update the panel drawing, assert to avoid debugging why this is.
* We could fix this in the future if it's ever needed. */
BLI_assert(0);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
else if (show_drag && BLI_rctf_isect_x(&rect_drag, mx)) {
/* XXX, for now don't allow dragging in floating windows yet. */
- if (ar->alignment == RGN_ALIGN_FLOAT) {
+ if (region->alignment == RGN_ALIGN_FLOAT) {
return;
}
panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
}
else if (show_pin && BLI_rctf_isect_x(&rect_pin, mx)) {
block->panel->flag ^= PNL_PIN;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
-bool UI_panel_category_is_visible(const ARegion *ar)
+bool UI_panel_category_is_visible(const ARegion *region)
{
/* more than one */
- return ar->panels_category.first && ar->panels_category.first != ar->panels_category.last;
+ return region->panels_category.first &&
+ region->panels_category.first != region->panels_category.last;
}
-PanelCategoryDyn *UI_panel_category_find(ARegion *ar, const char *idname)
+PanelCategoryDyn *UI_panel_category_find(ARegion *region, const char *idname)
{
- return BLI_findstring(&ar->panels_category, idname, offsetof(PanelCategoryDyn, idname));
+ return BLI_findstring(&region->panels_category, idname, offsetof(PanelCategoryDyn, idname));
}
-PanelCategoryStack *UI_panel_category_active_find(ARegion *ar, const char *idname)
+PanelCategoryStack *UI_panel_category_active_find(ARegion *region, const char *idname)
{
- return BLI_findstring(&ar->panels_category_active, idname, offsetof(PanelCategoryStack, idname));
+ return BLI_findstring(
+ &region->panels_category_active, idname, offsetof(PanelCategoryStack, idname));
}
-static void ui_panel_category_active_set(ARegion *ar, const char *idname, bool fallback)
+static void ui_panel_category_active_set(ARegion *region, const char *idname, bool fallback)
{
- ListBase *lb = &ar->panels_category_active;
- PanelCategoryStack *pc_act = UI_panel_category_active_find(ar, idname);
+ ListBase *lb = &region->panels_category_active;
+ PanelCategoryStack *pc_act = UI_panel_category_active_find(region, idname);
if (pc_act) {
BLI_remlink(lb, pc_act);
@@ -1719,7 +1697,8 @@ static void ui_panel_category_active_set(ARegion *ar, const char *idname, bool f
pc_act_next = pc_act->next;
while ((pc_act = pc_act_next)) {
pc_act_next = pc_act->next;
- if (!BLI_findstring(&ar->type->paneltypes, pc_act->idname, offsetof(PanelType, category))) {
+ if (!BLI_findstring(
+ &region->type->paneltypes, pc_act->idname, offsetof(PanelType, category))) {
BLI_remlink(lb, pc_act);
MEM_freeN(pc_act);
}
@@ -1727,32 +1706,32 @@ static void ui_panel_category_active_set(ARegion *ar, const char *idname, bool f
}
}
-void UI_panel_category_active_set(ARegion *ar, const char *idname)
+void UI_panel_category_active_set(ARegion *region, const char *idname)
{
- ui_panel_category_active_set(ar, idname, false);
+ ui_panel_category_active_set(region, idname, false);
}
-void UI_panel_category_active_set_default(ARegion *ar, const char *idname)
+void UI_panel_category_active_set_default(ARegion *region, const char *idname)
{
- if (!UI_panel_category_active_find(ar, idname)) {
- ui_panel_category_active_set(ar, idname, true);
+ if (!UI_panel_category_active_find(region, idname)) {
+ ui_panel_category_active_set(region, idname, true);
}
}
-const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback)
+const char *UI_panel_category_active_get(ARegion *region, bool set_fallback)
{
PanelCategoryStack *pc_act;
- for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
- if (UI_panel_category_find(ar, pc_act->idname)) {
+ for (pc_act = region->panels_category_active.first; pc_act; pc_act = pc_act->next) {
+ if (UI_panel_category_find(region, pc_act->idname)) {
return pc_act->idname;
}
}
if (set_fallback) {
- PanelCategoryDyn *pc_dyn = ar->panels_category.first;
+ PanelCategoryDyn *pc_dyn = region->panels_category.first;
if (pc_dyn) {
- ui_panel_category_active_set(ar, pc_dyn->idname, true);
+ ui_panel_category_active_set(region, pc_dyn->idname, true);
return pc_dyn->idname;
}
}
@@ -1760,11 +1739,11 @@ const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback)
return NULL;
}
-PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *ar, const int x, const int y)
+PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *region, const int x, const int y)
{
PanelCategoryDyn *ptd;
- for (ptd = ar->panels_category.first; ptd; ptd = ptd->next) {
+ for (ptd = region->panels_category.first; ptd; ptd = ptd->next) {
if (BLI_rcti_isect_pt(&ptd->rect, x, y)) {
return ptd;
}
@@ -1773,24 +1752,24 @@ PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *ar, const int x,
return NULL;
}
-PanelCategoryDyn *UI_panel_category_find_mouse_over(ARegion *ar, const wmEvent *event)
+PanelCategoryDyn *UI_panel_category_find_mouse_over(ARegion *region, const wmEvent *event)
{
- return UI_panel_category_find_mouse_over_ex(ar, event->mval[0], event->mval[1]);
+ return UI_panel_category_find_mouse_over_ex(region, event->mval[0], event->mval[1]);
}
-void UI_panel_category_add(ARegion *ar, const char *name)
+void UI_panel_category_add(ARegion *region, const char *name)
{
PanelCategoryDyn *pc_dyn = MEM_callocN(sizeof(*pc_dyn), __func__);
- BLI_addtail(&ar->panels_category, pc_dyn);
+ BLI_addtail(&region->panels_category, pc_dyn);
BLI_strncpy(pc_dyn->idname, name, sizeof(pc_dyn->idname));
/* 'pc_dyn->rect' must be set on draw */
}
-void UI_panel_category_clear_all(ARegion *ar)
+void UI_panel_category_clear_all(ARegion *region)
{
- BLI_freelistN(&ar->panels_category);
+ BLI_freelistN(&region->panels_category);
}
static void imm_buf_append(
@@ -1922,18 +1901,18 @@ static void ui_panel_category_draw_tab(bool filled,
* Draw vertical tabs on the left side of the region,
* one tab per category.
*/
-void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
+void UI_panel_category_draw_all(ARegion *region, const char *category_id_active)
{
/* no tab outlines for */
// #define USE_FLAT_INACTIVE
- const bool is_left = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment != RGN_ALIGN_RIGHT);
- View2D *v2d = &ar->v2d;
- uiStyle *style = UI_style_get();
+ const bool is_left = RGN_ALIGN_ENUM_FROM_MASK(region->alignment != RGN_ALIGN_RIGHT);
+ View2D *v2d = &region->v2d;
+ const uiStyle *style = UI_style_get();
const uiFontStyle *fstyle = &style->widget;
const int fontid = fstyle->uifont_id;
short fstyle_points = fstyle->points;
PanelCategoryDyn *pc_dyn;
- const float aspect = ((uiBlock *)ar->uiblocks.first)->aspect;
+ const float aspect = ((uiBlock *)region->uiblocks.first)->aspect;
const float zoom = 1.0f / aspect;
const int px = max_ii(1, round_fl_to_int(U.pixelsize));
const int px_x_sign = is_left ? px : -px;
@@ -1990,7 +1969,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
interp_v3_v3v3_uchar(
theme_col_tab_highlight_inactive, theme_col_tab_inactive, theme_col_text_hi, 0.12f);
- is_alpha = (ar->overlap && (theme_col_back[3] != 255));
+ is_alpha = (region->overlap && (theme_col_back[3] != 255));
if (fstyle->kerning == 1) {
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
@@ -2004,12 +1983,12 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* Check the region type supports categories to avoid an assert
* for showing 3D view panels in the properties space. */
- if ((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) {
- BLI_assert(UI_panel_category_is_visible(ar));
+ if ((1 << region->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) {
+ BLI_assert(UI_panel_category_is_visible(region));
}
/* calculate tab rect's and check if we need to scale down */
- for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
+ for (pc_dyn = region->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
rcti *rct = &pc_dyn->rect;
const char *category_id = pc_dyn->idname;
const char *category_id_draw = IFACE_(category_id);
@@ -2027,7 +2006,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
if (y_ofs > BLI_rcti_size_y(&v2d->mask)) {
scaletabs = (float)BLI_rcti_size_y(&v2d->mask) / (float)y_ofs;
- for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
+ for (pc_dyn = region->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
rcti *rct = &pc_dyn->rect;
rct->ymin = ((rct->ymin - v2d->mask.ymax) * scaletabs) + v2d->mask.ymax;
rct->ymax = ((rct->ymax - v2d->mask.ymax) * scaletabs) + v2d->mask.ymax;
@@ -2072,7 +2051,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
const int divider_xmax = is_left ? (v2d->mask.xmin + category_tabs_width) :
(v2d->mask.xmax - (category_tabs_width + px)) + px;
- for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
+ for (pc_dyn = region->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
const rcti *rct = &pc_dyn->rect;
const char *category_id = pc_dyn->idname;
const char *category_id_draw = IFACE_(category_id);
@@ -2209,14 +2188,14 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
}
static int ui_handle_panel_category_cycling(const wmEvent *event,
- ARegion *ar,
+ ARegion *region,
const uiBut *active_but)
{
const bool is_mousewheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE);
const bool inside_tabregion =
- ((RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) != RGN_ALIGN_RIGHT) ?
- (event->mval[0] < ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmax) :
- (event->mval[0] > ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmin));
+ ((RGN_ALIGN_ENUM_FROM_MASK(region->alignment) != RGN_ALIGN_RIGHT) ?
+ (event->mval[0] < ((PanelCategoryDyn *)region->panels_category.first)->rect.xmax) :
+ (event->mval[0] > ((PanelCategoryDyn *)region->panels_category.first)->rect.xmin));
/* if mouse is inside non-tab region, ctrl key is required */
if (is_mousewheel && !event->ctrl && !inside_tabregion) {
@@ -2228,9 +2207,9 @@ static int ui_handle_panel_category_cycling(const wmEvent *event,
* using ctrl+mousewheel work in tabbed regions */
}
else {
- const char *category = UI_panel_category_active_get(ar, false);
+ const char *category = UI_panel_category_active_get(region, false);
if (LIKELY(category)) {
- PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category);
+ PanelCategoryDyn *pc_dyn = UI_panel_category_find(region, category);
if (LIKELY(pc_dyn)) {
if (is_mousewheel) {
/* we can probably get rid of this and only allow ctrl+tabbing */
@@ -2242,15 +2221,15 @@ static int ui_handle_panel_category_cycling(const wmEvent *event,
if (!pc_dyn) {
/* proper cyclic behavior,
* back to first/last category (only used for ctrl+tab) */
- pc_dyn = backwards ? ar->panels_category.last : ar->panels_category.first;
+ pc_dyn = backwards ? region->panels_category.last : region->panels_category.first;
}
}
if (pc_dyn) {
/* intentionally don't reset scroll in this case,
* this allows for quick browsing between tabs */
- UI_panel_category_active_set(ar, pc_dyn->idname);
- ED_region_tag_redraw(ar);
+ UI_panel_category_active_set(region, pc_dyn->idname);
+ ED_region_tag_redraw(region);
}
}
}
@@ -2265,18 +2244,18 @@ static int ui_handle_panel_category_cycling(const wmEvent *event,
int ui_handler_panel_region(bContext *C,
const wmEvent *event,
- ARegion *ar,
+ ARegion *region,
const uiBut *active_but)
{
uiBlock *block;
- Panel *pa;
+ Panel *panel;
int retval, mx, my;
- bool has_category_tabs = UI_panel_category_is_visible(ar);
+ bool has_category_tabs = UI_panel_category_is_visible(region);
retval = WM_UI_HANDLER_CONTINUE;
/* Scrollbars can overlap panels now, they have handling priority. */
- if (UI_view2d_mouse_in_scrollers(ar, &ar->v2d, event->x, event->y)) {
+ if (UI_view2d_mouse_in_scrollers(region, &region->v2d, event->x, event->y)) {
return retval;
}
@@ -2284,21 +2263,21 @@ int ui_handler_panel_region(bContext *C,
if (has_category_tabs) {
if (event->val == KM_PRESS) {
if (event->type == LEFTMOUSE) {
- PanelCategoryDyn *pc_dyn = UI_panel_category_find_mouse_over(ar, event);
+ PanelCategoryDyn *pc_dyn = UI_panel_category_find_mouse_over(region, event);
if (pc_dyn) {
- UI_panel_category_active_set(ar, pc_dyn->idname);
- ED_region_tag_redraw(ar);
+ UI_panel_category_active_set(region, pc_dyn->idname);
+ ED_region_tag_redraw(region);
/* reset scroll to the top [#38348] */
- UI_view2d_offset(&ar->v2d, -1.0f, 1.0f);
+ UI_view2d_offset(&region->v2d, -1.0f, 1.0f);
retval = WM_UI_HANDLER_BREAK;
}
}
- else if ((event->type == TABKEY && event->ctrl) ||
+ else if ((event->type == EVT_TABKEY && event->ctrl) ||
ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
/* cycle tabs */
- retval = ui_handle_panel_category_cycling(event, ar, active_but);
+ retval = ui_handle_panel_category_cycling(event, region, active_but);
}
}
}
@@ -2307,32 +2286,33 @@ int ui_handler_panel_region(bContext *C,
return retval;
}
- for (block = ar->uiblocks.last; block; block = block->prev) {
+ for (block = region->uiblocks.last; block; block = block->prev) {
uiPanelMouseState mouse_state;
mx = event->x;
my = event->y;
- ui_window_to_block(ar, block, &mx, &my);
+ ui_window_to_block(region, block, &mx, &my);
/* checks for mouse position inside */
- pa = block->panel;
+ panel = block->panel;
- if (!pa) {
+ if (!panel) {
continue;
}
/* XXX - accessed freed panels when scripts reload, need to fix. */
- if (pa->type && pa->type->flag & PNL_NO_HEADER) {
+ if (panel->type && panel->type->flag & PNL_NO_HEADER) {
continue;
}
- mouse_state = ui_panel_mouse_state_get(block, pa, mx, my);
+ mouse_state = ui_panel_mouse_state_get(block, panel, mx, my);
/* XXX hardcoded key warning */
if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER) &&
event->val == KM_PRESS) {
- if (event->type == AKEY && ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) {
+ if (event->type == EVT_AKEY &&
+ ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) {
- if (pa->flag & PNL_CLOSEDY) {
+ if (panel->flag & PNL_CLOSEDY) {
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift);
}
@@ -2347,7 +2327,7 @@ int ui_handler_panel_region(bContext *C,
}
/* on active button, do not handle panels */
- if (ui_region_find_active_but(ar) != NULL) {
+ if (ui_region_find_active_but(region) != NULL) {
continue;
}
@@ -2356,9 +2336,9 @@ int ui_handler_panel_region(bContext *C,
if (event->val == KM_PRESS) {
/* open close on header */
- if (ELEM(event->type, RETKEY, PADENTER)) {
+ if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER)) {
if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
- ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->shift);
+ ui_handle_panel_header(C, block, mx, my, EVT_RETKEY, event->ctrl, event->shift);
retval = WM_UI_HANDLER_BREAK;
break;
}
@@ -2372,35 +2352,35 @@ int ui_handler_panel_region(bContext *C,
retval = WM_UI_HANDLER_BREAK;
break;
}
- else if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(pa->flag & PNL_CLOSED)) {
- panel_activate_state(C, pa, PANEL_STATE_DRAG_SCALE);
+ else if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(panel->flag & PNL_CLOSED)) {
+ panel_activate_state(C, panel, PANEL_STATE_DRAG_SCALE);
retval = WM_UI_HANDLER_BREAK;
break;
}
}
else if (event->type == RIGHTMOUSE) {
if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
- ui_popup_context_menu_for_panel(C, ar, block->panel);
+ ui_popup_context_menu_for_panel(C, region, block->panel);
retval = WM_UI_HANDLER_BREAK;
break;
}
}
- else if (event->type == ESCKEY) {
+ else if (event->type == EVT_ESCKEY) {
/*XXX 2.50*/
#if 0
if (block->handler) {
- rem_blockhandler(sa, block->handler);
- ED_region_tag_redraw(ar);
+ rem_blockhandler(area, block->handler);
+ ED_region_tag_redraw(region);
retval = WM_UI_HANDLER_BREAK;
}
#endif
}
- else if (event->type == PADPLUSKEY || event->type == PADMINUS) {
+ else if (event->type == EVT_PADPLUSKEY || event->type == EVT_PADMINUS) {
#if 0 /* XXX make float panel exception? */
int zoom = 0;
/* if panel is closed, only zoom if mouse is over the header */
- if (pa->flag & (PNL_CLOSEDX | PNL_CLOSEDY)) {
+ if (panel->flag & (PNL_CLOSEDX | PNL_CLOSEDY)) {
if (inside_header) {
zoom = 1;
}
@@ -2410,11 +2390,11 @@ int ui_handler_panel_region(bContext *C,
}
if (zoom) {
- ScrArea *sa = CTX_wm_area(C);
- SpaceLink *sl = sa->spacedata.first;
+ ScrArea *area = CTX_wm_area(C);
+ SpaceLink *sl = area->spacedata.first;
- if (sa->spacetype != SPACE_PROPERTIES) {
- if (!(pa->control & UI_PNL_SCALE)) {
+ if (area->spacetype != SPACE_PROPERTIES) {
+ if (!(panel->control & UI_PNL_SCALE)) {
if (event->type == PADPLUSKEY) {
sl->blockscale += 0.1;
}
@@ -2423,7 +2403,7 @@ int ui_handler_panel_region(bContext *C,
}
CLAMP(sl->blockscale, 0.6, 1.0);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
retval = WM_UI_HANDLER_BREAK;
}
}
@@ -2447,9 +2427,9 @@ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata)
/* verify if we can stop */
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- int align = panel_aligned(sa, ar);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ int align = panel_aligned(area, region);
if (align) {
panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
@@ -2484,21 +2464,41 @@ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata)
static void ui_handler_remove_panel(bContext *C, void *userdata)
{
- Panel *pa = userdata;
+ Panel *panel = userdata;
- panel_activate_state(C, pa, PANEL_STATE_EXIT);
+ panel_activate_state(C, panel, PANEL_STATE_EXIT);
}
-static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state)
+/**
+ * Set selection state for a panel and its subpanels. The subpanels need to know they are selected
+ * too so they can be drawn above their parent when it is dragged.
+ */
+static void set_panel_selection(Panel *panel, bool value)
+{
+ if (value) {
+ panel->flag |= PNL_SELECT;
+ }
+ else {
+ panel->flag &= ~PNL_SELECT;
+ }
+
+ LISTBASE_FOREACH (Panel *, child, &panel->children) {
+ set_panel_selection(child, value);
+ }
+}
+
+static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state)
{
- uiHandlePanelData *data = pa->activedata;
+ uiHandlePanelData *data = panel->activedata;
wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
if (data && data->state == state) {
return;
}
+ bool was_drag_drop = (data && data->state == PANEL_STATE_DRAG);
+
if (state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) {
if (data && data->state != PANEL_STATE_ANIMATION) {
/* XXX:
@@ -2507,14 +2507,14 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
* is very hard to control and use, and has no real benefit." - BillRey
* Aligorith, 2009Sep
*/
- // test_add_new_tabs(ar); // also copies locations of tabs in dragged panel
- check_panel_overlap(ar, NULL); /* clears */
+ // test_add_new_tabs(region); // also copies locations of tabs in dragged panel
+ check_panel_overlap(region, NULL); /* clears */
}
- pa->flag &= ~PNL_SELECT;
+ set_panel_selection(panel, false);
}
else {
- pa->flag |= PNL_SELECT;
+ set_panel_selection(panel, true);
}
if (data && data->animtimer) {
@@ -2524,18 +2524,18 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
if (state == PANEL_STATE_EXIT) {
MEM_freeN(data);
- pa->activedata = NULL;
+ panel->activedata = NULL;
WM_event_remove_ui_handler(
- &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, false);
+ &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, panel, false);
}
else {
if (!data) {
data = MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData");
- pa->activedata = data;
+ panel->activedata = data;
WM_event_add_ui_handler(
- C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, 0);
+ C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, panel, 0);
}
if (ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG)) {
@@ -2545,14 +2545,20 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
data->state = state;
data->startx = win->eventstate->x;
data->starty = win->eventstate->y;
- data->startofsx = pa->ofsx;
- data->startofsy = pa->ofsy;
- data->startsizex = pa->sizex;
- data->startsizey = pa->sizey;
+ data->startofsx = panel->ofsx;
+ data->startofsy = panel->ofsy;
+ data->startsizex = panel->sizex;
+ data->startsizey = panel->sizey;
data->starttime = PIL_check_seconds_timer();
+
+ /* Remember drag drop state even when animating to the aligned position after dragging. */
+ data->is_drag_drop = was_drag_drop;
+ if (state == PANEL_STATE_DRAG) {
+ data->is_drag_drop = true;
+ }
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
PanelType *UI_paneltype_find(int space_id, int region_id, const char *idname)
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
index ab20b5ac520..6d05fe15f97 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -20,9 +20,10 @@
* Utilities to inspect the interface, extract information.
*/
-#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_utildefines.h"
#include "DNA_screen_types.h"
@@ -160,6 +161,21 @@ bool UI_but_has_tooltip_label(const uiBut *but)
return false;
}
+int ui_but_icon(const uiBut *but)
+{
+ if (!(but->flag & UI_HAS_ICON)) {
+ return ICON_NONE;
+ }
+
+ /* Consecutive icons can be toggle between. */
+ if (but->drawflag & UI_BUT_ICON_REVERSE) {
+ return but->icon - but->iconadd;
+ }
+ else {
+ return but->icon + but->iconadd;
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -206,15 +222,15 @@ bool ui_but_contains_rect(const uiBut *but, const rctf *rect)
return BLI_rctf_isect(&but->rect, rect, NULL);
}
-bool ui_but_contains_point_px(const uiBut *but, const ARegion *ar, int x, int y)
+bool ui_but_contains_point_px(const uiBut *but, const ARegion *region, int x, int y)
{
uiBlock *block = but->block;
- if (!ui_region_contains_point_px(ar, x, y)) {
+ if (!ui_region_contains_point_px(region, x, y)) {
return false;
}
float mx = x, my = y;
- ui_window_to_block_fl(ar, block, &mx, &my);
+ ui_window_to_block_fl(region, block, &mx, &my);
if (but->pie_dir != UI_RADIAL_NONE) {
if (!ui_but_isect_pie_seg(block, but)) {
@@ -228,12 +244,12 @@ bool ui_but_contains_point_px(const uiBut *but, const ARegion *ar, int x, int y)
return true;
}
-bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *ar, const wmEvent *event)
+bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *region, const wmEvent *event)
{
rcti rect;
int x = event->x, y = event->y;
- ui_window_to_block(ar, but->block, &x, &y);
+ ui_window_to_block(region, but->block, &x, &y);
BLI_rcti_rctf_copy(&rect, &but->rect);
@@ -253,16 +269,16 @@ bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *ar, const wmEvent
}
/* x and y are only used in case event is NULL... */
-uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit)
+uiBut *ui_but_find_mouse_over_ex(ARegion *region, const int x, const int y, const bool labeledit)
{
uiBut *butover = NULL;
- if (!ui_region_contains_point_px(ar, x, y)) {
+ if (!ui_region_contains_point_px(region, x, y)) {
return NULL;
}
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
float mx = x, my = y;
- ui_window_to_block_fl(ar, block, &mx, &my);
+ ui_window_to_block_fl(region, block, &mx, &my);
for (uiBut *but = block->buttons.last; but; but = but->prev) {
if (ui_but_is_interactive(but, labeledit)) {
@@ -291,14 +307,14 @@ uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bo
return butover;
}
-uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event)
+uiBut *ui_but_find_mouse_over(ARegion *region, const wmEvent *event)
{
- return ui_but_find_mouse_over_ex(ar, event->x, event->y, event->ctrl != 0);
+ return ui_but_find_mouse_over_ex(region, event->x, event->y, event->ctrl != 0);
}
-uiBut *ui_but_find_rect_over(const struct ARegion *ar, const rcti *rect_px)
+uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px)
{
- if (!ui_region_contains_rect_px(ar, rect_px)) {
+ if (!ui_region_contains_rect_px(region, rect_px)) {
return NULL;
}
@@ -308,9 +324,9 @@ uiBut *ui_but_find_rect_over(const struct ARegion *ar, const rcti *rect_px)
BLI_rctf_rcti_copy(&rect_px_fl, rect_px);
uiBut *butover = NULL;
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
rctf rect_block;
- ui_window_to_block_rctf(ar, block, &rect_block, &rect_px_fl);
+ ui_window_to_block_rctf(region, block, &rect_block, &rect_px_fl);
for (uiBut *but = block->buttons.last; but; but = but->prev) {
if (ui_but_is_interactive(but, labeledit)) {
@@ -334,14 +350,14 @@ uiBut *ui_but_find_rect_over(const struct ARegion *ar, const rcti *rect_px)
return butover;
}
-uiBut *ui_list_find_mouse_over_ex(ARegion *ar, int x, int y)
+uiBut *ui_list_find_mouse_over_ex(ARegion *region, int x, int y)
{
- if (!ui_region_contains_point_px(ar, x, y)) {
+ if (!ui_region_contains_point_px(region, x, y)) {
return NULL;
}
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
float mx = x, my = y;
- ui_window_to_block_fl(ar, block, &mx, &my);
+ ui_window_to_block_fl(region, block, &mx, &my);
for (uiBut *but = block->buttons.last; but; but = but->prev) {
if (but->type == UI_BTYPE_LISTBOX && ui_but_contains_pt(but, mx, my)) {
return but;
@@ -352,9 +368,9 @@ uiBut *ui_list_find_mouse_over_ex(ARegion *ar, int x, int y)
return NULL;
}
-uiBut *ui_list_find_mouse_over(ARegion *ar, const wmEvent *event)
+uiBut *ui_list_find_mouse_over(ARegion *region, const wmEvent *event)
{
- return ui_list_find_mouse_over_ex(ar, event->x, event->y);
+ return ui_list_find_mouse_over_ex(region, event->x, event->y);
}
/** \} */
@@ -505,13 +521,47 @@ bool UI_block_can_add_separator(const uiBlock *block)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Block (#uiBlock) Spatial
+ * \{ */
+
+uiBlock *ui_block_find_mouse_over_ex(const ARegion *region,
+ const int x,
+ const int y,
+ bool only_clip)
+{
+ if (!ui_region_contains_point_px(region, x, y)) {
+ return NULL;
+ }
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
+ if (only_clip) {
+ if ((block->flag & UI_BLOCK_CLIP_EVENTS) == 0) {
+ continue;
+ }
+ }
+ float mx = x, my = y;
+ ui_window_to_block_fl(region, block, &mx, &my);
+ if (BLI_rctf_isect_pt(&block->rect, mx, my)) {
+ return block;
+ }
+ }
+ return NULL;
+}
+
+uiBlock *ui_block_find_mouse_over(const ARegion *region, const wmEvent *event, bool only_clip)
+{
+ return ui_block_find_mouse_over_ex(region, event->x, event->y, only_clip);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Region (#ARegion) State
* \{ */
-uiBut *ui_region_find_active_but(ARegion *ar)
+uiBut *ui_region_find_active_but(ARegion *region)
{
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
- for (uiBut *but = block->buttons.first; but; but = but->next) {
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (but->active) {
return but;
}
@@ -521,10 +571,10 @@ uiBut *ui_region_find_active_but(ARegion *ar)
return NULL;
}
-uiBut *ui_region_find_first_but_test_flag(ARegion *ar, int flag_include, int flag_exclude)
+uiBut *ui_region_find_first_but_test_flag(ARegion *region, int flag_include, int flag_exclude)
{
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
- for (uiBut *but = block->buttons.first; but; but = but->next) {
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (((but->flag & flag_include) == flag_include) && ((but->flag & flag_exclude) == 0)) {
return but;
}
@@ -540,10 +590,10 @@ uiBut *ui_region_find_first_but_test_flag(ARegion *ar, int flag_include, int fla
/** \name Region (#ARegion) Spatial
* \{ */
-bool ui_region_contains_point_px(const ARegion *ar, int x, int y)
+bool ui_region_contains_point_px(const ARegion *region, int x, int y)
{
rcti winrct;
- ui_region_winrct_get_no_margin(ar, &winrct);
+ ui_region_winrct_get_no_margin(region, &winrct);
if (!BLI_rcti_isect_pt(&winrct, x, y)) {
return false;
}
@@ -553,13 +603,13 @@ bool ui_region_contains_point_px(const ARegion *ar, int x, int y)
* even when they are not visible, so we need to make a copy of the mask to
* use to check
*/
- if (ar->v2d.mask.xmin != ar->v2d.mask.xmax) {
- const View2D *v2d = &ar->v2d;
+ if (region->v2d.mask.xmin != region->v2d.mask.xmax) {
+ const View2D *v2d = &region->v2d;
int mx = x, my = y;
- ui_window_to_region(ar, &mx, &my);
+ ui_window_to_region(region, &mx, &my);
if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) ||
- UI_view2d_mouse_in_scrollers(ar, &ar->v2d, x, y)) {
+ UI_view2d_mouse_in_scrollers(region, &region->v2d, x, y)) {
return false;
}
}
@@ -567,21 +617,21 @@ bool ui_region_contains_point_px(const ARegion *ar, int x, int y)
return true;
}
-bool ui_region_contains_rect_px(const ARegion *ar, const rcti *rect_px)
+bool ui_region_contains_rect_px(const ARegion *region, const rcti *rect_px)
{
rcti winrct;
- ui_region_winrct_get_no_margin(ar, &winrct);
+ ui_region_winrct_get_no_margin(region, &winrct);
if (!BLI_rcti_isect(&winrct, rect_px, NULL)) {
return false;
}
/* See comment in 'ui_region_contains_point_px' */
- if (ar->v2d.mask.xmin != ar->v2d.mask.xmax) {
- const View2D *v2d = &ar->v2d;
+ if (region->v2d.mask.xmin != region->v2d.mask.xmax) {
+ const View2D *v2d = &region->v2d;
rcti rect_region;
- ui_window_to_region_rcti(ar, &rect_region, rect_px);
+ ui_window_to_region_rcti(region, &rect_region, rect_px);
if (!BLI_rcti_isect(&v2d->mask, &rect_region, NULL) ||
- UI_view2d_rect_in_scrollers(ar, &ar->v2d, rect_px)) {
+ UI_view2d_rect_in_scrollers(region, &region->v2d, rect_px)) {
return false;
}
}
@@ -598,13 +648,13 @@ bool ui_region_contains_rect_px(const ARegion *ar, const rcti *rect_px)
/** Check if the cursor is over any popups. */
ARegion *ui_screen_region_find_mouse_over_ex(bScreen *screen, int x, int y)
{
- for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
+ LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
rcti winrct;
- ui_region_winrct_get_no_margin(ar, &winrct);
+ ui_region_winrct_get_no_margin(region, &winrct);
if (BLI_rcti_isect_pt(&winrct, x, y)) {
- return ar;
+ return region;
}
}
return NULL;
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c
index 917c35f0135..f9873f8b96f 100644
--- a/source/blender/editors/interface/interface_region_color_picker.c
+++ b/source/blender/editors/interface/interface_region_color_picker.c
@@ -23,19 +23,19 @@
* Color Picker Region & Color Utils
*/
+#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
-#include "BLI_utildefines.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -332,7 +332,7 @@ static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormode)
{
/* tag buttons */
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
if ((bt->func == ui_colorpicker_rna_cb) && (bt->type == UI_BTYPE_NUM_SLIDER) &&
(bt->rnaindex != 3)) {
/* RGB sliders (color circle and alpha are always shown) */
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c
index d32cd5c17e2..34ac58c1dca 100644
--- a/source/blender/editors/interface/interface_region_hud.c
+++ b/source/blender/editors/interface/interface_region_hud.c
@@ -30,9 +30,9 @@
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
-#include "BLI_string.h"
-#include "BLI_rect.h"
#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -51,8 +51,8 @@
#include "ED_screen.h"
#include "ED_undo.h"
-#include "interface_intern.h"
#include "GPU_framebuffer.h"
+#include "interface_intern.h"
/* -------------------------------------------------------------------- */
/** \name Utilities
@@ -74,25 +74,25 @@ static bool last_redo_poll(const bContext *C, short region_type)
* operator call. Otherwise we would be polling the operator with the
* wrong context.
*/
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar_op = (region_type != -1) ? BKE_area_find_region_type(sa, region_type) : NULL;
- ARegion *ar_prev = CTX_wm_region(C);
- CTX_wm_region_set((bContext *)C, ar_op);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region_op = (region_type != -1) ? BKE_area_find_region_type(area, region_type) : NULL;
+ ARegion *region_prev = CTX_wm_region(C);
+ CTX_wm_region_set((bContext *)C, region_op);
if (WM_operator_repeat_check(C, op) && WM_operator_check_ui_empty(op->type) == false) {
success = WM_operator_poll((bContext *)C, op->type);
}
- CTX_wm_region_set((bContext *)C, ar_prev);
+ CTX_wm_region_set((bContext *)C, region_prev);
}
return success;
}
-static void hud_region_hide(ARegion *ar)
+static void hud_region_hide(ARegion *region)
{
- ar->flag |= RGN_FLAG_HIDDEN;
+ region->flag |= RGN_FLAG_HIDDEN;
/* Avoids setting 'AREA_FLAG_REGION_SIZE_UPDATE'
* since other regions don't depend on this. */
- BLI_rcti_init(&ar->winrct, 0, 0, 0, 0);
+ BLI_rcti_init(&region->winrct, 0, 0, 0, 0);
}
/** \} */
@@ -103,10 +103,10 @@ static void hud_region_hide(ARegion *ar)
static bool hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD);
- if (ar != NULL) {
- struct HudRegionData *hrd = ar->regiondata;
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HUD);
+ if (region != NULL) {
+ struct HudRegionData *hrd = region->regiondata;
if (hrd != NULL) {
return last_redo_poll(C, hrd->regionid);
}
@@ -114,22 +114,22 @@ static bool hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt
return false;
}
-static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *pa)
+static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *panel)
{
wmOperator *op = WM_operator_last_redo(C);
- BLI_strncpy(pa->drawname, WM_operatortype_name(op->type, op->ptr), sizeof(pa->drawname));
+ BLI_strncpy(panel->drawname, WM_operatortype_name(op->type, op->ptr), sizeof(panel->drawname));
}
-static void hud_panel_operator_redo_draw(const bContext *C, Panel *pa)
+static void hud_panel_operator_redo_draw(const bContext *C, Panel *panel)
{
wmOperator *op = WM_operator_last_redo(C);
if (op == NULL) {
return;
}
if (!WM_operator_check_ui_enabled(C, op->type->name)) {
- uiLayoutSetEnabled(pa->layout, false);
+ uiLayoutSetEnabled(panel->layout, false);
}
- uiLayout *col = uiLayoutColumn(pa->layout, false);
+ uiLayout *col = uiLayoutColumn(panel->layout, false);
uiTemplateOperatorRedoProperties(col, C);
}
@@ -156,76 +156,76 @@ static void hud_panels_register(ARegionType *art, int space_type, int region_typ
/** \name Callbacks for Floating Region
* \{ */
-static void hud_region_init(wmWindowManager *wm, ARegion *ar)
+static void hud_region_init(wmWindowManager *wm, ARegion *region)
{
- ED_region_panels_init(wm, ar);
- UI_region_handlers_add(&ar->handlers);
- ar->flag |= RGN_FLAG_TEMP_REGIONDATA;
+ ED_region_panels_init(wm, region);
+ UI_region_handlers_add(&region->handlers);
+ region->flag |= RGN_FLAG_TEMP_REGIONDATA;
}
-static void hud_region_free(ARegion *ar)
+static void hud_region_free(ARegion *region)
{
- MEM_SAFE_FREE(ar->regiondata);
+ MEM_SAFE_FREE(region->regiondata);
}
-static void hud_region_layout(const bContext *C, ARegion *ar)
+static void hud_region_layout(const bContext *C, ARegion *region)
{
- struct HudRegionData *hrd = ar->regiondata;
+ struct HudRegionData *hrd = region->regiondata;
if (hrd == NULL || !last_redo_poll(C, hrd->regionid)) {
- ED_region_tag_redraw(ar);
- hud_region_hide(ar);
+ ED_region_tag_redraw(region);
+ hud_region_hide(region);
return;
}
- int size_y = ar->sizey;
+ int size_y = region->sizey;
- ED_region_panels_layout(C, ar);
+ ED_region_panels_layout(C, region);
- if (ar->panels.first && (ar->sizey != size_y)) {
- int winx_new = UI_DPI_FAC * (ar->sizex + 0.5f);
- int winy_new = UI_DPI_FAC * (ar->sizey + 0.5f);
- View2D *v2d = &ar->v2d;
+ if (region->panels.first && (region->sizey != size_y)) {
+ int winx_new = UI_DPI_FAC * (region->sizex + 0.5f);
+ int winy_new = UI_DPI_FAC * (region->sizey + 0.5f);
+ View2D *v2d = &region->v2d;
- if (ar->flag & RGN_FLAG_SIZE_CLAMP_X) {
- CLAMP_MAX(winx_new, ar->winx);
+ if (region->flag & RGN_FLAG_SIZE_CLAMP_X) {
+ CLAMP_MAX(winx_new, region->winx);
}
- if (ar->flag & RGN_FLAG_SIZE_CLAMP_Y) {
- CLAMP_MAX(winy_new, ar->winy);
+ if (region->flag & RGN_FLAG_SIZE_CLAMP_Y) {
+ CLAMP_MAX(winy_new, region->winy);
}
- ar->winx = winx_new;
- ar->winy = winy_new;
+ region->winx = winx_new;
+ region->winy = winy_new;
- ar->winrct.xmax = (ar->winrct.xmin + ar->winx) - 1;
- ar->winrct.ymax = (ar->winrct.ymin + ar->winy) - 1;
+ region->winrct.xmax = (region->winrct.xmin + region->winx) - 1;
+ region->winrct.ymax = (region->winrct.ymin + region->winy) - 1;
- UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
+ UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_PANELS_UI, region->winx, region->winy);
/* Weak, but needed to avoid glitches, especially with hi-dpi
* (where resizing the view glitches often).
* Fortunately this only happens occasionally. */
- ED_region_panels_layout(C, ar);
+ ED_region_panels_layout(C, region);
}
/* restore view matrix */
UI_view2d_view_restore(C);
}
-static void hud_region_draw(const bContext *C, ARegion *ar)
+static void hud_region_draw(const bContext *C, ARegion *region)
{
- UI_view2d_view_ortho(&ar->v2d);
- wmOrtho2_region_pixelspace(ar);
+ UI_view2d_view_ortho(&region->v2d);
+ wmOrtho2_region_pixelspace(region);
GPU_clear_color(0, 0, 0, 0.0f);
GPU_clear(GPU_COLOR_BIT);
- if ((ar->flag & RGN_FLAG_HIDDEN) == 0) {
+ if ((region->flag & RGN_FLAG_HIDDEN) == 0) {
ui_draw_menu_back(NULL,
NULL,
&(rcti){
- .xmax = ar->winx,
- .ymax = ar->winy,
+ .xmax = region->winx,
+ .ymax = region->winy,
});
- ED_region_panels_draw(C, ar);
+ ED_region_panels_draw(C, region);
}
}
@@ -250,44 +250,44 @@ ARegionType *ED_area_type_hud(int space_type)
return art;
}
-static ARegion *hud_region_add(ScrArea *sa)
+static ARegion *hud_region_add(ScrArea *area)
{
- ARegion *ar = MEM_callocN(sizeof(ARegion), "area region");
- ARegion *ar_win = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar_win) {
- BLI_insertlinkbefore(&sa->regionbase, ar_win, ar);
+ ARegion *region = MEM_callocN(sizeof(ARegion), "area region");
+ ARegion *region_win = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+ if (region_win) {
+ BLI_insertlinkbefore(&area->regionbase, region_win, region);
}
else {
- BLI_addtail(&sa->regionbase, ar);
+ BLI_addtail(&area->regionbase, region);
}
- ar->regiontype = RGN_TYPE_HUD;
- ar->alignment = RGN_ALIGN_FLOAT;
- ar->overlap = true;
- ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+ region->regiontype = RGN_TYPE_HUD;
+ region->alignment = RGN_ALIGN_FLOAT;
+ region->overlap = true;
+ region->flag |= RGN_FLAG_DYNAMIC_SIZE;
- if (ar_win) {
+ if (region_win) {
float x, y;
- UI_view2d_scroller_size_get(&ar_win->v2d, &x, &y);
- ar->runtime.offset_x = x;
- ar->runtime.offset_y = y;
+ UI_view2d_scroller_size_get(&region_win->v2d, &x, &y);
+ region->runtime.offset_x = x;
+ region->runtime.offset_y = y;
}
- return ar;
+ return region;
}
-void ED_area_type_hud_clear(wmWindowManager *wm, ScrArea *sa_keep)
+void ED_area_type_hud_clear(wmWindowManager *wm, ScrArea *area_keep)
{
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
bScreen *screen = WM_window_get_active_screen(win);
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa != sa_keep) {
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_HUD) {
- if ((ar->flag & RGN_FLAG_HIDDEN) == 0) {
- hud_region_hide(ar);
- ED_region_tag_redraw(ar);
- ED_area_tag_redraw(sa);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area != area_keep) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->regiontype == RGN_TYPE_HUD) {
+ if ((region->flag & RGN_FLAG_HIDDEN) == 0) {
+ hud_region_hide(region);
+ ED_region_tag_redraw(region);
+ ED_area_tag_redraw(area);
}
}
}
@@ -296,62 +296,62 @@ void ED_area_type_hud_clear(wmWindowManager *wm, ScrArea *sa_keep)
}
}
-void ED_area_type_hud_ensure(bContext *C, ScrArea *sa)
+void ED_area_type_hud_ensure(bContext *C, ScrArea *area)
{
wmWindowManager *wm = CTX_wm_manager(C);
- ED_area_type_hud_clear(wm, sa);
+ ED_area_type_hud_clear(wm, area);
- ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_HUD);
+ ARegionType *art = BKE_regiontype_from_id(area->type, RGN_TYPE_HUD);
if (art == NULL) {
return;
}
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD);
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HUD);
- if (ar && (ar->flag & RGN_FLAG_HIDDEN_BY_USER)) {
+ if (region && (region->flag & RGN_FLAG_HIDDEN_BY_USER)) {
/* The region is intentionally hidden by the user, don't show it. */
- hud_region_hide(ar);
+ hud_region_hide(region);
return;
}
bool init = false;
- bool was_hidden = ar == NULL || ar->visible == false;
- ARegion *ar_op = CTX_wm_region(C);
- BLI_assert((ar_op == NULL) || (ar_op->regiontype != RGN_TYPE_HUD));
- if (!last_redo_poll(C, ar_op ? ar_op->regiontype : -1)) {
- if (ar) {
- ED_region_tag_redraw(ar);
- hud_region_hide(ar);
+ bool was_hidden = region == NULL || region->visible == false;
+ ARegion *region_op = CTX_wm_region(C);
+ BLI_assert((region_op == NULL) || (region_op->regiontype != RGN_TYPE_HUD));
+ if (!last_redo_poll(C, region_op ? region_op->regiontype : -1)) {
+ if (region) {
+ ED_region_tag_redraw(region);
+ hud_region_hide(region);
}
return;
}
- if (ar == NULL) {
+ if (region == NULL) {
init = true;
- ar = hud_region_add(sa);
- ar->type = art;
+ region = hud_region_add(area);
+ region->type = art;
}
/* Let 'ED_area_update_region_sizes' do the work of placing the region.
- * Otherwise we could set the 'ar->winrct' & 'ar->winx/winy' here. */
+ * Otherwise we could set the 'region->winrct' & 'region->winx/winy' here. */
if (init) {
- sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
}
else {
- if (ar->flag & RGN_FLAG_HIDDEN) {
- sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ if (region->flag & RGN_FLAG_HIDDEN) {
+ area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
}
- ar->flag &= ~RGN_FLAG_HIDDEN;
+ region->flag &= ~RGN_FLAG_HIDDEN;
}
{
- struct HudRegionData *hrd = ar->regiondata;
+ struct HudRegionData *hrd = region->regiondata;
if (hrd == NULL) {
hrd = MEM_callocN(sizeof(*hrd), __func__);
- ar->regiondata = hrd;
+ region->regiondata = hrd;
}
- if (ar_op) {
- hrd->regionid = ar_op->regiontype;
+ if (region_op) {
+ hrd->regionid = region_op->regiontype;
}
else {
hrd->regionid = -1;
@@ -361,40 +361,40 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *sa)
if (init) {
/* This is needed or 'winrct' will be invalid. */
wmWindow *win = CTX_wm_window(C);
- ED_area_update_region_sizes(wm, win, sa);
+ ED_area_update_region_sizes(wm, win, area);
}
- ED_region_floating_initialize(ar);
- ED_region_tag_redraw(ar);
+ ED_region_floating_initialize(region);
+ ED_region_tag_redraw(region);
/* Reset zoom level (not well supported). */
- ar->v2d.cur = ar->v2d.tot = (rctf){
- .xmax = ar->winx,
- .ymax = ar->winy,
+ region->v2d.cur = region->v2d.tot = (rctf){
+ .xmax = region->winx,
+ .ymax = region->winy,
};
- ar->v2d.minzoom = 1.0f;
- ar->v2d.maxzoom = 1.0f;
+ region->v2d.minzoom = 1.0f;
+ region->v2d.maxzoom = 1.0f;
- ar->visible = !(ar->flag & RGN_FLAG_HIDDEN);
+ region->visible = !(region->flag & RGN_FLAG_HIDDEN);
/* We shouldn't need to do this every time :S */
/* XXX, this is evil! - it also makes the menu show on first draw. :( */
- if (ar->visible) {
- ARegion *ar_prev = CTX_wm_region(C);
- CTX_wm_region_set((bContext *)C, ar);
- hud_region_layout(C, ar);
+ if (region->visible) {
+ ARegion *region_prev = CTX_wm_region(C);
+ CTX_wm_region_set((bContext *)C, region);
+ hud_region_layout(C, region);
if (was_hidden) {
- ar->winx = ar->v2d.winx;
- ar->winy = ar->v2d.winy;
- ar->v2d.cur = ar->v2d.tot = (rctf){
- .xmax = ar->winx,
- .ymax = ar->winy,
+ region->winx = region->v2d.winx;
+ region->winy = region->v2d.winy;
+ region->v2d.cur = region->v2d.tot = (rctf){
+ .xmax = region->winx,
+ .ymax = region->winy,
};
}
- CTX_wm_region_set((bContext *)C, ar_prev);
+ CTX_wm_region_set((bContext *)C, region_prev);
}
- ar->visible = !((ar->flag & RGN_FLAG_HIDDEN) || (ar->flag & RGN_FLAG_TOO_SMALL));
+ region->visible = !((region->flag & RGN_FLAG_HIDDEN) || (region->flag & RGN_FLAG_TOO_SMALL));
}
/** \} */
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index 330a9d48ff4..1371c7524ae 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -23,10 +23,10 @@
* Pie Menu Region
*/
+#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
@@ -104,13 +104,12 @@ static float ui_pie_menu_title_width(const char *name, int icon)
uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, const wmEvent *event)
{
- uiStyle *style;
+ const uiStyle *style = UI_style_get_dpi();
uiPieMenu *pie;
short event_type;
wmWindow *win = CTX_wm_window(C);
- style = UI_style_get_dpi();
pie = MEM_callocN(sizeof(*pie), "pie menu");
pie->block_radial = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
@@ -213,7 +212,7 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
menu->towardstime = PIL_check_seconds_timer();
UI_popup_handlers_add(C, &window->modalhandlers, menu, WM_HANDLER_ACCEPT_DBL_CLICK);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(window);
MEM_freeN(pie);
}
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index 560c6146afe..3e34b7f3f8a 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -23,26 +23,26 @@
* PopUp Menu Region
*/
+#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
-#include "BLI_string.h"
+#include "BLI_ghash.h"
#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -88,11 +88,11 @@ int ui_but_menu_step(uiBut *but, int direction)
return 0;
}
-static uint ui_popup_string_hash(const char *str)
+static uint ui_popup_string_hash(const char *str, const bool use_sep)
{
/* sometimes button contains hotkey, sometimes not, strip for proper compare */
int hash;
- const char *delimit = strrchr(str, UI_SEP_CHAR);
+ const char *delimit = use_sep ? strrchr(str, UI_SEP_CHAR) : NULL;
if (delimit) {
hash = BLI_ghashutil_strhash_n(str, delimit - str);
@@ -126,13 +126,13 @@ static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but)
if (but) {
/* set */
- mem[hash_mod] = ui_popup_string_hash(but->str);
+ mem[hash_mod] = ui_popup_string_hash(but->str, but->flag & UI_BUT_HAS_SEP_CHAR);
return NULL;
}
else {
/* get */
for (but = block->buttons.first; but; but = but->next) {
- if (ui_popup_string_hash(but->str) == mem[hash_mod]) {
+ if (mem[hash_mod] == ui_popup_string_hash(but->str, but->flag & UI_BUT_HAS_SEP_CHAR)) {
return but;
}
}
@@ -276,17 +276,17 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
else {
/* for a header menu we set the direction automatic */
if (!pup->slideout && flip) {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- if (sa && ar) {
- if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
- if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_header_alignment(sa)) == RGN_ALIGN_BOTTOM) {
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ if (area && region) {
+ if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_header_alignment(area)) == RGN_ALIGN_BOTTOM) {
UI_block_direction_set(block, UI_DIR_UP);
UI_block_order_flip(block);
}
}
- if (ar->regiontype == RGN_TYPE_FOOTER) {
- if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_footer_alignment(sa)) == RGN_ALIGN_BOTTOM) {
+ if (region->regiontype == RGN_TYPE_FOOTER) {
+ if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_footer_alignment(area)) == RGN_ALIGN_BOTTOM) {
UI_block_direction_set(block, UI_DIR_UP);
UI_block_order_flip(block);
}
@@ -310,7 +310,7 @@ uiPopupBlockHandle *ui_popup_menu_create(
bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
{
wmWindow *window = CTX_wm_window(C);
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
uiPopupBlockHandle *handle;
uiPopupMenu *pup;
@@ -357,7 +357,7 @@ uiPopupBlockHandle *ui_popup_menu_create(
handle->popup = true;
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(window);
}
MEM_freeN(pup);
@@ -380,7 +380,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
const char *block_name,
int icon)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
uiPopupMenu *pup = MEM_callocN(sizeof(uiPopupMenu), "popup menu");
uiBut *but;
@@ -467,7 +467,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
menu->popup = true;
UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(window);
MEM_freeN(pup);
}
@@ -581,25 +581,22 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
/** \name Popup Block API
* \{ */
-void UI_popup_block_invoke_ex(bContext *C,
- uiBlockCreateFunc func,
- void *arg,
- void (*arg_free)(void *arg),
- const char *opname,
- int opcontext)
+void UI_popup_block_invoke_ex(
+ bContext *C, uiBlockCreateFunc func, void *arg, void (*arg_free)(void *arg), bool can_refresh)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, arg_free);
handle->popup = true;
- handle->can_refresh = true;
- handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
- handle->opcontext = opcontext;
+
+ /* It can be useful to disable refresh (even though it will work)
+ * as this exists text fields which can be disruptive if refresh isn't needed. */
+ handle->can_refresh = can_refresh;
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(window);
}
void UI_popup_block_invoke(bContext *C,
@@ -607,7 +604,7 @@ void UI_popup_block_invoke(bContext *C,
void *arg,
void (*arg_free)(void *arg))
{
- UI_popup_block_invoke_ex(C, func, arg, arg_free, NULL, WM_OP_INVOKE_DEFAULT);
+ UI_popup_block_invoke_ex(C, func, arg, arg_free, true);
}
void UI_popup_block_ex(bContext *C,
@@ -633,7 +630,7 @@ void UI_popup_block_ex(bContext *C,
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(window);
}
#if 0 /* UNUSED */
@@ -669,21 +666,17 @@ void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
/* In the case we have nested popups,
* closing one may need to redraw another, see: T48874 */
- for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
- ED_region_tag_refresh_ui(ar);
+ LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
+ ED_region_tag_refresh_ui(region);
}
}
}
}
-bool UI_popup_block_name_exists(bContext *C, const char *name)
+bool UI_popup_block_name_exists(const bScreen *screen, const char *name)
{
- bScreen *sc = CTX_wm_screen(C);
- uiBlock *block;
- ARegion *ar;
-
- for (ar = sc->regionbase.first; ar; ar = ar->next) {
- for (block = ar->uiblocks.first; block; block = block->next) {
+ LISTBASE_FOREACH (const ARegion *, region, &screen->regionbase) {
+ LISTBASE_FOREACH (const uiBlock *, block, &region->uiblocks) {
if (STREQ(block->name, name)) {
return true;
}
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index 2042c15ed96..0ad7e570e80 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -46,13 +46,13 @@
#include "BLI_listbase.h"
+#include "BLI_math_vector.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
-#include "BLI_math_vector.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "ED_screen.h"
@@ -94,7 +94,7 @@ static void ui_popover_create_block(bContext *C, uiPopover *pup, int opcontext)
{
BLI_assert(pup->ui_size_x != 0);
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
UI_block_flag_enable(pup->block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
@@ -104,15 +104,8 @@ static void ui_popover_create_block(bContext *C, uiPopover *pup, int opcontext)
}
#endif
- pup->layout = UI_block_layout(pup->block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- 0,
- 0,
- pup->ui_size_x,
- 0,
- UI_MENU_PADDING,
- style);
+ pup->layout = UI_block_layout(
+ pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, pup->ui_size_x, 0, 0, style);
uiLayoutSetOperatorContext(pup->layout, opcontext);
@@ -178,23 +171,23 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
}
if (!slideout) {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
- if (ar && ar->panels.first) {
+ if (region && region->panels.first) {
/* For regions with panels, prefer to open to top so we can
* see the values of the buttons below changing. */
UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
}
/* Prefer popover from header to be positioned into the editor. */
- else if (sa && ar) {
- if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
- if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_header_alignment(sa)) == RGN_ALIGN_BOTTOM) {
+ else if (area && region) {
+ if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_header_alignment(area)) == RGN_ALIGN_BOTTOM) {
UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
}
}
- if (ar->regiontype == RGN_TYPE_FOOTER) {
- if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_footer_alignment(sa)) == RGN_ALIGN_BOTTOM) {
+ if (region->regiontype == RGN_TYPE_FOOTER) {
+ if (RGN_ALIGN_ENUM_FROM_MASK(ED_area_footer_alignment(area)) == RGN_ALIGN_BOTTOM) {
UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
}
}
@@ -291,7 +284,7 @@ uiPopupBlockHandle *ui_popover_panel_create(
* add a modal handler and pass on events. */
if (!but) {
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(window);
handle->popup = true;
}
@@ -410,7 +403,7 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
/* Add handlers. */
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(window);
handle->popup = true;
/* Re-add so it gets priority. */
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index 867ac652505..2ad7e517c60 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -23,17 +23,17 @@
* PopUp Region (Generic)
*/
+#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
@@ -57,18 +57,18 @@
/**
* Translate any popup regions (so we can drag them).
*/
-void ui_popup_translate(ARegion *ar, const int mdiff[2])
+void ui_popup_translate(ARegion *region, const int mdiff[2])
{
uiBlock *block;
- BLI_rcti_translate(&ar->winrct, UNPACK2(mdiff));
+ BLI_rcti_translate(&region->winrct, UNPACK2(mdiff));
- ED_region_update_rect(ar);
+ ED_region_update_rect(region);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
/* update blocks */
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
uiPopupBlockHandle *handle = block->handle;
/* Make empty, will be initialized on next use, see T60608. */
BLI_rctf_init(&handle->prev_block_rect, 0, 0, 0, 0);
@@ -118,7 +118,7 @@ static void ui_popup_block_position(wmWindow *window,
if (block->buttons.first) {
BLI_rctf_init_minmax(&block->rect);
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
if (block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT) {
bt->rect.xmax += UI_MENU_SUBMENU_PADDING;
}
@@ -294,7 +294,7 @@ static void ui_popup_block_position(wmWindow *window,
}
/* Apply offset, buttons in window coords. */
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
ui_block_to_window_rctf(butregion, but->block, &bt->rect, &bt->rect);
BLI_rctf_translate(&bt->rect, offset_x, offset_y);
@@ -369,19 +369,19 @@ static void ui_popup_block_position(wmWindow *window,
/** \name Menu Block Creation
* \{ */
-static void ui_block_region_refresh(const bContext *C, ARegion *ar)
+static void ui_block_region_refresh(const bContext *C, ARegion *region)
{
ScrArea *ctx_area = CTX_wm_area(C);
ARegion *ctx_region = CTX_wm_region(C);
uiBlock *block;
- if (ar->do_draw & RGN_REFRESH_UI) {
+ if (region->do_draw & RGN_REFRESH_UI) {
ScrArea *handle_ctx_area;
ARegion *handle_ctx_region;
uiBlock *block_next;
- ar->do_draw &= ~RGN_REFRESH_UI;
- for (block = ar->uiblocks.first; block; block = block_next) {
+ region->do_draw &= ~RGN_REFRESH_UI;
+ for (block = region->uiblocks.first; block; block = block_next) {
block_next = block->next;
uiPopupBlockHandle *handle = block->handle;
@@ -407,11 +407,11 @@ static void ui_block_region_refresh(const bContext *C, ARegion *ar)
CTX_wm_region_set((bContext *)C, ctx_region);
}
-static void ui_block_region_draw(const bContext *C, ARegion *ar)
+static void ui_block_region_draw(const bContext *C, ARegion *region)
{
uiBlock *block;
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = region->uiblocks.first; block; block = block->next) {
UI_block_draw(C, block);
}
}
@@ -420,8 +420,8 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
* Use to refresh centered popups on screen resizing (for splash).
*/
static void ui_block_region_popup_window_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -430,7 +430,7 @@ static void ui_block_region_popup_window_listener(wmWindow *UNUSED(win),
switch (wmn->action) {
case NA_EDITED: {
/* window resize */
- ED_region_tag_refresh_ui(ar);
+ ED_region_tag_refresh_ui(region);
break;
}
}
@@ -525,39 +525,37 @@ void ui_popup_block_scrolltest(uiBlock *block)
static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle)
{
wmWindow *ctx_win = CTX_wm_window(C);
- ScrArea *ctx_sa = CTX_wm_area(C);
- ARegion *ctx_ar = CTX_wm_region(C);
+ ScrArea *ctx_area = CTX_wm_area(C);
+ ARegion *ctx_region = CTX_wm_region(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = ctx_win;
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
/* There may actually be a different window active than the one showing the popup, so lookup real
* one. */
- if (BLI_findindex(&sc->regionbase, handle->region) == -1) {
+ if (BLI_findindex(&screen->regionbase, handle->region) == -1) {
for (win = wm->windows.first; win; win = win->next) {
- sc = WM_window_get_active_screen(win);
- if (BLI_findindex(&sc->regionbase, handle->region) != -1) {
+ screen = WM_window_get_active_screen(win);
+ if (BLI_findindex(&screen->regionbase, handle->region) != -1) {
break;
}
}
}
- BLI_assert(win && sc);
+ BLI_assert(win && screen);
CTX_wm_window_set(C, win);
- ui_region_temp_remove(C, sc, handle->region);
+ ui_region_temp_remove(C, screen, handle->region);
/* Reset context (area and region were NULL'ed when chaning context window). */
CTX_wm_window_set(C, ctx_win);
- CTX_wm_area_set(C, ctx_sa);
- CTX_wm_region_set(C, ctx_ar);
+ CTX_wm_area_set(C, ctx_area);
+ CTX_wm_region_set(C, ctx_region);
/* reset to region cursor (only if there's not another menu open) */
- if (BLI_listbase_is_empty(&sc->regionbase)) {
- ED_region_cursor_set(win, ctx_sa, ctx_ar);
- /* in case cursor needs to be changed again */
- WM_event_add_mousemove(C);
+ if (BLI_listbase_is_empty(&screen->regionbase)) {
+ win->tag_cursor_refresh = true;
}
if (handle->scrolltimer) {
@@ -575,13 +573,13 @@ uiBlock *ui_popup_block_refresh(bContext *C,
{
const int margin = UI_POPUP_MARGIN;
wmWindow *window = CTX_wm_window(C);
- ARegion *ar = handle->region;
+ ARegion *region = handle->region;
uiBlockCreateFunc create_func = handle->popup_create_vars.create_func;
uiBlockHandleCreateFunc handle_create_func = handle->popup_create_vars.handle_create_func;
void *arg = handle->popup_create_vars.arg;
- uiBlock *block_old = ar->uiblocks.first;
+ uiBlock *block_old = region->uiblocks.first;
uiBlock *block;
handle->refresh = (block_old != NULL);
@@ -594,7 +592,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
/* create ui block */
if (create_func) {
- block = create_func(C, ar, arg);
+ block = create_func(C, region, arg);
}
else {
block = handle_create_func(C, handle, arg);
@@ -617,7 +615,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
block->handle = handle;
}
- ar->regiondata = handle;
+ region->regiondata = handle;
/* set UI_BLOCK_NUMSELECT before UI_block_end() so we get alphanumeric keys assigned */
if (but == NULL) {
@@ -691,16 +689,16 @@ uiBlock *ui_popup_block_refresh(bContext *C,
}
}
- ar->winrct.xmin = 0;
- ar->winrct.xmax = winx;
- ar->winrct.ymin = 0;
- ar->winrct.ymax = winy;
+ region->winrct.xmin = 0;
+ region->winrct.xmax = winx;
+ region->winrct.ymin = 0;
+ region->winrct.ymax = winy;
ui_block_calc_pie_segment(block, block->pie_data.pie_center_init);
/* lastly set the buttons at the center of the pie menu, ready for animation */
if (U.pie_animation_timeout > 0) {
- for (uiBut *but_iter = block->buttons.first; but_iter; but_iter = but_iter->next) {
+ LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) {
if (but_iter->pie_dir != UI_RADIAL_NONE) {
BLI_rctf_recenter(&but_iter->rect, UNPACK2(block->pie_data.pie_center_spawned));
}
@@ -708,6 +706,15 @@ uiBlock *ui_popup_block_refresh(bContext *C,
}
}
else {
+ /* Add an offset to draw the popover arrow. */
+ if ((block->flag & UI_BLOCK_POPOVER) && ELEM(block->direction, UI_DIR_UP, UI_DIR_DOWN)) {
+ /* Keep sync with 'ui_draw_popover_back_impl'. */
+ const float unit_size = U.widget_unit / block->aspect;
+ const float unit_half = unit_size * (block->direction == UI_DIR_DOWN ? 0.5 : -0.5);
+
+ UI_block_translate(block, 0, -unit_half);
+ }
+
/* clip block with window boundary */
ui_popup_block_clip(window, block);
@@ -726,16 +733,16 @@ uiBlock *ui_popup_block_refresh(bContext *C,
/* the block and buttons were positioned in window space as in 2.4x, now
* these menu blocks are regions so we bring it back to region space.
* additionally we add some padding for the menu shadow or rounded menus */
- ar->winrct.xmin = block->rect.xmin - margin;
- ar->winrct.xmax = block->rect.xmax + margin;
- ar->winrct.ymin = block->rect.ymin - margin;
- ar->winrct.ymax = block->rect.ymax + UI_POPUP_MENU_TOP;
+ region->winrct.xmin = block->rect.xmin - margin;
+ region->winrct.xmax = block->rect.xmax + margin;
+ region->winrct.ymin = block->rect.ymin - margin;
+ region->winrct.ymax = block->rect.ymax + UI_POPUP_MENU_TOP;
- UI_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+ UI_block_translate(block, -region->winrct.xmin, -region->winrct.ymin);
/* apply scroll offset */
if (handle->scrolloffset != 0.0f) {
- for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
bt->rect.ymin += handle->scrolloffset;
bt->rect.ymax += handle->scrolloffset;
}
@@ -745,22 +752,22 @@ uiBlock *ui_popup_block_refresh(bContext *C,
if (block_old) {
block->oldblock = block_old;
UI_block_update_from_old(C, block);
- UI_blocklist_free_inactive(C, &ar->uiblocks);
+ UI_blocklist_free_inactive(C, &region->uiblocks);
}
/* checks which buttons are visible, sets flags to prevent draw (do after region init) */
ui_popup_block_scrolltest(block);
/* adds subwindow */
- ED_region_floating_initialize(ar);
+ ED_region_floating_initialize(region);
/* get winmat now that we actually have the subwindow */
- wmGetProjectionMatrix(block->winmat, &ar->winrct);
+ wmGetProjectionMatrix(block->winmat, &region->winrct);
/* notify change and redraw */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
- ED_region_update_rect(ar);
+ ED_region_update_rect(region);
#ifdef DEBUG
window->eventstate = event_back;
@@ -780,7 +787,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
wmWindow *window = CTX_wm_window(C);
uiBut *activebut = UI_context_active_but_get(C);
static ARegionType type;
- ARegion *ar;
+ ARegion *region;
uiBlock *block;
uiPopupBlockHandle *handle;
@@ -811,16 +818,16 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
handle->can_refresh = false;
/* create area region */
- ar = ui_region_temp_add(CTX_wm_screen(C));
- handle->region = ar;
+ region = ui_region_temp_add(CTX_wm_screen(C));
+ handle->region = region;
memset(&type, 0, sizeof(ARegionType));
type.draw = ui_block_region_draw;
type.layout = ui_block_region_refresh;
type.regionid = RGN_TYPE_TEMPORARY;
- ar->type = &type;
+ region->type = &type;
- UI_region_handlers_add(&ar->handlers);
+ UI_region_handlers_add(&region->handlers);
block = ui_popup_block_refresh(C, handle, butregion, but);
handle = block->handle;
@@ -837,9 +844,9 @@ void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
{
/* If this popup is created from a popover which does NOT have keep-open flag set,
* then close the popover too. We could extend this to other popup types too. */
- ARegion *ar = handle->popup_create_vars.butregion;
- if (ar != NULL) {
- for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ ARegion *region = handle->popup_create_vars.butregion;
+ if (region != NULL) {
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
if (block->handle && (block->flag & UI_BLOCK_POPOVER) &&
(block->flag & UI_BLOCK_KEEP_OPEN) == 0) {
uiPopupBlockHandle *menu = block->handle;
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index 94bcd6ab37d..0007f6ab9a2 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -23,19 +23,21 @@
* Search Box Region & Interaction
*/
+#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
+#include "DNA_ID.h"
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
#include "BLI_math.h"
-#include "BLI_string.h"
+#include "BLI_listbase.h"
#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -54,9 +56,9 @@
#include "ED_screen.h"
+#include "GPU_state.h"
#include "interface_intern.h"
#include "interface_regions_intern.h"
-#include "GPU_state.h"
#define MENU_BORDER (int)(0.3f * U.widget_unit)
@@ -73,6 +75,7 @@ struct uiSearchItems {
char **names;
void **pointers;
int *icons;
+ int *states;
AutoComplete *autocpl;
void *active;
@@ -88,16 +91,30 @@ typedef struct uiSearchboxData {
bool noback;
/** draw thumbnail previews, rather than list */
bool preview;
- /** use the UI_SEP_CHAR char for splitting shortcuts (good for operators, bad for data) */
+ /** Use the #UI_SEP_CHAR char for splitting shortcuts (good for operators, bad for data). */
bool use_sep;
int prv_rows, prv_cols;
+ /**
+ * Show the active icon and text after the last instance of this string.
+ * Used so we can show leading text to menu items less prominently (not related to 'use_sep').
+ */
+ const char *sep_string;
} uiSearchboxData;
#define SEARCH_ITEMS 10
-/* exported for use by search callbacks */
-/* returns zero if nothing to add */
-bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid)
+/**
+ * Public function exported for functions that use #UI_BTYPE_SEARCH_MENU.
+ *
+ * \param items: Stores the items.
+ * \param name: Text to display for the item.
+ * \param poin: Opaque pointer (for use by the caller).
+ * \param iconid: The icon, #ICON_NONE for no icon.
+ * \param state: The buttons state flag, compatible with #uiBut.flag,
+ * typically #UI_BUT_DISABLED / #UI_BUT_INACTIVE.
+ * \return false if there is nothing to add.
+ */
+bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int state)
{
/* hijack for autocomplete */
if (items->autocpl) {
@@ -135,6 +152,14 @@ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int
items->icons[items->totitem] = iconid;
}
+ /* Limit flags that can be set so flags such as 'UI_SELECT' aren't accidentally set
+ * which will cause problems, add others as needed. */
+ BLI_assert(
+ (state & ~(UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR)) == 0);
+ if (items->states) {
+ items->states[items->totitem] = state;
+ }
+
items->totitem++;
return true;
@@ -161,10 +186,10 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name)
return -1;
}
-/* ar is the search box itself */
-static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step)
+/* region is the search box itself */
+static void ui_searchbox_select(bContext *C, ARegion *region, uiBut *but, int step)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
/* apply step */
data->active += step;
@@ -176,7 +201,7 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step)
if (data->items.more) {
data->items.offset++;
data->active = data->items.totitem - 1;
- ui_searchbox_update(C, ar, but, false);
+ ui_searchbox_update(C, region, but, false);
}
else {
data->active = data->items.totitem - 1;
@@ -186,7 +211,7 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step)
if (data->items.offset) {
data->items.offset--;
data->active = 0;
- ui_searchbox_update(C, ar, but, false);
+ ui_searchbox_update(C, region, but, false);
}
else {
/* only let users step into an 'unset' state for unlink buttons */
@@ -194,7 +219,7 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step)
}
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr)
@@ -229,24 +254,24 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
}
}
-int ui_searchbox_find_index(ARegion *ar, const char *name)
+int ui_searchbox_find_index(ARegion *region, const char *name)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
return UI_search_items_find_index(&data->items, name);
}
/* x and y in screencoords */
-bool ui_searchbox_inside(ARegion *ar, int x, int y)
+bool ui_searchbox_inside(ARegion *region, int x, int y)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
- return BLI_rcti_isect_pt(&data->bbox, x - ar->winrct.xmin, y - ar->winrct.ymin);
+ return BLI_rcti_isect_pt(&data->bbox, x - region->winrct.xmin, y - region->winrct.ymin);
}
/* string validated to be of correct length (but->hardmax) */
-bool ui_searchbox_apply(uiBut *but, ARegion *ar)
+bool ui_searchbox_apply(uiBut *but, ARegion *region)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
but->func_arg2 = NULL;
@@ -272,10 +297,31 @@ bool ui_searchbox_apply(uiBut *but, ARegion *ar)
}
}
-void ui_searchbox_event(bContext *C, ARegion *ar, uiBut *but, const wmEvent *event)
+static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C,
+ struct ARegion *region,
+ int *UNUSED(r_pass),
+ double *UNUSED(pass_delay),
+ bool *r_exit_on_event)
+{
+ *r_exit_on_event = true;
+
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ if (but->search && but->search->tooltip_fn) {
+ return but->search->tooltip_fn(C, region, but->search->arg, but->func_arg2);
+ }
+ }
+ }
+ return NULL;
+}
+
+bool ui_searchbox_event(
+ bContext *C, ARegion *region, uiBut *but, ARegion *butregion, const wmEvent *event)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
int type = event->type, val = event->val;
+ bool handled = false;
+ bool tooltip_timer_started = false;
if (type == MOUSEPAN) {
ui_pan_to_scroll(event, &type, &val);
@@ -283,37 +329,92 @@ void ui_searchbox_event(bContext *C, ARegion *ar, uiBut *but, const wmEvent *eve
switch (type) {
case WHEELUPMOUSE:
- case UPARROWKEY:
- ui_searchbox_select(C, ar, but, -1);
+ case EVT_UPARROWKEY:
+ ui_searchbox_select(C, region, but, -1);
+ handled = true;
break;
case WHEELDOWNMOUSE:
- case DOWNARROWKEY:
- ui_searchbox_select(C, ar, but, 1);
+ case EVT_DOWNARROWKEY:
+ ui_searchbox_select(C, region, but, 1);
+ handled = true;
+ break;
+ case RIGHTMOUSE:
+ if (val) {
+ if (but->search->context_menu_fn) {
+ if (data->active != -1) {
+ /* Check the cursor is over the active element
+ * (a little confusing if this isn't the case, although it does work). */
+ rcti rect;
+ ui_searchbox_butrect(&rect, data, data->active);
+ if (BLI_rcti_isect_pt(
+ &rect, event->x - region->winrct.xmin, event->y - region->winrct.ymin)) {
+
+ void *active = data->items.pointers[data->active];
+ if (but->search->context_menu_fn(C, but->search->arg, active, event)) {
+ handled = true;
+ }
+ }
+ }
+ }
+ }
break;
- case MOUSEMOVE:
- if (BLI_rcti_isect_pt(&ar->winrct, event->x, event->y)) {
+ case MOUSEMOVE: {
+ bool is_inside = false;
+
+ if (BLI_rcti_isect_pt(&region->winrct, event->x, event->y)) {
rcti rect;
int a;
for (a = 0; a < data->items.totitem; a++) {
ui_searchbox_butrect(&rect, data, a);
- if (BLI_rcti_isect_pt(&rect, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin)) {
+ if (BLI_rcti_isect_pt(
+ &rect, event->x - region->winrct.xmin, event->y - region->winrct.ymin)) {
+ is_inside = true;
if (data->active != a) {
data->active = a;
- ui_searchbox_select(C, ar, but, 0);
+ ui_searchbox_select(C, region, but, 0);
+ handled = true;
break;
}
}
}
}
+
+ if (U.flag & USER_TOOLTIPS) {
+ if (is_inside) {
+ if (data->active != -1) {
+ ScrArea *area = CTX_wm_area(C);
+ but->func_arg2 = data->items.pointers[data->active];
+ WM_tooltip_timer_init(C, CTX_wm_window(C), area, butregion, wm_searchbox_tooltip_init);
+ tooltip_timer_started = true;
+ }
+ }
+ }
+
break;
+ }
}
+
+ if (handled && (tooltip_timer_started == false)) {
+ wmWindow *win = CTX_wm_window(C);
+ WM_tooltip_clear(C, win);
+ }
+
+ return handled;
+}
+
+/** Wrap #uiButSearchUpdateFn callback. */
+static void ui_searchbox_update_fn(bContext *C, uiBut *but, const char *str, uiSearchItems *items)
+{
+ wmWindow *win = CTX_wm_window(C);
+ WM_tooltip_clear(C, win);
+ but->search->update_fn(C, but->search->arg, str, items);
}
-/* ar is the search box itself */
-void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, const bool reset)
+/* region is the search box itself */
+void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool reset)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
/* reset vars */
data->items.totitem = 0;
@@ -326,9 +427,9 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, const bool reset)
data->active = -1;
/* handle active */
- if (but->search_func && but->func_arg2) {
+ if (but->search->update_fn && but->func_arg2) {
data->items.active = but->func_arg2;
- but->search_func(C, but->search_arg, but->editstr, &data->items);
+ ui_searchbox_update_fn(C, but, but->editstr, &data->items);
data->items.active = NULL;
/* found active item, calculate real offset by centering it */
@@ -357,8 +458,8 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, const bool reset)
}
/* callback */
- if (but->search_func) {
- but->search_func(C, but->search_arg, but->editstr, &data->items);
+ if (but->search->update_fn) {
+ ui_searchbox_update_fn(C, but, but->editstr, &data->items);
}
/* handle case where editstr is equal to one of items */
@@ -379,20 +480,20 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, const bool reset)
}
/* validate selected item */
- ui_searchbox_select(C, ar, but, 0);
+ ui_searchbox_select(C, region, but, 0);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
-int ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
+int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *str)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
int match = AUTOCOMPLETE_NO_MATCH;
if (str[0]) {
data->items.autocpl = UI_autocomplete_begin(str, ui_but_string_get_max_length(but));
- but->search_func(C, but->search_arg, but->editstr, &data->items);
+ ui_searchbox_update_fn(C, but, but->editstr, &data->items);
match = UI_autocomplete_end(data->items.autocpl, str);
data->items.autocpl = NULL;
@@ -401,12 +502,12 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
return match;
}
-static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
+static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
/* pixel space */
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
if (data->noback == false) {
ui_draw_widget_menu_back(&data->bbox, true);
@@ -420,17 +521,16 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
if (data->preview) {
/* draw items */
for (a = 0; a < data->items.totitem; a++) {
+ const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
+
/* ensure icon is up-to-date */
ui_icon_ensure_deferred(C, data->items.icons[a], data->preview);
ui_searchbox_butrect(&rect, data, a);
/* widget itself */
- ui_draw_preview_item(&data->fstyle,
- &rect,
- data->items.names[a],
- data->items.icons[a],
- (a == data->active) ? UI_ACTIVE : 0);
+ ui_draw_preview_item(
+ &data->fstyle, &rect, data->items.names[a], data->items.icons[a], state);
}
/* indicate more */
@@ -448,17 +548,50 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
}
}
else {
+ const int search_sep_len = data->sep_string ? strlen(data->sep_string) : 0;
/* draw items */
for (a = 0; a < data->items.totitem; a++) {
+ const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
+ char *name = data->items.names[a];
+ int icon = data->items.icons[a];
+ char *name_sep_test = NULL;
+
ui_searchbox_butrect(&rect, data, a);
/* widget itself */
- ui_draw_menu_item(&data->fstyle,
- &rect,
- data->items.names[a],
- data->items.icons[a],
- (a == data->active) ? UI_ACTIVE : 0,
- data->use_sep);
+ if ((search_sep_len == 0) ||
+ !(name_sep_test = strstr(data->items.names[a], data->sep_string))) {
+
+ /* Simple menu item. */
+ ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, data->use_sep, NULL);
+ }
+ else {
+ /* Split menu item, faded text before the separator. */
+ char *name_sep = NULL;
+ do {
+ name_sep = name_sep_test;
+ name_sep_test = strstr(name_sep + search_sep_len, data->sep_string);
+ } while (name_sep_test != NULL);
+
+ name_sep += search_sep_len;
+ const char name_sep_prev = *name_sep;
+ *name_sep = '\0';
+ int name_width = 0;
+ ui_draw_menu_item(
+ &data->fstyle, &rect, name, 0, state | UI_BUT_INACTIVE, false, &name_width);
+ *name_sep = name_sep_prev;
+ rect.xmin += name_width;
+ rect.xmin += UI_UNIT_X / 4;
+
+ if (icon == ICON_BLANK1) {
+ icon = ICON_NONE;
+ rect.xmin -= UI_DPI_ICON_SIZE / 4;
+ }
+
+ /* The previous menu item draws the active selection. */
+ ui_draw_menu_item(
+ &data->fstyle, &rect, name_sep, icon, state & ~UI_ACTIVE, data->use_sep, NULL);
+ }
}
/* indicate more */
if (data->items.more) {
@@ -477,9 +610,9 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
}
}
-static void ui_searchbox_region_free_cb(ARegion *ar)
+static void ui_searchbox_region_free_cb(ARegion *region)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
int a;
/* free search data */
@@ -489,17 +622,18 @@ static void ui_searchbox_region_free_cb(ARegion *ar)
MEM_freeN(data->items.names);
MEM_freeN(data->items.pointers);
MEM_freeN(data->items.icons);
+ MEM_freeN(data->items.states);
MEM_freeN(data);
- ar->regiondata = NULL;
+ region->regiondata = NULL;
}
ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but)
{
wmWindow *win = CTX_wm_window(C);
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
static ARegionType type;
- ARegion *ar;
+ ARegion *region;
uiSearchboxData *data;
float aspect = but->block->aspect;
rctf rect_fl;
@@ -509,13 +643,13 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
int i;
/* create area region */
- ar = ui_region_temp_add(CTX_wm_screen(C));
+ region = ui_region_temp_add(CTX_wm_screen(C));
memset(&type, 0, sizeof(ARegionType));
type.draw = ui_searchbox_region_draw_cb;
type.free = ui_searchbox_region_free_cb;
type.regionid = RGN_TYPE_TEMPORARY;
- ar->type = &type;
+ region->type = &type;
/* create searchbox data */
data = MEM_callocN(sizeof(uiSearchboxData), "uiSearchboxData");
@@ -525,7 +659,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
ui_fontscale(&data->fstyle.points, aspect);
UI_fontstyle_set(&data->fstyle);
- ar->regiondata = data;
+ region->regiondata = data;
/* special case, hardcoded feature, not draw backdrop when called from menus,
* assume for design that popup already added it */
@@ -546,6 +680,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
if (but->optype != NULL || (but->drawflag & UI_BUT_HAS_SHORTCUT) != 0) {
data->use_sep = true;
}
+ data->sep_string = but->search->sep_string;
/* compute position */
if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
@@ -553,13 +688,13 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
/* this case is search menu inside other menu */
/* we copy region size */
- ar->winrct = butregion->winrct;
+ region->winrct = butregion->winrct;
/* widget rect, in region coords */
data->bbox.xmin = margin;
- data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - margin;
+ data->bbox.xmax = BLI_rcti_size_x(&region->winrct) - margin;
data->bbox.ymin = margin;
- data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - margin;
+ data->bbox.ymax = BLI_rcti_size_y(&region->winrct) - margin;
/* check if button is lower half */
if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) {
@@ -632,17 +767,17 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
data->bbox.ymax = BLI_rcti_size_y(&rect_i) + margin;
/* region bigger for shadow */
- ar->winrct.xmin = rect_i.xmin - margin;
- ar->winrct.xmax = rect_i.xmax + margin;
- ar->winrct.ymin = rect_i.ymin - margin;
- ar->winrct.ymax = rect_i.ymax;
+ region->winrct.xmin = rect_i.xmin - margin;
+ region->winrct.xmax = rect_i.xmax + margin;
+ region->winrct.ymin = rect_i.ymin - margin;
+ region->winrct.ymax = rect_i.ymax;
}
/* adds subwindow */
- ED_region_floating_initialize(ar);
+ ED_region_floating_initialize(region);
/* notify change and redraw */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
/* prepare search data */
if (data->preview) {
@@ -656,11 +791,12 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
data->items.names = MEM_callocN(data->items.maxitem * sizeof(void *), "search names");
data->items.pointers = MEM_callocN(data->items.maxitem * sizeof(void *), "search pointers");
data->items.icons = MEM_callocN(data->items.maxitem * sizeof(int), "search icons");
+ data->items.states = MEM_callocN(data->items.maxitem * sizeof(int), "search flags");
for (i = 0; i < data->items.maxitem; i++) {
data->items.names[i] = MEM_callocN(but->hardmax + 1, "search pointers");
}
- return ar;
+ return region;
}
/**
@@ -688,12 +824,12 @@ static void str_tolower_titlecaps_ascii(char *str, const size_t len)
}
}
-static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARegion *ar)
+static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARegion *region)
{
- uiSearchboxData *data = ar->regiondata;
+ uiSearchboxData *data = region->regiondata;
/* pixel space */
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
if (data->noback == false) {
ui_draw_widget_menu_back(&data->bbox, true);
@@ -717,9 +853,9 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
/* widget itself */
/* NOTE: i18n messages extracting tool does the same, please keep it in sync. */
{
- wmOperatorType *ot = data->items.pointers[a];
+ const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
- int state = (a == data->active) ? UI_ACTIVE : 0;
+ wmOperatorType *ot = data->items.pointers[a];
char text_pre[128];
char *text_pre_p = strstr(ot->idname, "_OT_");
if (text_pre_p == NULL) {
@@ -741,9 +877,10 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, text_pre),
data->items.icons[a],
state,
- false);
+ false,
+ NULL);
ui_draw_menu_item(
- &data->fstyle, &rect_post, data->items.names[a], 0, state, data->use_sep);
+ &data->fstyle, &rect_post, data->items.names[a], 0, state, data->use_sep, NULL);
}
}
/* indicate more */
@@ -764,19 +901,38 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
ARegion *ui_searchbox_create_operator(bContext *C, ARegion *butregion, uiBut *but)
{
- ARegion *ar;
+ ARegion *region;
UI_but_drawflag_enable(but, UI_BUT_HAS_SHORTCUT);
- ar = ui_searchbox_create_generic(C, butregion, but);
+ region = ui_searchbox_create_generic(C, butregion, but);
- ar->type->draw = ui_searchbox_region_draw_cb__operator;
+ region->type->draw = ui_searchbox_region_draw_cb__operator;
- return ar;
+ return region;
}
-void ui_searchbox_free(bContext *C, ARegion *ar)
+void ui_searchbox_free(bContext *C, ARegion *region)
{
- ui_region_temp_remove(C, CTX_wm_screen(C), ar);
+ ui_region_temp_remove(C, CTX_wm_screen(C), region);
+}
+
+static void ui_searchbox_region_draw_cb__menu(const bContext *UNUSED(C), ARegion *UNUSED(region))
+{
+ /* Currently unused. */
+}
+
+ARegion *ui_searchbox_create_menu(bContext *C, ARegion *butregion, uiBut *but)
+{
+ ARegion *region;
+
+ UI_but_drawflag_enable(but, UI_BUT_HAS_SHORTCUT);
+ region = ui_searchbox_create_generic(C, butregion, but);
+
+ if (false) {
+ region->type->draw = ui_searchbox_region_draw_cb__menu;
+ }
+
+ return region;
}
/* sets red alert if button holds a string it can't find */
@@ -802,7 +958,7 @@ void ui_but_search_refresh(uiBut *but)
items->names[x1] = MEM_callocN(but->hardmax + 1, "search names");
}
- but->search_func(but->block->evil_C, but->search_arg, but->drawstr, items);
+ ui_searchbox_update_fn(but->block->evil_C, but, but->drawstr, items);
/* only redalert when we are sure of it, this can miss cases when >10 matches */
if (items->totitem == 0) {
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 7a0c04be356..b64f080d9cc 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -32,19 +32,20 @@
* For now it's not a priority, so leave as-is.
*/
+#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
-#include "DNA_userdef_types.h"
#include "DNA_brush_types.h"
+#include "DNA_userdef_types.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_string.h"
#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -148,10 +149,10 @@ static void rgb_tint(float col[3], float h, float h_strength, float v, float v_s
hsv_to_rgb_v(col_hsv_to, col);
}
-static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
+static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *region)
{
const float pad_px = UI_TIP_PADDING;
- uiTooltipData *data = ar->regiondata;
+ uiTooltipData *data = region->regiondata;
const uiWidgetColors *theme = ui_tooltip_get_theme();
rcti bbox = data->bbox;
float tip_colors[UI_TIP_LC_MAX][3];
@@ -168,7 +169,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
float tone_bg;
int i;
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
/* draw background */
ui_draw_tooltip_background(UI_style_get(), NULL, &bbox);
@@ -271,11 +272,11 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
BLF_disable(blf_mono_font, BLF_WORD_WRAP);
}
-static void ui_tooltip_region_free_cb(ARegion *ar)
+static void ui_tooltip_region_free_cb(ARegion *region)
{
uiTooltipData *data;
- data = ar->regiondata;
+ data = region->regiondata;
for (int i = 0; i < data->fields_len; i++) {
const uiTooltipField *field = &data->fields[i];
@@ -286,7 +287,7 @@ static void ui_tooltip_region_free_cb(ARegion *ar)
}
MEM_freeN(data->fields);
MEM_freeN(data);
- ar->regiondata = NULL;
+ region->regiondata = NULL;
}
/** \} */
@@ -318,7 +319,7 @@ static bool ui_tooltip_data_append_from_keymap(bContext *C, uiTooltipData *data,
const int fields_len_init = data->fields_len;
char buf[512];
- for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
wmOperatorType *ot = WM_operatortype_find(kmi->idname, true);
if (ot != NULL) {
/* Tip */
@@ -393,15 +394,15 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
bool has_valid_context = true;
const char *has_valid_context_error = IFACE_("Unsupported context");
{
- ScrArea *sa = CTX_wm_area(C);
- if (sa == NULL) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area == NULL) {
has_valid_context = false;
}
else {
PropertyRNA *prop = RNA_struct_find_property(but->opptr, "space_type");
if (RNA_property_is_set(but->opptr, prop)) {
const int space_type_prop = RNA_property_enum_get(but->opptr, prop);
- if (space_type_prop != sa->spacetype) {
+ if (space_type_prop != area->spacetype) {
has_valid_context = false;
}
}
@@ -596,7 +597,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
else if (BPY_execute_string_as_intptr(C, expr_imports, expr, true, &expr_result)) {
if (expr_result != 0) {
wmKeyMap *keymap = (wmKeyMap *)expr_result;
- for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
if (STREQ(kmi->idname, but->optype->idname)) {
char tool_id_test[MAX_NAME];
RNA_string_get(kmi->ptr, "name", tool_id_test);
@@ -755,7 +756,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
}
}
#else
- UNUSED_VARS(is_label);
+ UNUSED_VARS(is_label, has_valid_context, has_valid_context_error);
#endif /* WITH_PYTHON */
if (data->fields_len == 0) {
@@ -1158,22 +1159,22 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
wmWindow *win = CTX_wm_window(C);
const int winx = WM_window_pixels_x(win);
const int winy = WM_window_pixels_y(win);
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
static ARegionType type;
- ARegion *ar;
+ ARegion *region;
int fonth, fontw;
int h, i;
rcti rect_i;
int font_flag = 0;
/* create area region */
- ar = ui_region_temp_add(CTX_wm_screen(C));
+ region = ui_region_temp_add(CTX_wm_screen(C));
memset(&type, 0, sizeof(ARegionType));
type.draw = ui_tooltip_region_draw_cb;
type.free = ui_tooltip_region_free_cb;
type.regionid = RGN_TYPE_TEMPORARY;
- ar->type = &type;
+ region->type = &type;
/* set font, get bb */
data->fstyle = style->widget; /* copy struct */
@@ -1237,7 +1238,7 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
BLF_disable(data->fstyle.uifont_id, font_flag);
BLF_disable(blf_mono_font, font_flag);
- ar->regiondata = data;
+ region->regiondata = data;
data->toth = fonth;
data->lineh = h;
@@ -1384,19 +1385,19 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
data->bbox.ymax = BLI_rcti_size_y(&rect_i);
/* region bigger for shadow */
- ar->winrct.xmin = rect_i.xmin - margin;
- ar->winrct.xmax = rect_i.xmax + margin;
- ar->winrct.ymin = rect_i.ymin - margin;
- ar->winrct.ymax = rect_i.ymax + margin;
+ region->winrct.xmin = rect_i.xmin - margin;
+ region->winrct.xmax = rect_i.xmax + margin;
+ region->winrct.ymin = rect_i.ymin - margin;
+ region->winrct.ymax = rect_i.ymax + margin;
}
/* adds subwindow */
- ED_region_floating_initialize(ar);
+ ED_region_floating_initialize(region);
/* notify change and redraw */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
- return ar;
+ return region;
}
/** \} */
@@ -1450,17 +1451,18 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
}
else {
init_position[0] = BLI_rctf_cent_x(&but->rect);
- init_position[1] = but->rect.ymin - (UI_POPUP_MARGIN / 2);
+ init_position[1] = but->rect.ymin;
if (butregion) {
ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
init_position[0] = win->eventstate->x;
}
+ init_position[1] -= (UI_POPUP_MARGIN / 2);
}
- ARegion *ar = ui_tooltip_create_with_data(
+ ARegion *region = ui_tooltip_create_with_data(
C, data, init_position, is_no_overlap ? &init_rect : NULL, aspect);
- return ar;
+ return region;
}
ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
@@ -1480,9 +1482,9 @@ ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect);
}
-void UI_tooltip_free(bContext *C, bScreen *sc, ARegion *ar)
+void UI_tooltip_free(bContext *C, bScreen *screen, ARegion *region)
{
- ui_region_temp_remove(C, sc, ar);
+ ui_region_temp_remove(C, screen, region);
}
/** \} */
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 5ba4dcd7439..9ff58ddd24f 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -25,9 +25,9 @@
* \note Most logic is now in 'interface_region_*.c'
*/
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
-#include "BLI_listbase.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -39,30 +39,30 @@
#include "interface_regions_intern.h"
-ARegion *ui_region_temp_add(bScreen *sc)
+ARegion *ui_region_temp_add(bScreen *screen)
{
- ARegion *ar;
+ ARegion *region;
- ar = MEM_callocN(sizeof(ARegion), "area region");
- BLI_addtail(&sc->regionbase, ar);
+ region = MEM_callocN(sizeof(ARegion), "area region");
+ BLI_addtail(&screen->regionbase, region);
- ar->regiontype = RGN_TYPE_TEMPORARY;
- ar->alignment = RGN_ALIGN_FLOAT;
+ region->regiontype = RGN_TYPE_TEMPORARY;
+ region->alignment = RGN_ALIGN_FLOAT;
- return ar;
+ return region;
}
-void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar)
+void ui_region_temp_remove(bContext *C, bScreen *screen, ARegion *region)
{
wmWindow *win = CTX_wm_window(C);
- BLI_assert(ar->regiontype == RGN_TYPE_TEMPORARY);
- BLI_assert(BLI_findindex(&sc->regionbase, ar) != -1);
+ BLI_assert(region->regiontype == RGN_TYPE_TEMPORARY);
+ BLI_assert(BLI_findindex(&screen->regionbase, region) != -1);
if (win) {
- wm_draw_region_clear(win, ar);
+ wm_draw_region_clear(win, region);
}
- ED_region_exit(C, ar);
- BKE_area_region_free(NULL, ar); /* NULL: no spacetype */
- BLI_freelinkN(&sc->regionbase, ar);
+ ED_region_exit(C, region);
+ BKE_area_region_free(NULL, region); /* NULL: no spacetype */
+ BLI_freelinkN(&screen->regionbase, region);
}
diff --git a/source/blender/editors/interface/interface_regions_intern.h b/source/blender/editors/interface/interface_regions_intern.h
index 31a0a0876a2..c299562a357 100644
--- a/source/blender/editors/interface/interface_regions_intern.h
+++ b/source/blender/editors/interface/interface_regions_intern.h
@@ -27,7 +27,7 @@
uint ui_popup_menu_hash(const char *str);
/* interface_regions_intern.h */
-ARegion *ui_region_temp_add(bScreen *sc);
-void ui_region_temp_remove(struct bContext *C, bScreen *sc, ARegion *ar);
+ARegion *ui_region_temp_add(bScreen *screen);
+void ui_region_temp_remove(struct bContext *C, bScreen *screen, ARegion *region);
#endif /* __INTERFACE_REGIONS_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 192571044b9..e481ec08d72 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -28,7 +28,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "BLI_listbase.h"
@@ -147,8 +146,9 @@ void UI_fontstyle_draw_ex(const uiFontStyle *fs,
const uchar col[4],
const struct uiFontStyleDraw_Params *fs_params,
size_t len,
- float *r_xofs,
- float *r_yofs)
+ int *r_xofs,
+ int *r_yofs,
+ struct ResultBLF *r_info)
{
int xofs = 0, yofs;
int font_flag = BLF_CLIPPING;
@@ -196,7 +196,7 @@ void UI_fontstyle_draw_ex(const uiFontStyle *fs,
BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f);
BLF_color4ubv(fs->uifont_id, col);
- BLF_draw(fs->uifont_id, str, len);
+ BLF_draw_ex(fs->uifont_id, str, len, r_info);
BLF_disable(fs->uifont_id, font_flag);
@@ -210,9 +210,9 @@ void UI_fontstyle_draw(const uiFontStyle *fs,
const uchar col[4],
const struct uiFontStyleDraw_Params *fs_params)
{
- float xofs, yofs;
+ int xofs, yofs;
- UI_fontstyle_draw_ex(fs, rect, str, col, fs_params, BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs);
+ UI_fontstyle_draw_ex(fs, rect, str, col, fs_params, BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs, NULL);
}
/* drawn same as above, but at 90 degree angle */
@@ -351,7 +351,7 @@ void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs,
/* ************** helpers ************************ */
/* XXX: read a style configure */
-uiStyle *UI_style_get(void)
+const uiStyle *UI_style_get(void)
{
#if 0
uiStyle *style = NULL;
@@ -364,9 +364,9 @@ uiStyle *UI_style_get(void)
}
/* for drawing, scaled with DPI setting */
-uiStyle *UI_style_get_dpi(void)
+const uiStyle *UI_style_get_dpi(void)
{
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
static uiStyle _style;
_style = *style;
@@ -422,8 +422,6 @@ void uiStyleInit(void)
{
uiFont *font;
uiStyle *style = U.uistyles.first;
- int monofont_size = datatoc_bmonofont_ttf_size;
- uchar *monofont_ttf = (uchar *)datatoc_bmonofont_ttf;
/* recover from uninitialized dpi */
if (U.dpi == 0) {
@@ -463,39 +461,15 @@ void uiStyleInit(void)
}
for (font = U.uifonts.first; font; font = font->next) {
+ const bool unique = false;
if (font->uifont_id == UIFONT_DEFAULT) {
-#ifdef WITH_INTERNATIONAL
- int font_size = datatoc_bfont_ttf_size;
- uchar *font_ttf = (uchar *)datatoc_bfont_ttf;
- static int last_font_size = 0;
-
- /* use unicode font for translation */
- if (U.transopts & USER_DOTRANSLATE) {
- font_ttf = BLF_get_unifont(&font_size);
-
- if (!font_ttf) {
- /* fall back if not found */
- font_size = datatoc_bfont_ttf_size;
- font_ttf = (uchar *)datatoc_bfont_ttf;
- }
- }
-
- /* relload only if needed */
- if (last_font_size != font_size) {
- BLF_unload("default");
- last_font_size = font_size;
- }
-
- font->blf_id = BLF_load_mem("default", font_ttf, font_size);
-#else
- font->blf_id = BLF_load_mem("default", (uchar *)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
-#endif
+ font->blf_id = BLF_load_default(unique);
}
else {
font->blf_id = BLF_load(font->filename);
if (font->blf_id == -1) {
- font->blf_id = BLF_load_mem("default", (uchar *)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
+ font->blf_id = BLF_load_default(unique);
}
}
@@ -521,27 +495,17 @@ void uiStyleInit(void)
ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT);
}
-#ifdef WITH_INTERNATIONAL
- /* use unicode font for text editor and interactive console */
- if (U.transopts & USER_DOTRANSLATE) {
- monofont_ttf = BLF_get_unifont_mono(&monofont_size);
-
- if (!monofont_ttf) {
- /* fall back if not found */
- monofont_size = datatoc_bmonofont_ttf_size;
- monofont_ttf = (uchar *)datatoc_bmonofont_ttf;
- }
- }
-#endif
-
/* XXX, this should be moved into a style,
* but for now best only load the monospaced font once. */
BLI_assert(blf_mono_font == -1);
+ /* Use unique font loading to avoid thread safety issues with mono font
+ * used for render metadata stamp in threads. */
if (U.font_path_ui_mono[0]) {
blf_mono_font = BLF_load_unique(U.font_path_ui_mono);
}
if (blf_mono_font == -1) {
- blf_mono_font = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size);
+ const bool unique = true;
+ blf_mono_font = BLF_load_mono_default(unique);
}
BLF_size(blf_mono_font, 12 * U.pixelsize, 72);
@@ -584,7 +548,8 @@ void uiStyleInit(void)
* keep for now though, since without this there is no way to display many unicode chars.
*/
if (blf_mono_font_render == -1) {
- blf_mono_font_render = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size);
+ const bool unique = true;
+ blf_mono_font_render = BLF_load_mono_default(unique);
}
BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72);
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c
new file mode 100644
index 00000000000..0a06f765c0e
--- /dev/null
+++ b/source/blender/editors/interface/interface_template_search_menu.c
@@ -0,0 +1,1098 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edinterface
+ *
+ * Search available menu items via the user interface & key-maps.
+ * Accessed via the #WM_OT_search_menu operator.
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_shader_fx_types.h"
+#include "DNA_texture_types.h"
+
+#include "BLI_alloca.h"
+#include "BLI_dynstr.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_listbase.h"
+#include "BLI_math_matrix.h"
+#include "BLI_memarena.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "interface_intern.h"
+
+/* For key-map item access. */
+#include "wm_event_system.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Menu Search Template Implementation
+ * \{ */
+
+/* Unicode arrow. */
+#define MENU_SEP "\xe2\x96\xb6"
+
+/**
+ * Use when #menu_items_from_ui_create is called with `include_all_areas`.
+ * so we can run the menu item in the area it was extracted from.
+ */
+struct MenuSearch_Context {
+ /**
+ * Index into `Area.ui_type` #EnumPropertyItem or the top-bar when -1.
+ * Needed to get the display-name to use as a prefix for each menu item.
+ */
+ int space_type_ui_index;
+
+ ScrArea *area;
+ ARegion *region;
+};
+
+struct MenuSearch_Parent {
+ struct MenuSearch_Parent *parent;
+ MenuType *parent_mt;
+ const char *drawstr;
+
+ /** Set while writing menu items only. */
+ struct MenuSearch_Parent *temp_child;
+};
+
+struct MenuSearch_Item {
+ struct MenuSearch_Item *next, *prev;
+ const char *drawstr;
+ const char *drawwstr_full;
+ /** Support a single level sub-menu nesting (for operator buttons that expand). */
+ const char *drawstr_submenu;
+ int icon;
+ int state;
+
+ struct MenuSearch_Parent *menu_parent;
+ MenuType *mt;
+
+ enum {
+ MENU_SEARCH_TYPE_OP = 1,
+ MENU_SEARCH_TYPE_RNA = 2,
+ } type;
+
+ union {
+ /** Operator menu item. */
+ struct {
+ wmOperatorType *type;
+ PointerRNA *opptr;
+ short opcontext;
+ bContextStore *context;
+ } op;
+
+ /** Property (only for check-box/boolean). */
+ struct {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ /** Only for enum buttons. */
+ int enum_value;
+ } rna;
+ };
+
+ /** Set when we need each menu item to be able to set it's own context. may be NULL. */
+ struct MenuSearch_Context *wm_context;
+};
+
+struct MenuSearch_Data {
+ /** MenuSearch_Item */
+ ListBase items;
+ /** Use for all small allocations. */
+ MemArena *memarena;
+
+ /** Use for context menu, to fake a button to create a context menu. */
+ struct {
+ uiBut but;
+ uiBlock block;
+ } context_menu_data;
+};
+
+static int menu_item_sort_by_drawstr_full(const void *menu_item_a_v, const void *menu_item_b_v)
+{
+ const struct MenuSearch_Item *menu_item_a = menu_item_a_v;
+ const struct MenuSearch_Item *menu_item_b = menu_item_b_v;
+ return strcmp(menu_item_a->drawwstr_full, menu_item_b->drawwstr_full);
+}
+
+static const char *strdup_memarena(MemArena *memarena, const char *str)
+{
+ const uint str_size = strlen(str) + 1;
+ char *str_dst = BLI_memarena_alloc(memarena, str_size);
+ memcpy(str_dst, str, str_size);
+ return str_dst;
+}
+
+static const char *strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_str)
+{
+ const uint str_size = BLI_dynstr_get_len(dyn_str) + 1;
+ char *str_dst = BLI_memarena_alloc(memarena, str_size);
+ BLI_dynstr_get_cstring_ex(dyn_str, str_dst);
+ return str_dst;
+}
+
+static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *data,
+ MemArena *memarena,
+ struct MenuType *mt,
+ const char *drawstr_submenu,
+ uiBut *but,
+ struct MenuSearch_Context *wm_context)
+{
+ struct MenuSearch_Item *item = NULL;
+ if (but->optype != NULL) {
+ item = BLI_memarena_calloc(memarena, sizeof(*item));
+ item->type = MENU_SEARCH_TYPE_OP;
+
+ item->op.type = but->optype;
+ item->op.opcontext = but->opcontext;
+ item->op.context = but->context;
+ item->op.opptr = but->opptr;
+ but->opptr = NULL;
+ }
+ else if (but->rnaprop != NULL) {
+ const int prop_type = RNA_property_type(but->rnaprop);
+ if (!ELEM(prop_type, PROP_BOOLEAN, PROP_ENUM)) {
+ /* Note that these buttons are not prevented,
+ * but aren't typically used in menus. */
+ printf("Button '%s' in menu '%s' is a menu item with unsupported RNA type %d\n",
+ but->drawstr,
+ mt->idname,
+ prop_type);
+ }
+ else {
+ item = BLI_memarena_calloc(memarena, sizeof(*item));
+ item->type = MENU_SEARCH_TYPE_RNA;
+
+ item->rna.ptr = but->rnapoin;
+ item->rna.prop = but->rnaprop;
+ item->rna.index = but->rnaindex;
+
+ if (prop_type == PROP_ENUM) {
+ item->rna.enum_value = (int)but->hardmax;
+ }
+ }
+ }
+
+ if (item != NULL) {
+ /* Handle shared settings. */
+ item->drawstr = strdup_memarena(memarena, but->drawstr);
+ item->icon = ui_but_icon(but);
+ item->state = (but->flag &
+ (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR));
+ item->mt = mt;
+ item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : NULL;
+
+ item->wm_context = wm_context;
+
+ BLI_addtail(&data->items, item);
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Populate a fake button from a menu item (use for context menu).
+ */
+static bool menu_items_to_ui_button(struct MenuSearch_Item *item, uiBut *but)
+{
+ bool changed = false;
+ switch (item->type) {
+ case MENU_SEARCH_TYPE_OP: {
+ but->optype = item->op.type;
+ but->opcontext = item->op.opcontext;
+ but->context = item->op.context;
+ but->opptr = item->op.opptr;
+ changed = true;
+ break;
+ }
+ case MENU_SEARCH_TYPE_RNA: {
+ const int prop_type = RNA_property_type(item->rna.prop);
+
+ but->rnapoin = item->rna.ptr;
+ but->rnaprop = item->rna.prop;
+ but->rnaindex = item->rna.index;
+
+ if (prop_type == PROP_ENUM) {
+ but->hardmax = item->rna.enum_value;
+ }
+ changed = true;
+ break;
+ }
+ }
+
+ if (changed) {
+ STRNCPY(but->drawstr, item->drawstr);
+ char *drawstr_sep = (item->state & UI_BUT_HAS_SEP_CHAR) ? strrchr(but->drawstr, UI_SEP_CHAR) :
+ NULL;
+ if (drawstr_sep) {
+ *drawstr_sep = '\0';
+ }
+
+ but->icon = item->icon;
+ but->str = but->strdata;
+ }
+
+ return changed;
+}
+
+/**
+ * Populate \a menu_stack with menus from inspecting active key-maps for this context.
+ */
+static void menu_types_add_from_keymap_items(bContext *C,
+ wmWindow *win,
+ ScrArea *area,
+ ARegion *region,
+ LinkNode **menuid_stack_p,
+ GHash *menu_to_kmi,
+ GSet *menu_tagged)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ListBase *handlers[] = {
+ region ? &region->handlers : NULL,
+ area ? &area->handlers : NULL,
+ &win->handlers,
+ };
+
+ for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) {
+ if (handlers[handler_index] == NULL) {
+ continue;
+ }
+ LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers[handler_index]) {
+ /* During this loop, UI handlers for nested menus can tag multiple handlers free. */
+ if (handler_base->flag & WM_HANDLER_DO_FREE) {
+ continue;
+ }
+ if (handler_base->type != WM_HANDLER_TYPE_KEYMAP) {
+ continue;
+ }
+
+ else if (handler_base->poll == NULL || handler_base->poll(region, win->eventstate)) {
+ wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base;
+ wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler);
+ if (keymap && WM_keymap_poll(C, keymap)) {
+ LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
+ if (kmi->flag & KMI_INACTIVE) {
+ continue;
+ }
+ if (STR_ELEM(kmi->idname, "WM_OT_call_menu", "WM_OT_call_menu_pie")) {
+ char menu_idname[MAX_NAME];
+ RNA_string_get(kmi->ptr, "name", menu_idname);
+ MenuType *mt = WM_menutype_find(menu_idname, false);
+
+ if (mt && BLI_gset_add(menu_tagged, mt)) {
+ /* Unlikely, but possible this will be included twice. */
+ BLI_linklist_prepend(menuid_stack_p, mt);
+
+ void **kmi_p;
+ if (!BLI_ghash_ensure_p(menu_to_kmi, mt, &kmi_p)) {
+ *kmi_p = kmi;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Display all operators (last). Developer-only convenience feature.
+ */
+static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *data)
+{
+ /* Add to temporary list so we can sort them separately. */
+ ListBase operator_items = {NULL, NULL};
+
+ MemArena *memarena = data->memarena;
+ GHashIterator iter;
+ for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter);
+ BLI_ghashIterator_step(&iter)) {
+ wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
+
+ if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) {
+ continue;
+ }
+
+ if (WM_operator_poll((bContext *)C, ot)) {
+ const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name);
+
+ struct MenuSearch_Item *item = NULL;
+ item = BLI_memarena_calloc(memarena, sizeof(*item));
+ item->type = MENU_SEARCH_TYPE_OP;
+
+ item->op.type = ot;
+ item->op.opcontext = WM_OP_INVOKE_DEFAULT;
+ item->op.context = NULL;
+
+ char idname_as_py[OP_MAX_TYPENAME];
+ char uiname[256];
+ WM_operator_py_idname(idname_as_py, ot->idname);
+
+ SNPRINTF(uiname, "%s " MENU_SEP "%s", idname_as_py, ot_ui_name);
+
+ item->drawwstr_full = strdup_memarena(memarena, uiname);
+ item->drawstr = ot_ui_name;
+
+ item->wm_context = NULL;
+
+ BLI_addtail(&operator_items, item);
+ }
+ }
+
+ BLI_listbase_sort(&operator_items, menu_item_sort_by_drawstr_full);
+
+ BLI_movelisttolist(&data->items, &operator_items);
+}
+
+/**
+ * Create #MenuSearch_Data by inspecting the current context, this uses two methods:
+ *
+ * - Look-up pre-defined editor-menus.
+ * - Look-up key-map items which call menus.
+ */
+static struct MenuSearch_Data *menu_items_from_ui_create(
+ bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas)
+{
+ MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ /** Map (#MenuType to #MenuSearch_Parent) */
+ GHash *menu_parent_map = BLI_ghash_ptr_new(__func__);
+ GHash *menu_display_name_map = BLI_ghash_ptr_new(__func__);
+ const uiStyle *style = UI_style_get_dpi();
+
+ /* Convert into non-ui structure. */
+ struct MenuSearch_Data *data = MEM_callocN(sizeof(*data), __func__);
+
+ DynStr *dyn_str = BLI_dynstr_new_memarena();
+
+ /* Use a stack of menus to handle and discover new menus in passes. */
+ LinkNode *menu_stack = NULL;
+
+ /* Tag menu types not to add, either because they have already been added
+ * or they have been blacklisted.
+ * Set of #MenuType. */
+ GSet *menu_tagged = BLI_gset_ptr_new(__func__);
+ /** Map (#MenuType -> #wmKeyMapItem). */
+ GHash *menu_to_kmi = BLI_ghash_ptr_new(__func__);
+
+ /* Blacklist menus we don't want to show. */
+ {
+ const char *idname_array[] = {
+ /* While we could include this, it's just showing filenames to load. */
+ "TOPBAR_MT_file_open_recent",
+ };
+ for (int i = 0; i < ARRAY_SIZE(idname_array); i++) {
+ MenuType *mt = WM_menutype_find(idname_array[i], false);
+ if (mt != NULL) {
+ BLI_gset_add(menu_tagged, mt);
+ }
+ }
+ }
+
+ /* Collect contexts, one for each 'ui_type'. */
+ struct MenuSearch_Context *wm_contexts = NULL;
+
+ const EnumPropertyItem *space_type_ui_items = NULL;
+ int space_type_ui_items_len = 0;
+ bool space_type_ui_items_free = false;
+
+ /* Text used as prefix for top-bar menu items. */
+ const char *global_menu_prefix = NULL;
+
+ if (include_all_areas) {
+ /* First create arrays for ui_type. */
+ PropertyRNA *prop_ui_type = NULL;
+ {
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Area, NULL, &ptr);
+ prop_ui_type = RNA_struct_find_property(&ptr, "ui_type");
+ RNA_property_enum_items(C,
+ &ptr,
+ prop_ui_type,
+ &space_type_ui_items,
+ &space_type_ui_items_len,
+ &space_type_ui_items_free);
+
+ wm_contexts = BLI_memarena_calloc(memarena, sizeof(*wm_contexts) * space_type_ui_items_len);
+ for (int i = 0; i < space_type_ui_items_len; i++) {
+ wm_contexts[i].space_type_ui_index = -1;
+ }
+ }
+
+ bScreen *screen = WM_window_get_active_screen(win);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+ if (region != NULL) {
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_Area, area, &ptr);
+ const int space_type_ui = RNA_property_enum_get(&ptr, prop_ui_type);
+
+ int space_type_ui_index = RNA_enum_from_value(space_type_ui_items, space_type_ui);
+ if (space_type_ui_index == -1) {
+ continue;
+ }
+
+ if (wm_contexts[space_type_ui_index].space_type_ui_index != -1) {
+ ScrArea *area_best = wm_contexts[space_type_ui_index].area;
+ const uint value_best = (uint)area_best->winx * (uint)area_best->winy;
+ const uint value_test = (uint)area->winx * (uint)area->winy;
+ if (value_best > value_test) {
+ continue;
+ }
+ }
+
+ wm_contexts[space_type_ui_index].space_type_ui_index = space_type_ui_index;
+ wm_contexts[space_type_ui_index].area = area;
+ wm_contexts[space_type_ui_index].region = region;
+ }
+ }
+
+ global_menu_prefix = CTX_IFACE_(RNA_property_translation_context(prop_ui_type), "Top Bar");
+ }
+
+ GHashIterator iter;
+
+ for (int space_type_ui_index = -1; space_type_ui_index < space_type_ui_items_len;
+ space_type_ui_index += 1) {
+
+ ScrArea *area = NULL;
+ ARegion *region = NULL;
+ struct MenuSearch_Context *wm_context = NULL;
+
+ if (include_all_areas) {
+ if (space_type_ui_index == -1) {
+ /* First run without any context, to populate the top-bar without. */
+ wm_context = NULL;
+ area = NULL;
+ region = NULL;
+ }
+ else {
+ wm_context = &wm_contexts[space_type_ui_index];
+ if (wm_context->space_type_ui_index == -1) {
+ continue;
+ }
+
+ area = wm_context->area;
+ region = wm_context->region;
+
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
+ }
+ }
+ else {
+ area = area_init;
+ region = region_init;
+ }
+
+ /* Populate menus from the editors,
+ * note that we could create a fake header, draw the header and extract the menus
+ * from the buttons, however this is quite involved and can be avoided as by convention
+ * each space-type has a single root-menu that headers use. */
+ {
+ const char *idname_array[2] = {NULL};
+ int idname_array_len = 0;
+
+ /* Use negative for global (no area) context, populate the top-bar. */
+ if (space_type_ui_index == -1) {
+ idname_array[idname_array_len++] = "TOPBAR_MT_editor_menus";
+ }
+
+#define SPACE_MENU_MAP(space_type, menu_id) \
+ case space_type: \
+ idname_array[idname_array_len++] = menu_id; \
+ break
+#define SPACE_MENU_NOP(space_type) \
+ case space_type: \
+ break
+
+ if (area != NULL) {
+ SpaceLink *sl = area->spacedata.first;
+ switch ((eSpace_Type)area->spacetype) {
+ SPACE_MENU_MAP(SPACE_VIEW3D, "VIEW3D_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_GRAPH, "GRAPH_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_OUTLINER, "OUTLINER_MT_editor_menus");
+ SPACE_MENU_NOP(SPACE_PROPERTIES);
+ SPACE_MENU_MAP(SPACE_FILE, "FILEBROWSER_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_IMAGE, "IMAGE_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_INFO, "INFO_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_SEQ, "SEQUENCER_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_TEXT, "TEXT_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_ACTION,
+ (((const SpaceAction *)sl)->mode == SACTCONT_TIMELINE) ?
+ "TIME_MT_editor_menus" :
+ "DOPESHEET_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_NLA, "NLA_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_NODE, "NODE_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_CONSOLE, "CONSOLE_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_USERPREF, "USERPREF_MT_editor_menus");
+ SPACE_MENU_MAP(SPACE_CLIP,
+ (((const SpaceClip *)sl)->mode == SC_MODE_TRACKING) ?
+ "CLIP_MT_tracking_editor_menus" :
+ "CLIP_MT_masking_editor_menus");
+ SPACE_MENU_NOP(SPACE_EMPTY);
+ SPACE_MENU_NOP(SPACE_SCRIPT);
+ SPACE_MENU_NOP(SPACE_STATUSBAR);
+ SPACE_MENU_NOP(SPACE_TOPBAR);
+ }
+ }
+ for (int i = 0; i < idname_array_len; i++) {
+ MenuType *mt = WM_menutype_find(idname_array[i], false);
+ if (mt != NULL) {
+ /* Check if this exists because of 'include_all_areas'. */
+ if (BLI_gset_add(menu_tagged, mt)) {
+ BLI_linklist_prepend(&menu_stack, mt);
+ }
+ }
+ }
+ }
+#undef SPACE_MENU_MAP
+#undef SPACE_MENU_NOP
+
+ bool has_keymap_menu_items = false;
+
+ while (menu_stack != NULL) {
+ MenuType *mt = BLI_linklist_pop(&menu_stack);
+ if (!WM_menutype_poll(C, mt)) {
+ continue;
+ }
+
+ uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
+ uiLayout *layout = UI_block_layout(
+ block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
+
+ UI_block_flag_enable(block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS);
+
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
+ UI_menutype_draw(C, mt, layout);
+
+ UI_block_end(C, block);
+
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ MenuType *mt_from_but = NULL;
+ /* Support menu titles with dynamic from initial labels
+ * (used by edit-mesh context menu). */
+ if (but->type == UI_BTYPE_LABEL) {
+
+ /* Check if the label is the title. */
+ uiBut *but_test = but->prev;
+ while (but_test && but_test->type == UI_BTYPE_SEPR) {
+ but_test = but_test->prev;
+ }
+
+ if (but_test == NULL) {
+ BLI_ghash_insert(
+ menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr));
+ }
+ }
+ else if (menu_items_from_ui_create_item_from_button(
+ data, memarena, mt, NULL, but, wm_context)) {
+ /* pass */
+ }
+ else if ((mt_from_but = UI_but_menutype_get(but))) {
+
+ if (BLI_gset_add(menu_tagged, mt_from_but)) {
+ BLI_linklist_prepend(&menu_stack, mt_from_but);
+ }
+
+ if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) {
+ struct MenuSearch_Parent *menu_parent = BLI_memarena_calloc(memarena,
+ sizeof(*menu_parent));
+ /* Use brackets for menu key shortcuts,
+ * converting "Text|Some-Shortcut" to "Text (Some-Shortcut)".
+ * This is needed so we don't right align sub-menu contents
+ * we only want to do that for the last menu item, not the path that leads to it.
+ */
+ const char *drawstr_sep = but->flag & UI_BUT_HAS_SEP_CHAR ?
+ strrchr(but->drawstr, UI_SEP_CHAR) :
+ NULL;
+ bool drawstr_is_empty = false;
+ if (drawstr_sep != NULL) {
+ BLI_assert(BLI_dynstr_get_len(dyn_str) == 0);
+ /* Detect empty string, fallback to menu name. */
+ const char *drawstr = but->drawstr;
+ int drawstr_len = drawstr_sep - but->drawstr;
+ if (UNLIKELY(drawstr_len == 0)) {
+ drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label);
+ drawstr_len = strlen(drawstr);
+ if (drawstr[0] == '\0') {
+ drawstr_is_empty = true;
+ }
+ }
+ BLI_dynstr_nappend(dyn_str, drawstr, drawstr_len);
+ BLI_dynstr_appendf(dyn_str, " (%s)", drawstr_sep + 1);
+ menu_parent->drawstr = strdup_memarena_from_dynstr(memarena, dyn_str);
+ BLI_dynstr_clear(dyn_str);
+ }
+ else {
+ const char *drawstr = but->drawstr;
+ if (UNLIKELY(drawstr[0] == '\0')) {
+ drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label);
+ if (drawstr[0] == '\0') {
+ drawstr_is_empty = true;
+ }
+ }
+ menu_parent->drawstr = strdup_memarena(memarena, drawstr);
+ }
+ menu_parent->parent_mt = mt;
+ BLI_ghash_insert(menu_parent_map, mt_from_but, menu_parent);
+
+ if (drawstr_is_empty) {
+ printf("Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->idname);
+ }
+ }
+ }
+ else if (but->menu_create_func != NULL) {
+ /* A non 'MenuType' menu button. */
+
+ /* Only expand one level deep, this is mainly for expanding operator menus. */
+ const char *drawstr_submenu = but->drawstr;
+
+ /* +1 to avoid overlap with the current 'block'. */
+ uiBlock *sub_block = UI_block_begin(C, region, __func__ + 1, UI_EMBOSS);
+ uiLayout *sub_layout = UI_block_layout(
+ sub_block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
+
+ UI_block_flag_enable(sub_block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS);
+
+ uiLayoutSetOperatorContext(sub_layout, WM_OP_INVOKE_REGION_WIN);
+
+ but->menu_create_func(C, sub_layout, but->poin);
+
+ UI_block_end(C, sub_block);
+
+ LISTBASE_FOREACH (uiBut *, sub_but, &sub_block->buttons) {
+ menu_items_from_ui_create_item_from_button(
+ data, memarena, mt, drawstr_submenu, sub_but, wm_context);
+ }
+
+ if (region) {
+ BLI_remlink(&region->uiblocks, sub_block);
+ }
+ UI_block_free(NULL, sub_block);
+ }
+ }
+ if (region) {
+ BLI_remlink(&region->uiblocks, block);
+ }
+ UI_block_free(NULL, block);
+
+ /* Add key-map items as a second pass,
+ * so all menus are accessed from the header & top-bar before key shortcuts are expanded. */
+ if ((menu_stack == NULL) && (has_keymap_menu_items == false)) {
+ has_keymap_menu_items = true;
+ menu_types_add_from_keymap_items(
+ C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged);
+ }
+ }
+ }
+
+ LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) {
+ item->menu_parent = BLI_ghash_lookup(menu_parent_map, item->mt);
+ }
+
+ GHASH_ITER (iter, menu_parent_map) {
+ struct MenuSearch_Parent *menu_parent = BLI_ghashIterator_getValue(&iter);
+ menu_parent->parent = BLI_ghash_lookup(menu_parent_map, menu_parent->parent_mt);
+ }
+
+ /* NOTE: currently this builds the full path for each menu item,
+ * that could be moved into the parent menu. */
+
+ /* Set names as full paths. */
+ LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) {
+ BLI_assert(BLI_dynstr_get_len(dyn_str) == 0);
+
+ if (include_all_areas) {
+ BLI_dynstr_appendf(dyn_str,
+ "%s: ",
+ (item->wm_context != NULL) ?
+ space_type_ui_items[item->wm_context->space_type_ui_index].name :
+ global_menu_prefix);
+ }
+
+ if (item->menu_parent != NULL) {
+ struct MenuSearch_Parent *menu_parent = item->menu_parent;
+ menu_parent->temp_child = NULL;
+ while (menu_parent && menu_parent->parent) {
+ menu_parent->parent->temp_child = menu_parent;
+ menu_parent = menu_parent->parent;
+ }
+ while (menu_parent) {
+ BLI_dynstr_append(dyn_str, menu_parent->drawstr);
+ BLI_dynstr_append(dyn_str, " " MENU_SEP " ");
+ menu_parent = menu_parent->temp_child;
+ }
+ }
+ else {
+ const char *drawstr = BLI_ghash_lookup(menu_display_name_map, item->mt);
+ if (drawstr == NULL) {
+ drawstr = CTX_IFACE_(item->mt->translation_context, item->mt->label);
+ }
+ BLI_dynstr_append(dyn_str, drawstr);
+
+ wmKeyMapItem *kmi = BLI_ghash_lookup(menu_to_kmi, item->mt);
+ if (kmi != NULL) {
+ char kmi_str[128];
+ WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str));
+ BLI_dynstr_appendf(dyn_str, " (%s)", kmi_str);
+ }
+
+ BLI_dynstr_append(dyn_str, " " MENU_SEP " ");
+ }
+
+ /* Optional nested menu. */
+ if (item->drawstr_submenu != NULL) {
+ BLI_dynstr_append(dyn_str, item->drawstr_submenu);
+ BLI_dynstr_append(dyn_str, " " MENU_SEP " ");
+ }
+
+ BLI_dynstr_append(dyn_str, item->drawstr);
+
+ item->drawwstr_full = strdup_memarena_from_dynstr(memarena, dyn_str);
+ BLI_dynstr_clear(dyn_str);
+ }
+ BLI_dynstr_free(dyn_str);
+
+ /* Finally sort menu items.
+ *
+ * Note: we might want to keep the in-menu order, for now sort all. */
+ BLI_listbase_sort(&data->items, menu_item_sort_by_drawstr_full);
+
+ BLI_ghash_free(menu_parent_map, NULL, NULL);
+ BLI_ghash_free(menu_display_name_map, NULL, NULL);
+
+ BLI_ghash_free(menu_to_kmi, NULL, NULL);
+
+ BLI_gset_free(menu_tagged, NULL);
+
+ data->memarena = memarena;
+
+ if (include_all_areas) {
+ CTX_wm_area_set(C, area_init);
+ CTX_wm_region_set(C, region_init);
+
+ if (space_type_ui_items_free) {
+ MEM_freeN((void *)space_type_ui_items);
+ }
+ }
+
+ /* Include all operators for developers,
+ * since it can be handy to have a quick way to access any operator,
+ * including operators being developed which haven't yet been added into the interface.
+ *
+ * These are added after all menu items so developers still get normal behavior by default,
+ * unless searching for something that isn't already in a menu (or scroll down).
+ *
+ * Keep this behind a developer only check:
+ * - Many operators need options to be set to give useful results, see: T74157.
+ * - User who really prefer to list all operators can use #WM_OT_search_operator.
+ */
+ if (U.flag & USER_DEVELOPER_UI) {
+ menu_items_from_all_operators(C, data);
+ }
+
+ return data;
+}
+
+static void menu_search_arg_free_fn(void *data_v)
+{
+ struct MenuSearch_Data *data = data_v;
+ LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) {
+ switch (item->type) {
+ case MENU_SEARCH_TYPE_OP: {
+ if (item->op.opptr != NULL) {
+ WM_operator_properties_free(item->op.opptr);
+ MEM_freeN(item->op.opptr);
+ }
+ }
+ case MENU_SEARCH_TYPE_RNA: {
+ break;
+ }
+ }
+ }
+
+ BLI_memarena_free(data->memarena);
+
+ MEM_freeN(data);
+}
+
+static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
+{
+ struct MenuSearch_Item *item = arg2;
+ if (item == NULL) {
+ return;
+ }
+ if (item->state & UI_BUT_DISABLED) {
+ return;
+ }
+
+ ScrArea *area_prev = CTX_wm_area(C);
+ ARegion *region_prev = CTX_wm_region(C);
+
+ if (item->wm_context != NULL) {
+ CTX_wm_area_set(C, item->wm_context->area);
+ CTX_wm_region_set(C, item->wm_context->region);
+ }
+
+ switch (item->type) {
+ case MENU_SEARCH_TYPE_OP: {
+ CTX_store_set(C, item->op.context);
+ WM_operator_name_call_ptr(C, item->op.type, item->op.opcontext, item->op.opptr);
+ CTX_store_set(C, NULL);
+ break;
+ }
+ case MENU_SEARCH_TYPE_RNA: {
+ PointerRNA *ptr = &item->rna.ptr;
+ PropertyRNA *prop = item->rna.prop;
+ int index = item->rna.index;
+ const int prop_type = RNA_property_type(prop);
+ bool changed = false;
+
+ if (prop_type == PROP_BOOLEAN) {
+ const bool is_array = RNA_property_array_check(prop);
+ if (is_array) {
+ const bool value = RNA_property_boolean_get_index(ptr, prop, index);
+ RNA_property_boolean_set_index(ptr, prop, index, !value);
+ }
+ else {
+ const bool value = RNA_property_boolean_get(ptr, prop);
+ RNA_property_boolean_set(ptr, prop, !value);
+ }
+ changed = true;
+ }
+ else if (prop_type == PROP_ENUM) {
+ RNA_property_enum_set(ptr, prop, item->rna.enum_value);
+ changed = true;
+ }
+
+ if (changed) {
+ RNA_property_update(C, ptr, prop);
+ }
+ break;
+ }
+ }
+
+ if (item->wm_context != NULL) {
+ CTX_wm_area_set(C, area_prev);
+ CTX_wm_region_set(C, region_prev);
+ }
+}
+
+static void menu_search_update_fn(const bContext *UNUSED(C),
+ void *arg,
+ const char *str,
+ uiSearchItems *items)
+{
+ struct MenuSearch_Data *data = arg;
+ const size_t str_len = strlen(str);
+ const int words_max = (str_len / 2) + 1;
+ int(*words)[2] = BLI_array_alloca(words, words_max);
+
+ const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max);
+
+ for (struct MenuSearch_Item *item = data->items.first; item; item = item->next) {
+ int index;
+
+ /* match name against all search words */
+ for (index = 0; index < words_len; index++) {
+ if (!ui_str_has_word_prefix(item->drawwstr_full, str + words[index][0], words[index][1])) {
+ break;
+ }
+ }
+
+ if (index == words_len) {
+ if (!UI_search_item_add(items, item->drawwstr_full, item, item->icon, item->state)) {
+ break;
+ }
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Context Menu
+ *
+ * This uses a fake button to create a context menu,
+ * if this ever causes hard to solve bugs we may need to create
+ * a separate context menu just for the search, however this is fairly involved.
+ * \{ */
+
+static bool ui_search_menu_create_context_menu(struct bContext *C,
+ void *arg,
+ void *active,
+ const struct wmEvent *UNUSED(event))
+{
+ struct MenuSearch_Data *data = arg;
+ struct MenuSearch_Item *item = active;
+ bool has_menu = false;
+
+ memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data));
+ uiBut *but = &data->context_menu_data.but;
+ uiBlock *block = &data->context_menu_data.block;
+
+ but->block = block;
+
+ if (menu_items_to_ui_button(item, but)) {
+ ScrArea *area_prev = CTX_wm_area(C);
+ ARegion *region_prev = CTX_wm_region(C);
+
+ if (item->wm_context != NULL) {
+ CTX_wm_area_set(C, item->wm_context->area);
+ CTX_wm_region_set(C, item->wm_context->region);
+ }
+
+ if (ui_popup_context_menu_for_button(C, but)) {
+ has_menu = true;
+ }
+
+ if (item->wm_context != NULL) {
+ CTX_wm_area_set(C, area_prev);
+ CTX_wm_region_set(C, region_prev);
+ }
+ }
+
+ return has_menu;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tooltip
+ * \{ */
+
+static struct ARegion *ui_search_menu_create_tooltip(struct bContext *C,
+ struct ARegion *region,
+ void *arg,
+ void *active)
+{
+ struct MenuSearch_Data *data = arg;
+ struct MenuSearch_Item *item = active;
+
+ memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data));
+ uiBut *but = &data->context_menu_data.but;
+ uiBlock *block = &data->context_menu_data.block;
+ unit_m4(block->winmat);
+ block->aspect = 1;
+
+ but->block = block;
+
+ /* Place the fake button at the cursor so the tool-tip is places properly. */
+ float tip_init[2];
+ const wmEvent *event = CTX_wm_window(C)->eventstate;
+ tip_init[0] = event->x;
+ tip_init[1] = event->y - (UI_UNIT_Y / 2);
+ ui_window_to_block_fl(region, block, &tip_init[0], &tip_init[1]);
+
+ but->rect.xmin = tip_init[0];
+ but->rect.xmax = tip_init[0];
+ but->rect.ymin = tip_init[1];
+ but->rect.ymax = tip_init[1];
+
+ if (menu_items_to_ui_button(item, but)) {
+ ScrArea *area_prev = CTX_wm_area(C);
+ ARegion *region_prev = CTX_wm_region(C);
+
+ if (item->wm_context != NULL) {
+ CTX_wm_area_set(C, item->wm_context->area);
+ CTX_wm_region_set(C, item->wm_context->region);
+ }
+
+ ARegion *region_tip = UI_tooltip_create_from_button(C, region, but, false);
+
+ if (item->wm_context != NULL) {
+ CTX_wm_area_set(C, area_prev);
+ CTX_wm_region_set(C, region_prev);
+ }
+ return region_tip;
+ }
+
+ return NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Menu Search Template Public API
+ * \{ */
+
+void UI_but_func_menu_search(uiBut *but)
+{
+ bContext *C = but->block->evil_C;
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ /* When run from top-bar scan all areas in the current window. */
+ bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR));
+ struct MenuSearch_Data *data = menu_items_from_ui_create(
+ C, win, area, region, include_all_areas);
+ UI_but_func_search_set(but,
+ /* Generic callback. */
+ ui_searchbox_create_menu,
+ menu_search_update_fn,
+ data,
+ menu_search_arg_free_fn,
+ menu_search_exec_fn,
+ NULL);
+
+ UI_but_func_search_set_context_menu(but, ui_search_menu_create_context_menu);
+ UI_but_func_search_set_tooltip(but, ui_search_menu_create_tooltip);
+ UI_but_func_search_set_sep_string(but, MENU_SEP);
+}
+
+void uiTemplateMenuSearch(uiLayout *layout)
+{
+ uiBlock *block;
+ uiBut *but;
+ static char search[256] = "";
+
+ block = uiLayoutGetBlock(layout);
+ UI_block_layout_set_current(block, layout);
+
+ but = uiDefSearchBut(
+ block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, "");
+ UI_but_func_menu_search(but);
+}
+
+#undef MENU_SEP
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c
new file mode 100644
index 00000000000..cdf87103587
--- /dev/null
+++ b/source/blender/editors/interface/interface_template_search_operator.c
@@ -0,0 +1,151 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edinterface
+ *
+ * Search available operators by scanning all and checking their poll function.
+ * accessed via the #WM_OT_search_operator operator.
+ */
+
+#include <string.h>
+
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_shader_fx_types.h"
+#include "DNA_texture_types.h"
+
+#include "BLI_alloca.h"
+#include "BLI_ghash.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "interface_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Operator Search Template Implementation
+ * \{ */
+
+static void operator_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
+{
+ wmOperatorType *ot = arg2;
+
+ if (ot) {
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL);
+ }
+}
+
+static void operator_search_update_fn(const bContext *C,
+ void *UNUSED(arg),
+ const char *str,
+ uiSearchItems *items)
+{
+ GHashIterator iter;
+ const size_t str_len = strlen(str);
+ const int words_max = (str_len / 2) + 1;
+ int(*words)[2] = BLI_array_alloca(words, words_max);
+
+ const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max);
+
+ for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter);
+ BLI_ghashIterator_step(&iter)) {
+ wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
+ const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name);
+ int index;
+
+ if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) {
+ continue;
+ }
+
+ /* match name against all search words */
+ for (index = 0; index < words_len; index++) {
+ if (!ui_str_has_word_prefix(ot_ui_name, str + words[index][0], words[index][1])) {
+ break;
+ }
+ }
+
+ if (index == words_len) {
+ if (WM_operator_poll((bContext *)C, ot)) {
+ char name[256];
+ int len = strlen(ot_ui_name);
+
+ /* display name for menu, can hold hotkey */
+ BLI_strncpy(name, ot_ui_name, sizeof(name));
+
+ /* check for hotkey */
+ if (len < sizeof(name) - 6) {
+ if (WM_key_event_operator_string(C,
+ ot->idname,
+ WM_OP_EXEC_DEFAULT,
+ NULL,
+ true,
+ &name[len + 1],
+ sizeof(name) - len - 1)) {
+ name[len] = UI_SEP_CHAR;
+ }
+ }
+
+ if (!UI_search_item_add(items, name, ot, ICON_NONE, 0)) {
+ break;
+ }
+ }
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Operator Search Template API
+ * \{ */
+
+void UI_but_func_operator_search(uiBut *but)
+{
+ UI_but_func_search_set(but,
+ ui_searchbox_create_operator,
+ operator_search_update_fn,
+ NULL,
+ false,
+ operator_search_exec_fn,
+ NULL);
+}
+
+void uiTemplateOperatorSearch(uiLayout *layout)
+{
+ uiBlock *block;
+ uiBut *but;
+ static char search[256] = "";
+
+ block = uiLayoutGetBlock(layout);
+ UI_block_layout_set_current(block, layout);
+
+ but = uiDefSearchBut(
+ block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, "");
+ UI_but_func_operator_search(but);
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 4c86e3252ed..0e67f943ee6 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -19,34 +19,32 @@
*/
#include <ctype.h>
-#include <stdlib.h>
#include <stddef.h>
+#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
+#include "DNA_brush_types.h"
#include "DNA_cachefile_types.h"
#include "DNA_constraint_types.h"
+#include "DNA_curveprofile_types.h"
+#include "DNA_gpencil_modifier_types.h"
#include "DNA_node_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_object_force_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_gpencil_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_shader_fx_types.h"
-#include "DNA_curveprofile_types.h"
+#include "DNA_texture_types.h"
-#include "BLI_utildefines.h"
-#include "BLI_alloca.h"
-#include "BLI_string.h"
-#include "BLI_ghash.h"
-#include "BLI_rect.h"
-#include "BLI_math.h"
-#include "BLI_listbase.h"
#include "BLI_fnmatch.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_path_util.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_timecode.h"
+#include "BLI_utildefines.h"
#include "BLF_api.h"
#include "BLT_translation.h"
@@ -56,21 +54,20 @@
#include "BKE_colortools.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
+#include "BKE_curveprofile.h"
#include "BKE_global.h"
#include "BKE_gpencil_modifier.h"
-#include "BKE_idcode.h"
#include "BKE_idprop.h"
+#include "BKE_idtype.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_packedFile.h"
-#include "BKE_paint.h"
#include "BKE_particle.h"
-#include "BKE_curveprofile.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -80,9 +77,9 @@
#include "DEG_depsgraph_build.h"
#include "ED_fileselect.h"
-#include "ED_screen.h"
#include "ED_object.h"
#include "ED_render.h"
+#include "ED_screen.h"
#include "ED_undo.h"
#include "RNA_access.h"
@@ -206,9 +203,9 @@ static void template_add_button_search_menu(const bContext *C,
static uiBlock *template_common_search_menu(const bContext *C,
ARegion *region,
- uiButSearchFunc search_func,
+ uiButSearchUpdateFn search_update_fn,
void *search_arg,
- uiButHandleFunc handle_func,
+ uiButHandleFunc search_exec_fn,
void *active_item,
const int preview_rows,
const int preview_cols,
@@ -280,8 +277,13 @@ static uiBlock *template_common_search_menu(const bContext *C,
0,
"");
}
- UI_but_func_search_set(
- but, ui_searchbox_create_generic, search_func, search_arg, false, handle_func, active_item);
+ UI_but_func_search_set(but,
+ ui_searchbox_create_generic,
+ search_update_fn,
+ search_arg,
+ NULL,
+ search_exec_fn,
+ active_item);
UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
UI_block_direction_set(block, UI_DIR_DOWN);
@@ -313,7 +315,7 @@ typedef struct TemplateID {
} TemplateID;
/* Search browse menu, assign */
-static void template_ID_set_property_cb(bContext *C, void *arg_template, void *item)
+static void template_ID_set_property_exec_fn(bContext *C, void *arg_template, void *item)
{
TemplateID *template_ui = (TemplateID *)arg_template;
@@ -363,7 +365,7 @@ static bool id_search_add(const bContext *C,
int iconid = ui_id_icon_get(C, id, template_ui->preview);
- if (false == UI_search_item_add(items, name_ui, id, iconid)) {
+ if (!UI_search_item_add(items, name_ui, id, iconid, 0)) {
return false;
}
}
@@ -444,11 +446,12 @@ static void id_search_cb_objects_from_scene(const bContext *C,
}
/* ID Search browse menu, open */
-static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
+static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem)
{
static TemplateID template_ui;
PointerRNA active_item_ptr;
- void (*id_search_cb_p)(const bContext *, void *, const char *, uiSearchItems *) = id_search_cb;
+ void (*id_search_update_fn)(
+ const bContext *, void *, const char *, uiSearchItems *) = id_search_cb;
/* arg_litem is malloced, can be freed by parent button */
template_ui = *((TemplateID *)arg_litem);
@@ -458,16 +461,16 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
/* Currently only used for objects. */
if (template_ui.idcode == ID_OB) {
if (template_ui.filter == UI_TEMPLATE_ID_FILTER_AVAILABLE) {
- id_search_cb_p = id_search_cb_objects_from_scene;
+ id_search_update_fn = id_search_cb_objects_from_scene;
}
}
}
return template_common_search_menu(C,
- ar,
- id_search_cb_p,
+ region,
+ id_search_update_fn,
&template_ui,
- template_ID_set_property_cb,
+ template_ID_set_property_exec_fn,
active_item_ptr.data,
template_ui.prv_rows,
template_ui.prv_cols,
@@ -523,6 +526,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
if (id && CTX_wm_window(C)->eventstate->shift) {
/* only way to force-remove data (on save) */
+ id_us_clear_real(id);
id_fake_user_clear(id);
id->us = 0;
}
@@ -544,10 +548,10 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
case UI_ID_LOCAL:
if (id) {
Main *bmain = CTX_data_main(C);
- if (BKE_override_library_is_enabled() && CTX_wm_window(C)->eventstate->shift) {
+ if (BKE_lib_override_library_is_enabled() && CTX_wm_window(C)->eventstate->shift) {
if (ID_IS_OVERRIDABLE_LIBRARY(id)) {
/* Only remap that specific ID usage to overriding local data-block. */
- ID *override_id = BKE_override_library_create_from_id(bmain, id, false);
+ ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false);
if (override_id != NULL) {
BKE_main_id_clear_newpoins(bmain);
@@ -557,7 +561,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
}
}
else {
- if (id_make_local(bmain, id, false, false)) {
+ if (BKE_lib_id_make_local(bmain, id, false, 0)) {
BKE_main_id_clear_newpoins(bmain);
/* reassign to get get proper updates/notifiers */
@@ -570,7 +574,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_OVERRIDE:
if (id && id->override_library) {
- BKE_override_library_free(&id->override_library, true);
+ BKE_lib_override_library_free(&id->override_library, true);
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
@@ -591,11 +595,9 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
DEG_relations_tag_update(bmain);
}
else {
- if (id) {
- Main *bmain = CTX_data_main(C);
- id_single_user(C, id, &template_ui->ptr, template_ui->prop);
- DEG_relations_tag_update(bmain);
- }
+ Main *bmain = CTX_data_main(C);
+ id_single_user(C, id, &template_ui->ptr, template_ui->prop);
+ DEG_relations_tag_update(bmain);
}
}
break;
@@ -670,6 +672,14 @@ static const char *template_id_browse_tip(const StructRNA *type)
return N_("Browse Workspace to be linked");
case ID_LP:
return N_("Browse LightProbe to be linked");
+ case ID_HA:
+ return N_("Browse Hair Data to be linked");
+ case ID_PT:
+ return N_("Browse Point Cloud Data to be linked");
+ case ID_VO:
+ return N_("Browse Volume Data to be linked");
+ case ID_SIM:
+ return N_("Browse Simulation to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -683,10 +693,12 @@ static const char *template_id_browse_tip(const StructRNA *type)
static const char *template_id_context(StructRNA *type)
{
if (type) {
- return BKE_idcode_to_translation_context(RNA_type_to_ID_code(type));
+ return BKE_idtype_idcode_to_translation_context(RNA_type_to_ID_code(type));
}
return BLT_I18NCONTEXT_DEFAULT;
}
+#else
+# define template_id_context(type) 0
#endif
static uiBut *template_id_def_new_but(uiBlock *block,
@@ -732,7 +744,14 @@ static uiBut *template_id_def_new_but(uiBlock *block,
BLT_I18NCONTEXT_ID_GPENCIL,
BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
BLT_I18NCONTEXT_ID_WORKSPACE,
- BLT_I18NCONTEXT_ID_LIGHTPROBE, );
+ BLT_I18NCONTEXT_ID_LIGHTPROBE,
+ BLT_I18NCONTEXT_ID_HAIR,
+ BLT_I18NCONTEXT_ID_POINTCLOUD,
+ BLT_I18NCONTEXT_ID_VOLUME,
+ BLT_I18NCONTEXT_ID_SIMULATION, );
+ /* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters,
+ * check the definition to see if a new call must be added when the limit
+ * is exceeded. */
if (newop) {
but = uiDefIconTextButO(block,
@@ -813,8 +832,8 @@ static void template_ID(bContext *C,
}
if (text) {
- /* Add label resepecting the seperated layout property split state. */
- layout = uiItemL_respect_property_split(layout, text, ICON_NONE);
+ /* Add label resepecting the separated layout property split state. */
+ uiItemL_respect_property_split(layout, text, ICON_NONE);
}
if (flag & UI_ID_BROWSE) {
@@ -879,7 +898,7 @@ static void template_ID(bContext *C,
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
else {
- const bool disabled = (!id_make_local(CTX_data_main(C), id, true /* test */, false) ||
+ const bool disabled = (!BKE_lib_id_make_local(CTX_data_main(C), id, true /* test */, 0) ||
(idfrom && idfrom->lib));
but = uiDefIconBut(block,
UI_BTYPE_BUT,
@@ -894,7 +913,7 @@ static void template_ID(bContext *C,
0,
0,
0,
- BKE_override_library_is_enabled() ?
+ BKE_lib_override_library_is_enabled() ?
TIP_("Direct linked library data-block, click to make local, "
"Shift + Click to create a library override") :
TIP_("Direct linked library data-block, click to make local"));
@@ -1137,12 +1156,12 @@ static void template_ID_tabs(bContext *C,
const int but_height = UI_UNIT_Y * 1.1;
uiBlock *block = uiLayoutGetBlock(layout);
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
ListBase ordered;
BKE_id_ordered_list(&ordered, template->idlb);
- for (LinkData *link = ordered.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &ordered) {
ID *id = link->data;
const int name_width = UI_fontstyle_string_width(&style->widgetlabel, id->name + 2);
const int but_width = name_width + UI_UNIT_X;
@@ -1163,7 +1182,7 @@ static void template_ID_tabs(bContext *C,
0.0f,
0.0f,
"");
- UI_but_funcN_set(&tab->but, template_ID_set_property_cb, MEM_dupallocN(template), id);
+ UI_but_funcN_set(&tab->but, template_ID_set_property_exec_fn, MEM_dupallocN(template), id);
tab->but.custom_data = (void *)id;
tab->but.dragpoin = id;
tab->menu = mt;
@@ -1509,7 +1528,7 @@ typedef struct TemplateSearch {
int preview_rows, preview_cols;
} TemplateSearch;
-static void template_search_handle_cb(bContext *C, void *arg_template, void *item)
+static void template_search_exec_fn(bContext *C, void *arg_template, void *item)
{
TemplateSearch *template_search = arg_template;
uiRNACollectionSearch *coll_search = &template_search->search_data;
@@ -1533,9 +1552,9 @@ static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_tem
return template_common_search_menu(C,
region,
- ui_rna_collection_search_cb,
+ ui_rna_collection_search_update_fn,
&template_search,
- template_search_handle_cb,
+ template_search_exec_fn,
active_ptr.data,
template_search.preview_rows,
template_search.preview_cols,
@@ -1799,14 +1818,14 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
{
Object *ob = ob_v;
ModifierData *md = md_v;
- ModifierData *nmd = modifier_new(md->type);
+ ModifierData *nmd = BKE_modifier_new(md->type);
- modifier_copyData(md, nmd);
+ BKE_modifier_copydata(md, nmd);
nmd->mode &= ~eModifierMode_Virtual;
BLI_addhead(&ob->modifiers, nmd);
- modifier_unique_name(&ob->modifiers, nmd);
+ BKE_modifier_unique_name(&ob->modifiers, nmd);
ob->partype = PAROBJECT;
@@ -1816,20 +1835,26 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
ED_undo_push(C, "Modifier convert to real");
}
-static int modifier_can_delete(ModifierData *md)
+static bool modifier_can_delete(ModifierData *md)
{
/* fluid particle modifier can't be deleted here */
if (md->type == eModifierType_ParticleSystem) {
short particle_type = ((ParticleSystemModifierData *)md)->psys->part->type;
- if (particle_type == PART_FLUID || particle_type == PART_FLUID_FLIP ||
- particle_type == PART_FLUID_FOAM || particle_type == PART_FLUID_SPRAY ||
- particle_type == PART_FLUID_BUBBLE || particle_type == PART_FLUID_TRACER ||
- particle_type == PART_FLUID_SPRAYFOAM || particle_type == PART_FLUID_SPRAYBUBBLE ||
- particle_type == PART_FLUID_FOAMBUBBLE || particle_type == PART_FLUID_SPRAYFOAMBUBBLE) {
- return 0;
+ if (ELEM(particle_type,
+ PART_FLUID,
+ PART_FLUID_FLIP,
+ PART_FLUID_FOAM,
+ PART_FLUID_SPRAY,
+ PART_FLUID_BUBBLE,
+ PART_FLUID_TRACER,
+ PART_FLUID_SPRAYFOAM,
+ PART_FLUID_SPRAYBUBBLE,
+ PART_FLUID_FOAMBUBBLE,
+ PART_FLUID_SPRAYFOAMBUBBLE)) {
+ return false;
}
}
- return 1;
+ return true;
}
/* Check whether Modifier is a simulation or not,
@@ -1864,7 +1889,7 @@ static uiLayout *draw_modifier(uiLayout *layout,
int cageIndex,
int lastCageIndex)
{
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
PointerRNA ptr;
uiBut *but;
uiBlock *block;
@@ -1958,9 +1983,9 @@ static uiLayout *draw_modifier(uiLayout *layout,
}
if (ob->type == OB_MESH) {
- if (modifier_supportsCage(scene, md) && (index <= lastCageIndex)) {
+ if (BKE_modifier_supports_cage(scene, md) && (index <= lastCageIndex)) {
sub = uiLayoutRow(row, true);
- if (index < cageIndex || !modifier_couldBeCage(scene, md)) {
+ if (index < cageIndex || !BKE_modifier_couldbe_cage(scene, md)) {
uiLayoutSetActive(sub, false);
}
uiItemR(sub, &ptr, "show_on_cage", 0, "", ICON_NONE);
@@ -2056,7 +2081,7 @@ static uiLayout *draw_modifier(uiLayout *layout,
"apply_as",
MODIFIER_APPLY_DATA);
- if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) {
+ if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) {
uiItemEnumO(row,
"OBJECT_OT_modifier_apply",
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
@@ -2123,10 +2148,10 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
/* find modifier and draw it */
- cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
+ cageIndex = BKE_modifiers_get_cage_index(scene, ob, &lastCageIndex, 0);
/* XXX virtual modifiers are not accessible for python */
- vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ vmd = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
for (i = 0; vmd; i++, vmd = vmd->next) {
if (md == vmd) {
@@ -2148,7 +2173,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
static uiLayout *gpencil_draw_modifier(uiLayout *layout, Object *ob, GpencilModifierData *md)
{
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
PointerRNA ptr;
uiBlock *block;
uiLayout *box, *column, *row, *sub;
@@ -2225,6 +2250,10 @@ static uiLayout *gpencil_draw_modifier(uiLayout *layout, Object *ob, GpencilModi
0,
"apply_as",
MODIFIER_APPLY_DATA);
+
+ UI_block_lock_clear(block);
+ UI_block_lock_set(block, ob && ID_IS_LINKED(ob), ERROR_LIBDATA_MESSAGE);
+
uiItemO(row,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"),
ICON_NONE,
@@ -2287,7 +2316,7 @@ uiLayout *uiTemplateGpencilModifier(uiLayout *layout, bContext *UNUSED(C), Point
static uiLayout *gpencil_draw_shaderfx(uiLayout *layout, Object *ob, ShaderFxData *md)
{
- const ShaderFxTypeInfo *mti = BKE_shaderfxType_getInfo(md->type);
+ const ShaderFxTypeInfo *mti = BKE_shaderfx_get_info(md->type);
PointerRNA ptr;
uiBlock *block;
uiLayout *box, *column, *row, *sub;
@@ -2404,21 +2433,196 @@ uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA *
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Operator Redo Buttons Template
+/** \name Operator Property Buttons Template
* \{ */
-static void template_operator_redo_property_buts_draw(
- const bContext *C, wmOperator *op, uiLayout *layout, int layout_flags, bool *r_has_advanced)
+typedef struct uiTemplateOperatorPropertyPollParam {
+ const bContext *C;
+ wmOperator *op;
+ short flag;
+} uiTemplateOperatorPropertyPollParam;
+
+#ifdef USE_OP_RESET_BUT
+static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C),
+ void *op_pt,
+ void *UNUSED(arg_dummy2))
+{
+ WM_operator_properties_reset((wmOperator *)op_pt);
+}
+#endif
+
+static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *prop,
+ void *user_data)
+{
+ uiTemplateOperatorPropertyPollParam *params = user_data;
+
+ if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) &&
+ (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) {
+ return false;
+ }
+ return params->op->type->poll_property(params->C, params->op, prop);
+}
+
+static eAutoPropButsReturn template_operator_property_buts_draw_single(
+ const bContext *C,
+ wmOperator *op,
+ uiLayout *layout,
+ const eButLabelAlign label_align,
+ int layout_flags)
+{
+ uiBlock *block = uiLayoutGetBlock(layout);
+ eAutoPropButsReturn return_info = 0;
+
+ if (!op->properties) {
+ IDPropertyTemplate val = {0};
+ op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
+ }
+
+ /* poll() on this operator may still fail,
+ * at the moment there is no nice feedback when this happens just fails silently. */
+ if (!WM_operator_repeat_check(C, op)) {
+ UI_block_lock_set(block, true, "Operator can't' redo");
+ return return_info;
+ }
+ else {
+ /* useful for macros where only one of the steps can't be re-done */
+ UI_block_lock_clear(block);
+ }
+
+ if (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) {
+ uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
+ }
+
+ /* menu */
+ if (op->type->flag & OPTYPE_PRESET) {
+ /* XXX, no simple way to get WM_MT_operator_presets.bl_label
+ * from python! Label remains the same always! */
+ PointerRNA op_ptr;
+ uiLayout *row;
+
+ block->ui_operator = op;
+
+ row = uiLayoutRow(layout, true);
+ uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE);
+
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false);
+ uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_string_set(&op_ptr, "operator", op->type->idname);
+
+ uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_string_set(&op_ptr, "operator", op->type->idname);
+ RNA_boolean_set(&op_ptr, "remove_active", true);
+ }
+
+ if (op->type->ui) {
+ op->layout = layout;
+ op->type->ui((bContext *)C, op);
+ op->layout = NULL;
+
+ /* UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. We could
+ * allow ot.ui callback to return this, but not needed right now. */
+ }
+ else {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+ uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags};
+ const bool use_prop_split = (layout_flags & UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT) == 0;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ uiLayoutSetPropSep(layout, use_prop_split);
+ uiLayoutSetPropDecorate(layout, false);
+
+ /* main draw call */
+ return_info = uiDefAutoButsRNA(
+ layout,
+ &ptr,
+ op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL,
+ op->type->poll_property ? &user_data : NULL,
+ op->type->prop,
+ label_align,
+ (layout_flags & UI_TEMPLATE_OP_PROPS_COMPACT));
+
+ if ((return_info & UI_PROP_BUTS_NONE_ADDED) &&
+ (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) {
+ uiItemL(layout, IFACE_("No Properties"), ICON_NONE);
+ }
+ }
+
+#ifdef USE_OP_RESET_BUT
+ /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled
+ * but this is not so important if this button is drawn in those cases
+ * (which isn't all that likely anyway) - campbell */
+ if (op->properties->len) {
+ uiBut *but;
+ uiLayout *col; /* needed to avoid alignment errors with previous buttons */
+
+ col = uiLayoutColumn(layout, false);
+ block = uiLayoutGetBlock(col);
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_FILE_REFRESH,
+ IFACE_("Reset"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Reset operator defaults"));
+ UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL);
+ }
+#endif
+
+ /* set various special settings for buttons */
+
+ /* Only do this if we're not refreshing an existing UI. */
+ if (block->oldblock == NULL) {
+ const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0;
+ uiBut *but;
+
+ for (but = block->buttons.first; but; but = but->next) {
+ /* no undo for buttons for operator redo panels */
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+
+ /* only for popups, see [#36109] */
+
+ /* if button is operator's default property, and a text-field, enable focus for it
+ * - this is used for allowing operators with popups to rename stuff with fewer clicks
+ */
+ if (is_popup) {
+ if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) {
+ UI_but_focus_on_enter_event(CTX_wm_window(C), but);
+ }
+ }
+ }
+ }
+
+ return return_info;
+}
+
+static void template_operator_property_buts_draw_recursive(const bContext *C,
+ wmOperator *op,
+ uiLayout *layout,
+ const eButLabelAlign label_align,
+ int layout_flags,
+ bool *r_has_advanced)
{
if (op->type->flag & OPTYPE_MACRO) {
- for (wmOperator *macro_op = op->macro.first; macro_op; macro_op = macro_op->next) {
- template_operator_redo_property_buts_draw(C, macro_op, layout, layout_flags, r_has_advanced);
+ LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) {
+ template_operator_property_buts_draw_recursive(
+ C, macro_op, layout, label_align, layout_flags, r_has_advanced);
}
}
else {
/* Might want to make label_align adjustable somehow. */
- eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs(
- C, layout, op, UI_BUT_LABEL_ALIGN_NONE, layout_flags);
+ eAutoPropButsReturn return_info = template_operator_property_buts_draw_single(
+ C, op, layout, label_align, layout_flags);
if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) {
if (r_has_advanced) {
*r_has_advanced = true;
@@ -2427,6 +2631,61 @@ static void template_operator_redo_property_buts_draw(
}
}
+static bool ui_layout_operator_properties_only_booleans(const bContext *C,
+ wmWindowManager *wm,
+ wmOperator *op,
+ int layout_flags)
+{
+ if (op->type->flag & OPTYPE_MACRO) {
+ LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) {
+ if (!ui_layout_operator_properties_only_booleans(C, wm, macro_op, layout_flags)) {
+ return false;
+ }
+ }
+ }
+ else {
+ uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags};
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ RNA_STRUCT_BEGIN (&ptr, prop) {
+ if (RNA_property_flag(prop) & PROP_HIDDEN) {
+ continue;
+ }
+ if (op->type->poll_property &&
+ !ui_layout_operator_buts_poll_property(&ptr, prop, &user_data)) {
+ continue;
+ }
+ if (RNA_property_type(prop) != PROP_BOOLEAN) {
+ return false;
+ }
+ }
+ RNA_STRUCT_END;
+ }
+
+ return true;
+}
+
+/**
+ * Draw Operator property buttons for redoing execution with different settings.
+ * This function does not initialize the layout,
+ * functions can be called on the layout before and after.
+ */
+void uiTemplateOperatorPropertyButs(
+ const bContext *C, uiLayout *layout, wmOperator *op, eButLabelAlign label_align, short flag)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ /* If there are only checkbox items, don't use split layout by default. It looks weird if the
+ * checkboxes only use half the width. */
+ if (ui_layout_operator_properties_only_booleans(C, wm, op, flag)) {
+ flag |= UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT;
+ }
+
+ template_operator_property_buts_draw_recursive(C, op, layout, label_align, flag, NULL);
+}
+
void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
{
wmOperator *op = WM_operator_last_redo(C);
@@ -2459,8 +2718,8 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
#endif
UI_block_func_handle_set(block, ED_undo_operator_repeat_cb_evt, op);
- template_operator_redo_property_buts_draw(
- C, op, layout, layout_flags, NULL /* &has_advanced */);
+ template_operator_property_buts_draw_recursive(
+ C, op, layout, UI_BUT_LABEL_ALIGN_NONE, layout_flags, NULL /* &has_advanced */);
/* Warning! this leaves the handle function for any other users of this block. */
#if 0
@@ -2723,7 +2982,7 @@ void uiTemplatePreview(uiLayout *layout,
uiLayout *row, *col;
uiBlock *block;
uiPreview *ui_preview = NULL;
- ARegion *ar;
+ ARegion *region;
Material *ma = NULL;
Tex *tex = (Tex *)id;
@@ -2769,19 +3028,20 @@ void uiTemplatePreview(uiLayout *layout,
if (!preview_id || (preview_id[0] == '\0')) {
/* If no identifier given, generate one from ID type. */
- BLI_snprintf(_preview_id, UI_MAX_NAME_STR, "uiPreview_%s", BKE_idcode_to_name(GS(id->name)));
+ BLI_snprintf(
+ _preview_id, UI_MAX_NAME_STR, "uiPreview_%s", BKE_idtype_idcode_to_name(GS(id->name)));
preview_id = _preview_id;
}
/* Find or add the uiPreview to the current Region. */
- ar = CTX_wm_region(C);
- ui_preview = BLI_findstring(&ar->ui_previews, preview_id, offsetof(uiPreview, preview_id));
+ region = CTX_wm_region(C);
+ ui_preview = BLI_findstring(&region->ui_previews, preview_id, offsetof(uiPreview, preview_id));
if (!ui_preview) {
ui_preview = MEM_callocN(sizeof(uiPreview), "uiPreview");
BLI_strncpy(ui_preview->preview_id, preview_id, sizeof(ui_preview->preview_id));
ui_preview->height = (short)(UI_UNIT_Y * 7.6f);
- BLI_addtail(&ar->ui_previews, ui_preview);
+ BLI_addtail(&region->ui_previews, ui_preview);
}
if (ui_preview->height < UI_UNIT_Y) {
@@ -3047,14 +3307,14 @@ static void colorband_tools_dofunc(bContext *C, void *coba_v, int event)
ED_region_tag_redraw(CTX_wm_region(C));
}
-static uiBlock *colorband_tools_func(bContext *C, ARegion *ar, void *coba_v)
+static uiBlock *colorband_tools_func(bContext *C, ARegion *region, void *coba_v)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
ColorBand *coba = coba_v;
uiBlock *block;
short yco = 0, menuwidth = 10 * UI_UNIT_X;
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS_PULLDOWN);
+ block = UI_block_begin(C, region, __func__, UI_EMBOSS_PULLDOWN);
UI_block_func_butmenu_set(block, colorband_tools_dofunc, coba);
uiLayout *layout = UI_block_layout(block,
@@ -3443,7 +3703,7 @@ typedef struct IconViewMenuArgs {
} IconViewMenuArgs;
/* ID Search browse menu, open */
-static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem)
+static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *region, void *arg_litem)
{
static IconViewMenuArgs args;
uiBlock *block;
@@ -3459,7 +3719,7 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem)
w = UI_UNIT_X * (args.icon_scale);
h = UI_UNIT_X * (args.icon_scale + args.show_labels);
- block = UI_block_begin(C, ar, "_popup", UI_EMBOSS_PULLDOWN);
+ block = UI_block_begin(C, region, "_popup", UI_EMBOSS_PULLDOWN);
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NO_FLIP);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
@@ -3867,14 +4127,14 @@ static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
}
/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
-static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v)
+static uiBlock *curvemap_clipping_func(bContext *C, ARegion *region, void *cumap_v)
{
CurveMapping *cumap = cumap_v;
uiBlock *block;
uiBut *bt;
float width = 8 * UI_UNIT_X;
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, region, __func__, UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
@@ -4015,12 +4275,12 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
}
static uiBlock *curvemap_tools_func(
- bContext *C, ARegion *ar, CurveMapping *cumap, bool show_extend, int reset_mode)
+ bContext *C, ARegion *region, CurveMapping *cumap, bool show_extend, int reset_mode)
{
uiBlock *block;
short yco = 0, menuwidth = 10 * UI_UNIT_X;
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, region, __func__, UI_EMBOSS);
UI_block_func_butmenu_set(block, curvemap_tools_dofunc, cumap);
{
@@ -4143,24 +4403,24 @@ static uiBlock *curvemap_tools_func(
return block;
}
-static uiBlock *curvemap_tools_posslope_func(bContext *C, ARegion *ar, void *cumap_v)
+static uiBlock *curvemap_tools_posslope_func(bContext *C, ARegion *region, void *cumap_v)
{
- return curvemap_tools_func(C, ar, cumap_v, true, UICURVE_FUNC_RESET_POS);
+ return curvemap_tools_func(C, region, cumap_v, true, UICURVE_FUNC_RESET_POS);
}
-static uiBlock *curvemap_tools_negslope_func(bContext *C, ARegion *ar, void *cumap_v)
+static uiBlock *curvemap_tools_negslope_func(bContext *C, ARegion *region, void *cumap_v)
{
- return curvemap_tools_func(C, ar, cumap_v, true, UICURVE_FUNC_RESET_NEG);
+ return curvemap_tools_func(C, region, cumap_v, true, UICURVE_FUNC_RESET_NEG);
}
-static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *ar, void *cumap_v)
+static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *region, void *cumap_v)
{
- return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_NEG);
+ return curvemap_tools_func(C, region, cumap_v, false, UICURVE_FUNC_RESET_NEG);
}
-static uiBlock *curvemap_brush_tools_negslope_func(bContext *C, ARegion *ar, void *cumap_v)
+static uiBlock *curvemap_brush_tools_negslope_func(bContext *C, ARegion *region, void *cumap_v)
{
- return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_POS);
+ return curvemap_tools_func(C, region, cumap_v, false, UICURVE_FUNC_RESET_POS);
}
static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
@@ -4563,14 +4823,14 @@ static void CurveProfile_presets_dofunc(bContext *C, void *profile_v, int event)
ED_region_tag_redraw(CTX_wm_region(C));
}
-static uiBlock *CurveProfile_presets_func(bContext *C, ARegion *ar, CurveProfile *profile)
+static uiBlock *CurveProfile_presets_func(bContext *C, ARegion *region, CurveProfile *profile)
{
uiBlock *block;
short yco = 0;
short menuwidth = 12 * UI_UNIT_X;
menuwidth = 0;
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, region, __func__, UI_EMBOSS);
UI_block_func_butmenu_set(block, CurveProfile_presets_dofunc, profile);
uiDefIconTextBut(block,
@@ -4607,7 +4867,7 @@ static uiBlock *CurveProfile_presets_func(bContext *C, ARegion *ar, CurveProfile
UI_BTYPE_BUT_MENU,
1,
ICON_BLANK1,
- IFACE_("Cornice Moulding"),
+ IFACE_("Cornice Molding"),
0,
yco -= UI_UNIT_Y,
menuwidth,
@@ -4622,7 +4882,7 @@ static uiBlock *CurveProfile_presets_func(bContext *C, ARegion *ar, CurveProfile
UI_BTYPE_BUT_MENU,
1,
ICON_BLANK1,
- IFACE_("Crown Moulding"),
+ IFACE_("Crown Molding"),
0,
yco -= UI_UNIT_Y,
menuwidth,
@@ -4655,9 +4915,9 @@ static uiBlock *CurveProfile_presets_func(bContext *C, ARegion *ar, CurveProfile
return block;
}
-static uiBlock *CurveProfile_buttons_presets(bContext *C, ARegion *ar, void *profile_v)
+static uiBlock *CurveProfile_buttons_presets(bContext *C, ARegion *region, void *profile_v)
{
- return CurveProfile_presets_func(C, ar, (CurveProfile *)profile_v);
+ return CurveProfile_presets_func(C, region, (CurveProfile *)profile_v);
}
/* Only for CurveProfile tools block */
@@ -4683,13 +4943,13 @@ static void CurveProfile_tools_dofunc(bContext *C, void *profile_v, int event)
ED_region_tag_redraw(CTX_wm_region(C));
}
-static uiBlock *CurveProfile_tools_func(bContext *C, ARegion *ar, CurveProfile *profile)
+static uiBlock *CurveProfile_tools_func(bContext *C, ARegion *region, CurveProfile *profile)
{
uiBlock *block;
short yco = 0;
short menuwidth = 10 * UI_UNIT_X;
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, region, __func__, UI_EMBOSS);
UI_block_func_butmenu_set(block, CurveProfile_tools_dofunc, profile);
uiDefIconTextBut(block,
@@ -4729,9 +4989,9 @@ static uiBlock *CurveProfile_tools_func(bContext *C, ARegion *ar, CurveProfile *
return block;
}
-static uiBlock *CurveProfile_buttons_tools(bContext *C, ARegion *ar, void *profile_v)
+static uiBlock *CurveProfile_buttons_tools(bContext *C, ARegion *region, void *profile_v)
{
- return CurveProfile_tools_func(C, ar, (CurveProfile *)profile_v);
+ return CurveProfile_tools_func(C, region, (CurveProfile *)profile_v);
}
static void CurveProfile_buttons_zoom_in(bContext *C, void *profile_v, void *UNUSED(arg))
@@ -5385,6 +5645,21 @@ void uiTemplateColorPicker(uiLayout *layout,
}
}
+static void ui_template_palette_menu(bContext *UNUSED(C), uiLayout *layout, void *UNUSED(but_p))
+{
+ uiLayout *row;
+
+ uiItemL(layout, IFACE_("Sort by:"), ICON_NONE);
+ row = uiLayoutRow(layout, false);
+ uiItemEnumO_value(row, IFACE_("Hue"), ICON_NONE, "PALETTE_OT_sort", "type", 1);
+ row = uiLayoutRow(layout, false);
+ uiItemEnumO_value(row, IFACE_("Saturation"), ICON_NONE, "PALETTE_OT_sort", "type", 2);
+ row = uiLayoutRow(layout, false);
+ uiItemEnumO_value(row, IFACE_("Value"), ICON_NONE, "PALETTE_OT_sort", "type", 3);
+ row = uiLayoutRow(layout, false);
+ uiItemEnumO_value(row, IFACE_("Luminance"), ICON_NONE, "PALETTE_OT_sort", "type", 4);
+}
+
void uiTemplatePalette(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
@@ -5396,6 +5671,8 @@ void uiTemplatePalette(uiLayout *layout,
PaletteColor *color;
uiBlock *block;
uiLayout *col;
+ uiBut *but = NULL;
+
int row_cols = 0, col_id = 0;
int cols_per_row = MAX2(uiLayoutGetWidth(layout) / UI_UNIT_X, 1);
@@ -5437,6 +5714,37 @@ void uiTemplatePalette(uiLayout *layout,
UI_UNIT_X,
UI_UNIT_Y,
NULL);
+ if (color) {
+ but = uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "PALETTE_OT_color_move",
+ WM_OP_INVOKE_DEFAULT,
+ ICON_TRIA_UP,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+ UI_but_operator_ptr_get(but);
+ RNA_enum_set(but->opptr, "type", -1);
+
+ but = uiDefIconButO(block,
+ UI_BTYPE_BUT,
+ "PALETTE_OT_color_move",
+ WM_OP_INVOKE_DEFAULT,
+ ICON_TRIA_DOWN,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL);
+ UI_but_operator_ptr_get(but);
+ RNA_enum_set(but->opptr, "type", 1);
+
+ /* Menu. */
+ uiDefIconMenuBut(
+ block, ui_template_palette_menu, NULL, ICON_SORTSIZE, 0, 0, UI_UNIT_X, UI_UNIT_Y, "");
+ }
col = uiLayoutColumn(layout, true);
uiLayoutRow(col, true);
@@ -5934,7 +6242,7 @@ void uiTemplateList(uiLayout *layout,
uiListType *ui_list_type;
uiList *ui_list = NULL;
uiListDyn *dyn_data;
- ARegion *ar;
+ ARegion *region;
uiListDrawItemFunc draw_item;
uiListDrawFilterFunc draw_filter;
uiListFilterItemsFunc filter_items;
@@ -6026,16 +6334,16 @@ void uiTemplateList(uiLayout *layout,
ui_list_id, sizeof(ui_list_id), "%s_%s", ui_list_type->idname, list_id ? list_id : "");
/* Allows to work in popups. */
- ar = CTX_wm_menu(C);
- if (ar == NULL) {
- ar = CTX_wm_region(C);
+ region = CTX_wm_menu(C);
+ if (region == NULL) {
+ region = CTX_wm_region(C);
}
- ui_list = BLI_findstring(&ar->ui_lists, ui_list_id, offsetof(uiList, list_id));
+ ui_list = BLI_findstring(&region->ui_lists, ui_list_id, offsetof(uiList, list_id));
if (!ui_list) {
ui_list = MEM_callocN(sizeof(uiList), "uiList");
BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id));
- BLI_addtail(&ar->ui_lists, ui_list);
+ BLI_addtail(&region->ui_lists, ui_list);
ui_list->list_grip = -UI_LIST_AUTO_SIZE_THRESHOLD; /* Force auto size by default. */
if (sort_reverse) {
ui_list->filter_sort_flag |= UILST_FLT_SORT_REVERSE;
@@ -6506,296 +6814,6 @@ void uiTemplateList(uiLayout *layout,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Operator Search Template
- * \{ */
-
-static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
-{
- wmOperatorType *ot = arg2;
-
- if (ot) {
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL);
- }
-}
-
-static bool has_word_prefix(const char *haystack, const char *needle, size_t needle_len)
-{
- const char *match = BLI_strncasestr(haystack, needle, needle_len);
- if (match) {
- if ((match == haystack) || (*(match - 1) == ' ') || ispunct(*(match - 1))) {
- return true;
- }
- else {
- return has_word_prefix(match + 1, needle, needle_len);
- }
- }
- else {
- return false;
- }
-}
-
-static void operator_search_cb(const bContext *C,
- void *UNUSED(arg),
- const char *str,
- uiSearchItems *items)
-{
- GHashIterator iter;
- const size_t str_len = strlen(str);
- const int words_max = (str_len / 2) + 1;
- int(*words)[2] = BLI_array_alloca(words, words_max);
-
- const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max);
-
- for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter);
- BLI_ghashIterator_step(&iter)) {
- wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
- const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name);
- int index;
-
- if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) {
- continue;
- }
-
- /* match name against all search words */
- for (index = 0; index < words_len; index++) {
- if (!has_word_prefix(ot_ui_name, str + words[index][0], words[index][1])) {
- break;
- }
- }
-
- if (index == words_len) {
- if (WM_operator_poll((bContext *)C, ot)) {
- char name[256];
- int len = strlen(ot_ui_name);
-
- /* display name for menu, can hold hotkey */
- BLI_strncpy(name, ot_ui_name, sizeof(name));
-
- /* check for hotkey */
- if (len < sizeof(name) - 6) {
- if (WM_key_event_operator_string(C,
- ot->idname,
- WM_OP_EXEC_DEFAULT,
- NULL,
- true,
- &name[len + 1],
- sizeof(name) - len - 1)) {
- name[len] = UI_SEP_CHAR;
- }
- }
-
- if (false == UI_search_item_add(items, name, ot, 0)) {
- break;
- }
- }
- }
- }
-}
-
-void UI_but_func_operator_search(uiBut *but)
-{
- UI_but_func_search_set(
- but, ui_searchbox_create_operator, operator_search_cb, NULL, false, operator_call_cb, NULL);
-}
-
-void uiTemplateOperatorSearch(uiLayout *layout)
-{
- uiBlock *block;
- uiBut *but;
- static char search[256] = "";
-
- block = uiLayoutGetBlock(layout);
- UI_block_layout_set_current(block, layout);
-
- but = uiDefSearchBut(
- block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, "");
- UI_but_func_operator_search(but);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Operator Redo Properties Template
- * \{ */
-
-#ifdef USE_OP_RESET_BUT
-static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C),
- void *op_pt,
- void *UNUSED(arg_dummy2))
-{
- WM_operator_properties_reset((wmOperator *)op_pt);
-}
-#endif
-
-struct uiTemplateOperatorPropertyPollParam {
- const bContext *C;
- wmOperator *op;
- short flag;
-};
-
-static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr),
- struct PropertyRNA *prop,
- void *user_data)
-{
- struct uiTemplateOperatorPropertyPollParam *params = user_data;
- if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) &&
- (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) {
- return false;
- }
- return params->op->type->poll_property(params->C, params->op, prop);
-}
-
-/**
- * Draw Operator property buttons for redoing execution with different settings.
- * This function does not initialize the layout,
- * functions can be called on the layout before and after.
- */
-eAutoPropButsReturn uiTemplateOperatorPropertyButs(const bContext *C,
- uiLayout *layout,
- wmOperator *op,
- const eButLabelAlign label_align,
- const short flag)
-{
- uiBlock *block = uiLayoutGetBlock(layout);
- eAutoPropButsReturn return_info = 0;
-
- if (!op->properties) {
- IDPropertyTemplate val = {0};
- op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
- }
-
- /* poll() on this operator may still fail,
- * at the moment there is no nice feedback when this happens just fails silently. */
- if (!WM_operator_repeat_check(C, op)) {
- UI_block_lock_set(block, true, "Operator can't' redo");
- return return_info;
- }
- else {
- /* useful for macros where only one of the steps can't be re-done */
- UI_block_lock_clear(block);
- }
-
- if (flag & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) {
- uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
- }
-
- /* menu */
- if (op->type->flag & OPTYPE_PRESET) {
- /* XXX, no simple way to get WM_MT_operator_presets.bl_label
- * from python! Label remains the same always! */
- PointerRNA op_ptr;
- uiLayout *row;
-
- block->ui_operator = op;
-
- row = uiLayoutRow(layout, true);
- uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE);
-
- wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false);
- uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_string_set(&op_ptr, "operator", op->type->idname);
-
- uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_string_set(&op_ptr, "operator", op->type->idname);
- RNA_boolean_set(&op_ptr, "remove_active", true);
- }
-
- if (op->type->ui) {
- op->layout = layout;
- op->type->ui((bContext *)C, op);
- op->layout = NULL;
-
- /* UI_LAYOUT_OP_SHOW_EMPTY ignored. return_info is ignored too. We could
- * allow ot.ui callback to return this, but not needed right now. */
- }
- else {
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
- struct uiTemplateOperatorPropertyPollParam user_data = {
- .C = C,
- .op = op,
- .flag = flag,
- };
-
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
- uiLayoutSetPropSep(layout, true);
- uiLayoutSetPropDecorate(layout, false);
-
- /* main draw call */
- return_info = uiDefAutoButsRNA(
- layout,
- &ptr,
- op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL,
- op->type->poll_property ? &user_data : NULL,
- op->type->prop,
- label_align,
- (flag & UI_TEMPLATE_OP_PROPS_COMPACT));
-
- if ((return_info & UI_PROP_BUTS_NONE_ADDED) && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) {
- uiItemL(layout, IFACE_("No Properties"), ICON_NONE);
- }
- }
-
-#ifdef USE_OP_RESET_BUT
- /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled
- * but this is not so important if this button is drawn in those cases
- * (which isn't all that likely anyway) - campbell */
- if (op->properties->len) {
- uiBut *but;
- uiLayout *col; /* needed to avoid alignment errors with previous buttons */
-
- col = uiLayoutColumn(layout, false);
- block = uiLayoutGetBlock(col);
- but = uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_FILE_REFRESH,
- IFACE_("Reset"),
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- TIP_("Reset operator defaults"));
- UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL);
- }
-#endif
-
- /* set various special settings for buttons */
-
- /* Only do this if we're not refreshing an existing UI. */
- if (block->oldblock == NULL) {
- const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0;
- uiBut *but;
-
- for (but = block->buttons.first; but; but = but->next) {
- /* no undo for buttons for operator redo panels */
- UI_but_flag_disable(but, UI_BUT_UNDO);
-
- /* only for popups, see [#36109] */
-
- /* if button is operator's default property, and a text-field, enable focus for it
- * - this is used for allowing operators with popups to rename stuff with fewer clicks
- */
- if (is_popup) {
- if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) {
- UI_but_focus_on_enter_event(CTX_wm_window(C), but);
- }
- }
- }
- }
-
- return return_info;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Running Jobs Template
* \{ */
@@ -6871,8 +6889,9 @@ static char *progress_tooltip_func(bContext *UNUSED(C), void *argN, const char *
void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
{
+ Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
uiBlock *block;
void *owner = NULL;
int handle_event, icon = 0;
@@ -6884,7 +6903,7 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
Scene *scene;
/* another scene can be rendering too, for example via compositor */
- for (scene = CTX_data_main(C)->scenes.first; scene; scene = scene->id.next) {
+ for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
if (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)) {
handle_event = B_STOPOTHER;
icon = ICON_NONE;
@@ -6946,7 +6965,7 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
* progress bar which is not being updated (bake jobs only need
* to update NC_IMAGE context.
*/
- if (sa->spacetype != SPACE_NODE) {
+ if (area->spacetype != SPACE_NODE) {
handle_event = B_STOPOTHER;
icon = ICON_IMAGE;
break;
@@ -7086,7 +7105,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
uiLayout *ui_abs;
uiBlock *block;
uiBut *but;
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
int width;
int icon;
@@ -7415,13 +7434,13 @@ typedef struct ComponentMenuArgs {
char propname[64]; /* XXX arbitrary */
} ComponentMenuArgs;
/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
-static uiBlock *component_menu(bContext *C, ARegion *ar, void *args_v)
+static uiBlock *component_menu(bContext *C, ARegion *region, void *args_v)
{
ComponentMenuArgs *args = (ComponentMenuArgs *)args_v;
uiBlock *block;
uiLayout *layout;
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, region, __func__, UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN);
layout = uiLayoutColumn(UI_block_layout(block,
diff --git a/source/blender/editors/interface/interface_undo.c b/source/blender/editors/interface/interface_undo.c
new file mode 100644
index 00000000000..016bc4159db
--- /dev/null
+++ b/source/blender/editors/interface/interface_undo.c
@@ -0,0 +1,139 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edinterface
+ *
+ * Undo stack to use for UI widgets that manage their own editing state.
+ */
+
+#include <string.h>
+
+#include "BLI_listbase.h"
+
+#include "DNA_listBase.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "interface_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Text Field Undo Stack
+ * \{ */
+
+typedef struct uiUndoStack_Text_State {
+ struct uiUndoStack_Text_State *next, *prev;
+ int cursor_index;
+ char text[0];
+} uiUndoStack_Text_State;
+
+typedef struct uiUndoStack_Text {
+ ListBase states;
+ uiUndoStack_Text_State *current;
+} uiUndoStack_Text;
+
+static const char *ui_textedit_undo_impl(uiUndoStack_Text *stack, int *r_cursor_index)
+{
+ /* Don't undo if no data has been pushed yet. */
+ if (stack->current == NULL) {
+ return NULL;
+ }
+
+ /* Travel backwards in the stack and copy information to the caller. */
+ if (stack->current->prev != NULL) {
+ stack->current = stack->current->prev;
+
+ *r_cursor_index = stack->current->cursor_index;
+ return stack->current->text;
+ }
+ return NULL;
+}
+
+static const char *ui_textedit_redo_impl(uiUndoStack_Text *stack, int *r_cursor_index)
+{
+ /* Don't redo if no data has been pushed yet. */
+ if (stack->current == NULL) {
+ return NULL;
+ }
+
+ /* Only redo if new data has not been entered since the last undo. */
+ if (stack->current->next) {
+ stack->current = stack->current->next;
+
+ *r_cursor_index = stack->current->cursor_index;
+ return stack->current->text;
+ }
+ return NULL;
+}
+
+const char *ui_textedit_undo(uiUndoStack_Text *stack, int direction, int *r_cursor_index)
+{
+ BLI_assert(ELEM(direction, -1, 1));
+ if (direction < 0) {
+ return ui_textedit_undo_impl(stack, r_cursor_index);
+ }
+ else {
+ return ui_textedit_redo_impl(stack, r_cursor_index);
+ }
+}
+
+/**
+ * Push the information in the arguments to a new state in the undo stack.
+ *
+ * \note Currently the total length of the undo stack is not limited.
+ */
+void ui_textedit_undo_push(uiUndoStack_Text *stack, const char *text, int cursor_index)
+{
+ /* Clear all redo actions from the current state. */
+ if (stack->current != NULL) {
+ while (stack->current->next) {
+ uiUndoStack_Text_State *state = stack->current->next;
+ BLI_remlink(&stack->states, state);
+ MEM_freeN(state);
+ }
+ }
+
+ /* Create the new state */
+ const int text_size = strlen(text) + 1;
+ stack->current = MEM_mallocN(sizeof(uiUndoStack_Text_State) + text_size, __func__);
+ stack->current->cursor_index = cursor_index;
+ memcpy(stack->current->text, text, text_size);
+ BLI_addtail(&stack->states, stack->current);
+}
+/**
+ * Start the undo stack.
+ *
+ * \note The current state should be pushed immediately after calling this.
+ */
+uiUndoStack_Text *ui_textedit_undo_stack_create(void)
+{
+ uiUndoStack_Text *stack = MEM_mallocN(sizeof(uiUndoStack_Text), __func__);
+ stack->current = NULL;
+ BLI_listbase_clear(&stack->states);
+
+ return stack;
+}
+
+void ui_textedit_undo_stack_destroy(uiUndoStack_Text *stack)
+{
+ BLI_freelistN(&stack->states);
+ MEM_freeN(stack);
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 63e382e2280..4013e962ce5 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -21,21 +21,23 @@
* \ingroup edinterface
*/
+#include <assert.h>
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
-#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
-#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
+#include "BKE_lib_id.h"
#include "BKE_report.h"
#include "MEM_guardedalloc.h"
@@ -50,6 +52,22 @@
#include "interface_intern.h"
+bool ui_str_has_word_prefix(const char *haystack, const char *needle, size_t needle_len)
+{
+ const char *match = BLI_strncasestr(haystack, needle, needle_len);
+ if (match) {
+ if ((match == haystack) || (*(match - 1) == ' ') || ispunct(*(match - 1))) {
+ return true;
+ }
+ else {
+ return ui_str_has_word_prefix(match + 1, needle, needle_len);
+ }
+ }
+ else {
+ return false;
+ }
+}
+
/*************************** RNA Utilities ******************************/
uiBut *uiDefAutoButR(uiBlock *block,
@@ -293,7 +311,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
const bool compact)
{
eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED;
- uiLayout *split, *col;
+ uiLayout *col;
const char *name;
RNA_STRUCT_BEGIN (ptr, prop) {
@@ -324,19 +342,11 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
}
else {
BLI_assert(label_align == UI_BUT_LABEL_ALIGN_SPLIT_COLUMN);
- split = uiLayoutSplit(layout, 0.5f, false);
-
- col = uiLayoutColumn(split, false);
- uiItemL(col, (is_boolean) ? "" : name, ICON_NONE);
- col = uiLayoutColumn(split, false);
+ col = uiLayoutColumn(layout, true);
+ /* Let uiItemFullR() create the split layout. */
+ uiLayoutSetPropSep(col, true);
}
- /* May need to add more cases here.
- * don't override enum flag names */
-
- /* name is shown above, empty name for button below */
- name = (flag & PROP_ENUM_FLAG || is_boolean) ? NULL : "";
-
break;
}
case UI_BUT_LABEL_ALIGN_NONE:
@@ -389,17 +399,23 @@ static int sort_search_items_list(const void *a, const void *b)
}
}
-void ui_rna_collection_search_cb(const struct bContext *C,
- void *arg,
- const char *str,
- uiSearchItems *items)
+void ui_rna_collection_search_update_fn(const struct bContext *C,
+ void *arg,
+ const char *str,
+ uiSearchItems *items)
{
uiRNACollectionSearch *data = arg;
- char *name;
int i = 0, iconid = 0, flag = RNA_property_flag(data->target_prop);
ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list");
CollItemSearch *cis;
- const bool skip_filter = (data->but_changed && !(*data->but_changed));
+ const bool is_ptr_target = (RNA_property_type(data->target_prop) == PROP_POINTER);
+ /* For non-pointer properties, UI code acts entirely based on the item's name. So the name has to
+ * match the RNA name exactly. So only for pointer properties, the name can be modified to add
+ * further UI hints. */
+ const bool requires_exact_data_name = !is_ptr_target;
+ const bool skip_filter = data->search_but && !data->search_but->changed;
+ char name_buf[UI_MAX_DRAW_STR];
+ char *name;
/* build a temporary list of relevant items first */
RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) {
@@ -411,30 +427,42 @@ void ui_rna_collection_search_cb(const struct bContext *C,
}
/* use filter */
- if (RNA_property_type(data->target_prop) == PROP_POINTER) {
+ if (is_ptr_target) {
if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0) {
continue;
}
}
- /* Could use the string length here. */
- name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
-
iconid = 0;
if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
iconid = ui_id_icon_get(C, itemptr.data, false);
+
+ if (requires_exact_data_name) {
+ name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL);
+ }
+ else {
+ BKE_id_full_name_ui_prefix_get(name_buf, itemptr.data);
+ BLI_STATIC_ASSERT(sizeof(name_buf) >= MAX_ID_FULL_NAME_UI,
+ "Name string buffer should be big enough to hold full UI ID name");
+ name = name_buf;
+ }
+ }
+ else {
+ name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL);
}
if (name) {
if (skip_filter || BLI_strcasestr(name, str)) {
cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch");
cis->data = itemptr.data;
- cis->name = MEM_dupallocN(name);
+ cis->name = BLI_strdup(name);
cis->index = i;
cis->iconid = iconid;
BLI_addtail(items_list, cis);
}
- MEM_freeN(name);
+ if (name != name_buf) {
+ MEM_freeN(name);
+ }
}
i++;
@@ -445,7 +473,7 @@ void ui_rna_collection_search_cb(const struct bContext *C,
/* add search items from temporary list */
for (cis = items_list->first; cis; cis = cis->next) {
- if (UI_search_item_add(items, cis->name, cis->data, cis->iconid) == false) {
+ if (!UI_search_item_add(items, cis->name, cis->data, cis->iconid, 0)) {
break;
}
}
@@ -525,7 +553,7 @@ int UI_calc_float_precision(int prec, double value)
* this is so 0.00001 is not displayed as 0.00,
* _but_, this is only for small values si 10.0001 will not get the same treatment.
*/
- value = ABS(value);
+ value = fabs(value);
if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) {
int value_i = (int)((value * max_pow) + 0.5);
if (value_i != 0) {
@@ -647,6 +675,7 @@ void UI_butstore_free(uiBlock *block, uiButStore *bs_handle)
}
BLI_freelistN(&bs_handle->items);
+ BLI_assert(BLI_findindex(&block->butstore, bs_handle) != -1);
BLI_remlink(&block->butstore, bs_handle);
MEM_freeN(bs_handle);
@@ -747,8 +776,7 @@ void UI_butstore_update(uiBlock *block)
/* move this list to the new block */
if (block->oldblock) {
if (block->oldblock->butstore.first) {
- block->butstore = block->oldblock->butstore;
- BLI_listbase_clear(&block->oldblock->butstore);
+ BLI_movelisttolist(&block->butstore, &block->oldblock->butstore);
}
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index fd2f652d40e..4706be205e1 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -21,13 +21,12 @@
* \ingroup edinterface
*/
+#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "DNA_brush_types.h"
-#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "BLI_math.h"
@@ -42,6 +41,8 @@
#include "BLF_api.h"
+#include "ED_node.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -1348,6 +1349,7 @@ void UI_widgetbase_draw_cache_flush(void)
(float *)g_widget_base_batch.params);
GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
GPU_matrix_bind(batch->interface);
+ GPU_shader_set_srgb_uniform(batch->interface);
GPU_batch_bind(batch);
GPU_batch_draw_advanced(batch, 0, 0, 0, g_widget_base_batch.count);
@@ -1742,9 +1744,8 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
strwidth = BLF_width(fstyle->uifont_id, str, max_len);
if ((okwidth > 0.0f) && (strwidth > okwidth)) {
- /* utf8 two-dots leader '..' (shorter than ellipsis '...'),
- * some compilers complain with real literal string. */
- const char sep[] = {0xe2, 0x80, 0xA5, 0x0};
+ /* Ellipsis. Some compilers complain with real literal string. */
+ const char sep[] = {0xe2, 0x80, 0xA6, 0x0};
const int sep_len = sizeof(sep) - 1;
const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1);
float parts_strwidth;
@@ -2092,6 +2093,25 @@ static void widget_draw_text_ime_underline(const uiFontStyle *fstyle,
}
#endif /* WITH_INPUT_IME */
+static bool widget_draw_text_underline_calc_center_x(const char *UNUSED(str),
+ const size_t str_step_ofs,
+ const rcti *glyph_step_bounds,
+ const int UNUSED(glyph_advance_x),
+ const rctf *glyph_bounds,
+ const int glyph_bearing[2],
+ void *user_data)
+{
+ /* The index of the character to get, set to the x-position. */
+ int *ul_data = user_data;
+ if (ul_data[0] == (int)str_step_ofs) {
+ ul_data[1] = glyph_step_bounds->xmin + glyph_bearing[0] +
+ (BLI_rctf_size_x(glyph_bounds) / 2.0f);
+ /* Early exit. */
+ return false;
+ }
+ return true;
+}
+
static void widget_draw_text(const uiFontStyle *fstyle,
const uiWidgetColors *wcol,
uiBut *but,
@@ -2301,7 +2321,7 @@ static void widget_draw_text(const uiFontStyle *fstyle,
if (!use_right_only) {
/* for underline drawing */
- float font_xofs, font_yofs;
+ int font_xofs, font_yofs;
int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) :
(drawstr_left_len - but->ofs);
@@ -2316,34 +2336,44 @@ static void widget_draw_text(const uiFontStyle *fstyle,
},
drawlen,
&font_xofs,
- &font_yofs);
+ &font_yofs,
+ NULL);
if (but->menu_key != '\0') {
- char fixedbuf[128];
- const char *str;
-
- BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawlen));
-
- str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
- if (str == NULL) {
- str = strchr(fixedbuf, but->menu_key);
+ const char *drawstr_ofs = drawstr + but->ofs;
+ int ul_index = -1;
+
+ {
+ /* Find upper case, fallback to lower case. */
+ const char *drawstr_end = drawstr_ofs + drawlen;
+ const char keys[] = {but->menu_key - 32, but->menu_key};
+ for (int i = 0; i < ARRAY_SIZE(keys); i++) {
+ const char *drawstr_menu = strchr(drawstr_ofs, keys[i]);
+ if (drawstr_menu != NULL && drawstr_menu < drawstr_end) {
+ ul_index = (int)(drawstr_menu - drawstr_ofs);
+ break;
+ }
+ }
}
- if (str) {
- int ul_index = -1;
- float ul_advance;
-
- ul_index = (int)(str - fixedbuf);
-
+ if (ul_index != -1) {
if (fstyle->kerning == 1) {
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
}
- fixedbuf[ul_index] = '\0';
- ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index) + (1.0f * UI_DPI_FAC);
+ int ul_data[2] = {
+ ul_index, /* Character index to test. */
+ 0, /* Write the x-offset here. */
+ };
+ BLF_boundbox_foreach_glyph(fstyle->uifont_id,
+ drawstr_ofs,
+ ul_index + 1,
+ widget_draw_text_underline_calc_center_x,
+ ul_data);
+ ul_data[1] -= BLF_width(fstyle->uifont_id, "_", 2) / 2.0f;
BLF_position(fstyle->uifont_id,
- rect->xmin + font_xofs + ul_advance,
+ rect->xmin + font_xofs + ul_data[1],
rect->ymin + font_yofs,
0.0f);
BLF_color4ubv(fstyle->uifont_id, wcol->text);
@@ -2376,21 +2406,6 @@ static void widget_draw_text(const uiFontStyle *fstyle,
}
}
-static BIFIconID widget_icon_id(uiBut *but)
-{
- if (!(but->flag & UI_HAS_ICON)) {
- return ICON_NONE;
- }
-
- /* Consecutive icons can be toggle between. */
- if (but->drawflag & UI_BUT_ICON_REVERSE) {
- return but->icon - but->iconadd;
- }
- else {
- return but->icon + but->iconadd;
- }
-}
-
static void widget_draw_extra_icons(const uiWidgetColors *wcol,
uiBut *but,
rcti *rect,
@@ -2408,6 +2423,30 @@ static void widget_draw_extra_icons(const uiWidgetColors *wcol,
}
}
+static void widget_draw_node_link_socket(const uiWidgetColors *wcol,
+ const rcti *rect,
+ uiBut *but,
+ float alpha)
+{
+ /* Node socket pointer can be passed as custom_data, see UI_but_node_link_set(). */
+ if (but->custom_data) {
+ const float scale = 0.9f / but->block->aspect;
+
+ float col[4];
+ rgba_uchar_to_float(col, but->col);
+ col[3] *= alpha;
+
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+
+ ED_node_socket_draw(but->custom_data, rect, col, scale);
+ }
+ else {
+ widget_draw_icon(but, ICON_LAYER_USED, alpha, rect, wcol->text);
+ }
+}
+
/* draws text and icons for buttons */
static void widget_draw_text_icon(const uiFontStyle *fstyle,
const uiWidgetColors *wcol,
@@ -2417,15 +2456,27 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
const bool show_menu_icon = ui_but_draw_menu_icon(but);
float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
+ bool no_text_padding = but->drawflag & UI_BUT_NO_TEXT_PADDING;
ui_but_text_password_hide(password_str, but, false);
/* check for button text label */
if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) && (but->flag & UI_BUT_NODE_LINK)) {
rcti temp = *rect;
- temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
- widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, wcol->text);
- rect->xmax = temp.xmin;
+ const int size = BLI_rcti_size_y(rect) + 1; /* Not the icon size! */
+
+ if (but->drawflag & UI_BUT_ICON_LEFT) {
+ temp.xmax = rect->xmin + size;
+ rect->xmin = temp.xmax;
+ /* Further padding looks off. */
+ no_text_padding = true;
+ }
+ else {
+ temp.xmin = rect->xmax - size;
+ rect->xmax = temp.xmin;
+ }
+
+ widget_draw_node_link_socket(wcol, &temp, but, alpha);
}
/* If there's an icon too (made with uiDefIconTextBut) then draw the icon
@@ -2433,7 +2484,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
/* Big previews with optional text label below */
if (but->flag & UI_BUT_ICON_PREVIEW && ui_block_is_menu(but->block)) {
- const BIFIconID icon = widget_icon_id(but);
+ const BIFIconID icon = ui_but_icon(but);
int icon_size = BLI_rcti_size_y(rect);
int text_size = 0;
@@ -2470,7 +2521,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
}
#endif
- const BIFIconID icon = widget_icon_id(but);
+ const BIFIconID icon = ui_but_icon(but);
int icon_size_init = is_tool ? ICON_DEFAULT_HEIGHT_TOOLBAR : ICON_DEFAULT_HEIGHT;
const float icon_size = icon_size_init / (but->block->aspect * U.inv_dpi_fac);
const float icon_padding = 2 * UI_DPI_FAC;
@@ -2510,21 +2561,30 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
rect->xmin += icon_size + icon_padding;
}
- int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
- if (but->editstr) {
- rect->xmin += text_padding;
- }
- else if (but->flag & UI_BUT_DRAG_MULTI) {
- bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL;
- if (text_is_edited) {
+ if (!no_text_padding) {
+ int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
+ if (but->editstr) {
rect->xmin += text_padding;
}
- }
- else if (but->drawflag & UI_BUT_TEXT_LEFT) {
- rect->xmin += text_padding;
- }
- else if (but->drawflag & UI_BUT_TEXT_RIGHT) {
- rect->xmax -= text_padding;
+ else if (but->flag & UI_BUT_DRAG_MULTI) {
+ bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL;
+ if (text_is_edited) {
+ rect->xmin += text_padding;
+ }
+ }
+ else if (but->drawflag & UI_BUT_TEXT_LEFT) {
+
+ /* Reduce the left padding for labels without an icon. */
+ if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) &&
+ !ui_block_is_menu(but->block)) {
+ text_padding /= 2;
+ }
+
+ rect->xmin += text_padding;
+ }
+ else if (but->drawflag & UI_BUT_TEXT_RIGHT) {
+ rect->xmax -= text_padding;
+ }
}
/* Menu contains sub-menu items with triangle icon on their right. Shortcut
@@ -4128,10 +4188,10 @@ static void widget_optionbut(uiWidgetColors *wcol,
/* smaller */
delta = 1 + BLI_rcti_size_y(&recttemp) / 8;
- recttemp.xmin += delta;
- recttemp.ymin += delta;
- recttemp.xmax -= delta;
- recttemp.ymax -= delta;
+ BLI_rcti_resize(
+ &recttemp, BLI_rcti_size_x(&recttemp) - delta * 2, BLI_rcti_size_y(&recttemp) - delta * 2);
+ /* Keep one edge in place. */
+ BLI_rcti_translate(&recttemp, text_before_widget ? delta : -delta, 0);
rad = wcol->roundness * BLI_rcti_size_y(&recttemp);
round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
@@ -4143,13 +4203,13 @@ static void widget_optionbut(uiWidgetColors *wcol,
widgetbase_draw(&wtb, wcol);
- /* text space */
- const float offset = BLI_rcti_size_y(rect) * 0.7 + delta;
+ /* Text space - factor is really just eyeballed. */
+ const float offset = delta * 0.9;
if (text_before_widget) {
- rect->xmax -= offset;
+ rect->xmax = recttemp.xmin - offset;
}
else {
- rect->xmin += offset;
+ rect->xmin = recttemp.xmax + offset;
}
}
@@ -4598,7 +4658,7 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
* \{ */
/* conversion from old to new buttons, so still messy */
-void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
+void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBut *but, rcti *rect)
{
bTheme *btheme = UI_GetTheme();
const ThemeUI *tui = &btheme->tui;
@@ -4706,9 +4766,14 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case UI_BTYPE_CHECKBOX_N:
if (!(but->flag & UI_HAS_ICON)) {
wt = widget_type(UI_WTYPE_CHECKBOX);
+
if ((but->drawflag & (UI_BUT_TEXT_LEFT | UI_BUT_TEXT_RIGHT)) == 0) {
but->drawflag |= UI_BUT_TEXT_LEFT;
}
+ /* widget_optionbut() carefully sets the text rectangle for fine tuned paddings. If the
+ * text drawing were to add its own padding, DPI and zoom factor would be applied twice
+ * in the final padding, so it's difficult to control it. */
+ but->drawflag |= UI_BUT_NO_TEXT_PADDING;
}
else {
wt = widget_type(UI_WTYPE_TOGGLE);
@@ -4791,30 +4856,30 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
case UI_BTYPE_IMAGE:
- ui_draw_but_IMAGE(ar, but, &tui->wcol_regular, rect);
+ ui_draw_but_IMAGE(region, but, &tui->wcol_regular, rect);
break;
case UI_BTYPE_HISTOGRAM:
- ui_draw_but_HISTOGRAM(ar, but, &tui->wcol_regular, rect);
+ ui_draw_but_HISTOGRAM(region, but, &tui->wcol_regular, rect);
break;
case UI_BTYPE_WAVEFORM:
- ui_draw_but_WAVEFORM(ar, but, &tui->wcol_regular, rect);
+ ui_draw_but_WAVEFORM(region, but, &tui->wcol_regular, rect);
break;
case UI_BTYPE_VECTORSCOPE:
- ui_draw_but_VECTORSCOPE(ar, but, &tui->wcol_regular, rect);
+ ui_draw_but_VECTORSCOPE(region, but, &tui->wcol_regular, rect);
break;
case UI_BTYPE_CURVE:
/* do not draw right to edge of rect */
rect->xmin += (0.2f * UI_UNIT_X);
rect->xmax -= (0.2f * UI_UNIT_X);
- ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
+ ui_draw_but_CURVE(region, but, &tui->wcol_regular, rect);
break;
case UI_BTYPE_CURVEPROFILE:
- ui_draw_but_CURVEPROFILE(ar, but, &tui->wcol_regular, rect);
+ ui_draw_but_CURVEPROFILE(region, but, &tui->wcol_regular, rect);
break;
case UI_BTYPE_PROGRESS_BAR:
@@ -4831,7 +4896,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
case UI_BTYPE_TRACK_PREVIEW:
- ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect);
+ ui_draw_but_TRACKPREVIEW(region, but, &tui->wcol_regular, rect);
break;
case UI_BTYPE_NODE_SOCKET:
@@ -4971,8 +5036,6 @@ static void ui_draw_popover_back_impl(const uiWidgetColors *wcol,
rect->xmin + unit_size,
rect->xmax - unit_size) :
BLI_rcti_cent_x(rect);
- rect->ymax -= unit_half;
- rect->ymin += unit_half;
GPU_blend(true);
@@ -4993,35 +5056,53 @@ static void ui_draw_popover_back_impl(const uiWidgetColors *wcol,
if (ELEM(direction, UI_DIR_UP, UI_DIR_DOWN)) {
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4ubv(wcol->inner);
+
+ const bool is_down = (direction == UI_DIR_DOWN);
+ const int sign = is_down ? 1 : -1;
+ float y = is_down ? rect->ymax : rect->ymin;
+
GPU_blend(true);
immBegin(GPU_PRIM_TRIS, 3);
- if (direction == UI_DIR_DOWN) {
- const float y = rect->ymax;
- immVertex2f(pos, cent_x - unit_half, y);
- immVertex2f(pos, cent_x + unit_half, y);
- immVertex2f(pos, cent_x, y + unit_half);
- }
- else {
- const float y = rect->ymin;
- immVertex2f(pos, cent_x - unit_half, y);
- immVertex2f(pos, cent_x + unit_half, y);
- immVertex2f(pos, cent_x, y - unit_half);
- }
+ immUniformColor4ub(UNPACK3(wcol->outline), 166);
+ immVertex2f(pos, cent_x - unit_half, y);
+ immVertex2f(pos, cent_x + unit_half, y);
+ immVertex2f(pos, cent_x, y + sign * unit_half);
+ immEnd();
+
+ y = y - sign * round(U.pixelsize * 1.41);
+
+ GPU_blend(false);
+ immBegin(GPU_PRIM_TRIS, 3);
+ immUniformColor4ub(0, 0, 0, 0);
+ immVertex2f(pos, cent_x - unit_half, y);
+ immVertex2f(pos, cent_x + unit_half, y);
+ immVertex2f(pos, cent_x, y + sign * unit_half);
immEnd();
+
+ GPU_blend(true);
+ immBegin(GPU_PRIM_TRIS, 3);
+ immUniformColor4ubv(wcol->inner);
+ immVertex2f(pos, cent_x - unit_half, y);
+ immVertex2f(pos, cent_x + unit_half, y);
+ immVertex2f(pos, cent_x, y + sign * unit_half);
+ immEnd();
+
immUnbindProgram();
}
GPU_blend(false);
}
-void ui_draw_popover_back(ARegion *ar, uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
+void ui_draw_popover_back(struct ARegion *region,
+ uiStyle *UNUSED(style),
+ uiBlock *block,
+ rcti *rect)
{
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
if (block) {
float mval_origin[2] = {UNPACK2(block->bounds_offset)};
- ui_window_to_block_fl(ar, block, &mval_origin[0], &mval_origin[1]);
+ ui_window_to_block_fl(region, block, &mval_origin[0], &mval_origin[1]);
ui_draw_popover_back_impl(
wt->wcol_theme, rect, block->direction, U.widget_unit / block->aspect, mval_origin);
}
@@ -5238,7 +5319,7 @@ void ui_draw_widget_menu_back(const rcti *rect, bool use_shadow)
ui_draw_widget_back_color(UI_WTYPE_MENU_BACK, use_shadow, rect, NULL);
}
-void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
+void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
{
uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
wt->state(wt, 0, 0);
@@ -5246,10 +5327,23 @@ void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block),
wt->draw(&wt->wcol, rect, 0, 0);
}
-/* helper call to draw a menu item without button */
-/* state: UI_ACTIVE or 0 */
-void ui_draw_menu_item(
- const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep)
+/**
+ * Helper call to draw a menu item without a button.
+ *
+ * \param state: The state of the button,
+ * typically #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE.
+ * \param use_sep: When true, characters after the last #UI_SEP_CHAR are right aligned,
+ * use for displaying key shortcuts.
+ * \param r_xmax: The right hand position of the text, this takes into the icon,
+ * padding and text clipping when there is not enough room to display the full text.
+ */
+void ui_draw_menu_item(const uiFontStyle *fstyle,
+ rcti *rect,
+ const char *name,
+ int iconid,
+ int state,
+ bool use_sep,
+ int *r_xmax)
{
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
rcti _rect = *rect;
@@ -5268,7 +5362,7 @@ void ui_draw_menu_item(
/* cut string in 2 parts? */
if (use_sep) {
- cpoin = strchr(name, UI_SEP_CHAR);
+ cpoin = strrchr(name, UI_SEP_CHAR);
if (cpoin) {
*cpoin = 0;
@@ -5299,27 +5393,21 @@ void ui_draw_menu_item(
UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
}
- UI_fontstyle_draw(fstyle,
- rect,
- drawstr,
- wt->wcol.text,
- &(struct uiFontStyleDraw_Params){
- .align = UI_STYLE_TEXT_LEFT,
- });
- }
-
- /* part text right aligned */
- if (use_sep) {
- if (cpoin) {
- rect->xmax = _rect.xmax - 5;
- UI_fontstyle_draw(fstyle,
- rect,
- cpoin + 1,
- wt->wcol.text,
- &(struct uiFontStyleDraw_Params){
- .align = UI_STYLE_TEXT_RIGHT,
- });
- *cpoin = UI_SEP_CHAR;
+ int xofs = 0, yofs = 0;
+ struct ResultBLF info;
+ UI_fontstyle_draw_ex(fstyle,
+ rect,
+ drawstr,
+ wt->wcol.text,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_LEFT,
+ },
+ BLF_DRAW_STR_DUMMY_MAX,
+ &xofs,
+ &yofs,
+ &info);
+ if (r_xmax != NULL) {
+ *r_xmax = xofs + info.width;
}
}
@@ -5339,6 +5427,24 @@ void ui_draw_menu_item(
UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false);
GPU_blend(false);
}
+
+ /* part text right aligned */
+ if (use_sep) {
+ if (cpoin) {
+ /* Set inactive state for grayed out text. */
+ wt->state(wt, state | UI_BUT_INACTIVE, 0);
+
+ rect->xmax = _rect.xmax - 5;
+ UI_fontstyle_draw(fstyle,
+ rect,
+ cpoin + 1,
+ wt->wcol.text,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_RIGHT,
+ });
+ *cpoin = UI_SEP_CHAR;
+ }
+ }
}
void ui_draw_preview_item(
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 3aede744115..01c9716ec86 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -32,8 +32,8 @@
#include "DNA_userdef_types.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_addon.h"
#include "BKE_appdir.h"
@@ -49,8 +49,8 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
-#include "interface_intern.h"
#include "GPU_framebuffer.h"
+#include "interface_intern.h"
/* global for themes */
typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
@@ -196,9 +196,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp = ts->back_grad;
break;
- case TH_SHOW_BACK_GRAD:
+ case TH_BACKGROUND_TYPE:
cp = &setting;
- setting = ts->show_back_grad;
+ setting = ts->background_type;
break;
case TH_TEXT:
if (theme_regionid == RGN_TYPE_WINDOW) {
@@ -311,6 +311,12 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_TIME_SCRUB_BACKGROUND:
cp = ts->time_scrub_background;
break;
+ case TH_TIME_MARKER_LINE:
+ cp = ts->time_marker_line;
+ break;
+ case TH_TIME_MARKER_LINE_SELECTED:
+ cp = ts->time_marker_line_selected;
+ break;
case TH_VIEW_OVERLAY:
cp = ts->view_overlay;
break;
@@ -634,6 +640,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_NODE_CURVING:
cp = &ts->noodle_curving;
break;
+ case TH_NODE_GRID_LEVELS:
+ cp = &ts->grid_levels;
+ break;
case TH_SEQ_MOVIE:
cp = ts->movie;
@@ -656,9 +665,6 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_SEQ_EFFECT:
cp = ts->effect;
break;
- case TH_SEQ_TRANSITION:
- cp = ts->transition;
- break;
case TH_SEQ_META:
cp = ts->meta;
break;
@@ -668,6 +674,15 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_SEQ_PREVIEW:
cp = ts->preview_back;
break;
+ case TH_SEQ_COLOR:
+ cp = ts->color_strip;
+ break;
+ case TH_SEQ_ACTIVE:
+ cp = ts->active_strip;
+ break;
+ case TH_SEQ_SELECTED:
+ cp = ts->selected_strip;
+ break;
case TH_CONSOLE_OUTPUT:
cp = ts->console_output;
@@ -884,6 +899,17 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_WIDGET_TEXT_CURSOR:
cp = btheme->tui.widget_text_cursor;
break;
+
+ case TH_TRANSPARENT_CHECKER_PRIMARY:
+ cp = btheme->tui.transparent_checker_primary;
+ break;
+ case TH_TRANSPARENT_CHECKER_SECONDARY:
+ cp = btheme->tui.transparent_checker_secondary;
+ break;
+ case TH_TRANSPARENT_CHECKER_SIZE:
+ cp = &btheme->tui.transparent_checker_size;
+ break;
+
case TH_AXIS_X:
cp = btheme->tui.xaxis;
break;
@@ -903,6 +929,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_GIZMO_SECONDARY:
cp = btheme->tui.gizmo_secondary;
break;
+ case TH_GIZMO_VIEW_ALIGN:
+ cp = btheme->tui.gizmo_view_align;
+ break;
case TH_GIZMO_A:
cp = btheme->tui.gizmo_a;
break;
@@ -1065,9 +1094,7 @@ void UI_Theme_Restore(struct bThemeState *theme_state)
void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, uchar col[4])
{
int r, g, b, a;
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
r = coloffset + (int)cp[0];
CLAMP(r, 0, 255);
g = coloffset + (int)cp[1];
@@ -1085,10 +1112,8 @@ void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset,
void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, uchar col[3])
{
- const uchar *cp1, *cp2;
-
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+ const uchar *cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ const uchar *cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
CLAMP(fac, 0.0f, 1.0f);
col[0] = floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
@@ -1098,10 +1123,8 @@ void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, uchar col[
void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[3])
{
- const uchar *cp1, *cp2;
-
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+ const uchar *cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ const uchar *cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
CLAMP(fac, 0.0f, 1.0f);
r_col[0] = ((1.0f - fac) * cp1[0] + fac * cp2[0]) / 255.0f;
@@ -1111,10 +1134,8 @@ void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[
void UI_GetThemeColorBlend4f(int colorid1, int colorid2, float fac, float r_col[4])
{
- const uchar *cp1, *cp2;
-
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+ const uchar *cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ const uchar *cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
CLAMP(fac, 0.0f, 1.0f);
r_col[0] = ((1.0f - fac) * cp1[0] + fac * cp2[0]) / 255.0f;
@@ -1133,44 +1154,34 @@ void UI_FontThemeColor(int fontid, int colorid)
/* get individual values, not scaled */
float UI_GetThemeValuef(int colorid)
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
return ((float)cp[0]);
}
/* get individual values, not scaled */
int UI_GetThemeValue(int colorid)
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
return ((int)cp[0]);
}
/* versions of the function above, which take a space-type */
float UI_GetThemeValueTypef(int colorid, int spacetype)
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
return ((float)cp[0]);
}
int UI_GetThemeValueType(int colorid, int spacetype)
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
return ((int)cp[0]);
}
/* get the color, range 0.0-1.0 */
void UI_GetThemeColor3fv(int colorid, float col[3])
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
col[0] = ((float)cp[0]) / 255.0f;
col[1] = ((float)cp[1]) / 255.0f;
col[2] = ((float)cp[2]) / 255.0f;
@@ -1178,9 +1189,7 @@ void UI_GetThemeColor3fv(int colorid, float col[3])
void UI_GetThemeColor4fv(int colorid, float col[4])
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
col[0] = ((float)cp[0]) / 255.0f;
col[1] = ((float)cp[1]) / 255.0f;
col[2] = ((float)cp[2]) / 255.0f;
@@ -1189,9 +1198,7 @@ void UI_GetThemeColor4fv(int colorid, float col[4])
void UI_GetThemeColorType4fv(int colorid, int spacetype, float col[4])
{
- const unsigned char *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
col[0] = ((float)cp[0]) / 255.0f;
col[1] = ((float)cp[1]) / 255.0f;
col[2] = ((float)cp[2]) / 255.0f;
@@ -1201,10 +1208,8 @@ void UI_GetThemeColorType4fv(int colorid, int spacetype, float col[4])
/* get the color, range 0.0-1.0, complete with shading offset */
void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3])
{
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
int r, g, b;
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
r = offset + (int)cp[0];
CLAMP(r, 0, 255);
@@ -1220,10 +1225,8 @@ void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3])
void UI_GetThemeColorShade3ubv(int colorid, int offset, uchar col[3])
{
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
int r, g, b;
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
r = offset + (int)cp[0];
CLAMP(r, 0, 255);
@@ -1240,10 +1243,8 @@ void UI_GetThemeColorShade3ubv(int colorid, int offset, uchar col[3])
void UI_GetThemeColorBlendShade3ubv(
int colorid1, int colorid2, float fac, int offset, uchar col[3])
{
- const uchar *cp1, *cp2;
-
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+ const uchar *cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ const uchar *cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
CLAMP(fac, 0.0f, 1.0f);
@@ -1257,10 +1258,9 @@ void UI_GetThemeColorBlendShade3ubv(
void UI_GetThemeColorShade4ubv(int colorid, int offset, uchar col[4])
{
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
int r, g, b;
- const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
r = offset + (int)cp[0];
CLAMP(r, 0, 255);
g = offset + (int)cp[1];
@@ -1276,10 +1276,8 @@ void UI_GetThemeColorShade4ubv(int colorid, int offset, uchar col[4])
void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4])
{
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
int r, g, b, a;
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
r = coloffset + (int)cp[0];
CLAMP(r, 0, 255);
@@ -1298,11 +1296,9 @@ void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset,
void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3])
{
+ const uchar *cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ const uchar *cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
int r, g, b;
- const uchar *cp1, *cp2;
-
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
CLAMP(fac, 0.0f, 1.0f);
@@ -1320,11 +1316,9 @@ void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int of
void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4])
{
+ const uchar *cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ const uchar *cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
int r, g, b, a;
- const uchar *cp1, *cp2;
-
- cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
- cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
CLAMP(fac, 0.0f, 1.0f);
@@ -1346,9 +1340,7 @@ void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int of
/* get the color, in char pointer */
void UI_GetThemeColor3ubv(int colorid, uchar col[3])
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
col[0] = cp[0];
col[1] = cp[1];
col[2] = cp[2];
@@ -1357,10 +1349,8 @@ void UI_GetThemeColor3ubv(int colorid, uchar col[3])
/* get the color, range 0.0-1.0, complete with shading offset */
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
{
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
int r, g, b, a;
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
r = offset + (int)cp[0];
CLAMP(r, 0, 255);
@@ -1381,9 +1371,7 @@ void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
/* get the color, in char pointer */
void UI_GetThemeColor4ubv(int colorid, uchar col[4])
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
col[0] = cp[0];
col[1] = cp[1];
col[2] = cp[2];
@@ -1392,9 +1380,7 @@ void UI_GetThemeColor4ubv(int colorid, uchar col[4])
void UI_GetThemeColorType3fv(int colorid, int spacetype, float col[3])
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
col[0] = ((float)cp[0]) / 255.0f;
col[1] = ((float)cp[1]) / 255.0f;
col[2] = ((float)cp[2]) / 255.0f;
@@ -1402,9 +1388,7 @@ void UI_GetThemeColorType3fv(int colorid, int spacetype, float col[3])
void UI_GetThemeColorType3ubv(int colorid, int spacetype, uchar col[3])
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
col[0] = cp[0];
col[1] = cp[1];
col[2] = cp[2];
@@ -1412,9 +1396,7 @@ void UI_GetThemeColorType3ubv(int colorid, int spacetype, uchar col[3])
void UI_GetThemeColorType4ubv(int colorid, int spacetype, uchar col[4])
{
- const uchar *cp;
-
- cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, spacetype, colorid);
col[0] = cp[0];
col[1] = cp[1];
col[2] = cp[2];
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index a23bd7dad35..f8419ba3eba 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -32,17 +32,18 @@
#include "DNA_userdef_types.h"
#include "BLI_array.h"
-#include "BLI_utildefines.h"
#include "BLI_link_utils.h"
-#include "BLI_rect.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
-#include "BLI_timecode.h"
+#include "BLI_rect.h"
#include "BLI_string.h"
+#include "BLI_timecode.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "BKE_global.h"
+#include "BKE_screen.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
@@ -59,7 +60,7 @@
#include "interface_intern.h"
-static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers);
+static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize);
/* -------------------------------------------------------------------- */
/** \name Internal Utilities
@@ -67,8 +68,8 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
BLI_INLINE int clamp_float_to_int(const float f)
{
- const float min = INT_MIN;
- const float max = INT_MAX;
+ const float min = (float)INT_MIN;
+ const float max = (float)INT_MAX;
if (UNLIKELY(f < min)) {
return min;
@@ -133,7 +134,7 @@ void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask)
*
* \param mask_scroll: Optionally clamp scrollbars by this region.
*/
-static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scroll)
+static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
{
int scroll;
@@ -143,26 +144,24 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
mask_scroll = &v2d->mask;
}
- if (check_scrollers) {
- /* check size if hiding flag is set: */
- if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
- if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) {
- if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) {
- v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
- }
- else {
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
- }
+ /* check size if hiding flag is set: */
+ if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
+ if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) {
+ if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) {
+ v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
+ }
+ else {
+ v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
}
}
- if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
- if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) {
- if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) {
- v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
- }
- else {
- v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
- }
+ }
+ if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
+ if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) {
+ if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) {
+ v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
+ }
+ else {
+ v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
}
}
}
@@ -243,7 +242,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
{
bool tot_changed = false, do_init;
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
@@ -268,7 +267,6 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
*/
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
v2d->keeptot = V2D_KEEPTOT_BOUNDS;
-
if (do_init) {
v2d->tot.xmin = v2d->tot.ymin = 0.0f;
v2d->tot.xmax = (float)(winx - 1);
@@ -385,8 +383,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
v2d->winx = winx;
v2d->winy = winy;
- /* set masks (always do), but leave scroller scheck to totrect_set */
- view2d_masks(v2d, 0, NULL);
+ view2d_masks(v2d, NULL);
if (do_init) {
/* Visible by default. */
@@ -394,13 +391,12 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
}
/* set 'tot' rect before setting cur? */
- /* XXX confusing stuff here still -
- * I made this function not check scroller hide - that happens in totrect_set */
+ /* XXX confusing stuff here still */
if (tot_changed) {
UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
}
else {
- ui_view2d_curRect_validate_resize(v2d, !do_init, 0);
+ ui_view2d_curRect_validate_resize(v2d, !do_init);
}
}
@@ -409,7 +405,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
* 'cur' is not allowed to be: larger than max, smaller than min, or outside of 'tot'
*/
// XXX pre2.5 -> this used to be called test_view2d()
-static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers)
+static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
{
float totwidth, totheight, curwidth, curheight, width, height;
float winx, winy;
@@ -722,7 +718,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
* - width is OK, but need to check if outside of boundaries
*
* So, resolution is to just shift view by the gap between the extremities.
- * We favour moving the 'minimum' across, as that's origin for most things
+ * We favor moving the 'minimum' across, as that's origin for most things.
* (XXX - in the past, max was favored... if there are bugs, swap!)
*/
if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) {
@@ -779,7 +775,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
* - height is OK, but need to check if outside of boundaries
*
* So, resolution is to just shift view by the gap between the extremities.
- * We favour moving the 'minimum' across, as that's origin for most things
+ * We favor moving the 'minimum' across, as that's origin for most things.
*/
if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
/* outside boundaries on both sides,
@@ -851,12 +847,12 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
}
/* set masks */
- view2d_masks(v2d, mask_scrollers, NULL);
+ view2d_masks(v2d, NULL);
}
void UI_view2d_curRect_validate(View2D *v2d)
{
- ui_view2d_curRect_validate_resize(v2d, 0, 1);
+ ui_view2d_curRect_validate_resize(v2d, false);
}
/* ------------------ */
@@ -865,8 +861,7 @@ void UI_view2d_curRect_validate(View2D *v2d)
* to make sure 'related' views stay in synchrony */
void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
{
- ScrArea *sa;
- ARegion *ar;
+ ARegion *region;
/* don't continue if no view syncing to be done */
if ((v2dcur->flag & (V2D_VIEWSYNC_SCREEN_TIME | V2D_VIEWSYNC_AREA_VERTICAL)) == 0) {
@@ -875,24 +870,24 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
/* check if doing within area syncing (i.e. channels/vertical) */
if ((v2dcur->flag & V2D_VIEWSYNC_AREA_VERTICAL) && (area)) {
- for (ar = area->regionbase.first; ar; ar = ar->next) {
+ for (region = area->regionbase.first; region; region = region->next) {
/* don't operate on self */
- if (v2dcur != &ar->v2d) {
+ if (v2dcur != &region->v2d) {
/* only if view has vertical locks enabled */
- if (ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) {
+ if (region->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) {
if (flag == V2D_LOCK_COPY) {
/* other views with locks on must copy active */
- ar->v2d.cur.ymin = v2dcur->cur.ymin;
- ar->v2d.cur.ymax = v2dcur->cur.ymax;
+ region->v2d.cur.ymin = v2dcur->cur.ymin;
+ region->v2d.cur.ymax = v2dcur->cur.ymax;
}
else { /* V2D_LOCK_SET */
/* active must copy others */
- v2dcur->cur.ymin = ar->v2d.cur.ymin;
- v2dcur->cur.ymax = ar->v2d.cur.ymax;
+ v2dcur->cur.ymin = region->v2d.cur.ymin;
+ v2dcur->cur.ymax = region->v2d.cur.ymax;
}
/* region possibly changed, so refresh */
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
}
}
@@ -900,25 +895,25 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
/* check if doing whole screen syncing (i.e. time/horizontal) */
if ((v2dcur->flag & V2D_VIEWSYNC_SCREEN_TIME) && (screen)) {
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) {
+ for (region = area_iter->regionbase.first; region; region = region->next) {
/* don't operate on self */
- if (v2dcur != &ar->v2d) {
+ if (v2dcur != &region->v2d) {
/* only if view has horizontal locks enabled */
- if (ar->v2d.flag & V2D_VIEWSYNC_SCREEN_TIME) {
+ if (region->v2d.flag & V2D_VIEWSYNC_SCREEN_TIME) {
if (flag == V2D_LOCK_COPY) {
/* other views with locks on must copy active */
- ar->v2d.cur.xmin = v2dcur->cur.xmin;
- ar->v2d.cur.xmax = v2dcur->cur.xmax;
+ region->v2d.cur.xmin = v2dcur->cur.xmin;
+ region->v2d.cur.xmax = v2dcur->cur.xmax;
}
else { /* V2D_LOCK_SET */
/* active must copy others */
- v2dcur->cur.xmin = ar->v2d.cur.xmin;
- v2dcur->cur.xmax = ar->v2d.cur.xmax;
+ v2dcur->cur.xmin = region->v2d.cur.xmin;
+ v2dcur->cur.xmax = region->v2d.cur.xmax;
}
/* region possibly changed, so refresh */
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
}
}
@@ -983,22 +978,10 @@ void UI_view2d_curRect_reset(View2D *v2d)
/* Change the size of the maximum viewable area (i.e. 'tot' rect) */
void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize)
{
- // int scroll = view2d_scroll_mapped(v2d->scroll);
-
/* don't do anything if either value is 0 */
width = abs(width);
height = abs(height);
- /* hrumf! */
- /* XXX: there are work arounds for this in the panel and file browse code. */
- /* round to int, because this is called with width + V2D_SCROLL_WIDTH */
- // if (scroll & V2D_SCROLL_HORIZONTAL) {
- // width -= (int)V2D_SCROLL_WIDTH;
- // }
- // if (scroll & V2D_SCROLL_VERTICAL) {
- // height -= (int)V2D_SCROLL_HEIGHT;
- // }
-
if (ELEM(0, width, height)) {
if (G.debug & G_DEBUG) {
printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n",
@@ -1048,20 +1031,12 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resiz
}
/* make sure that 'cur' rect is in a valid state as a result of these changes */
- ui_view2d_curRect_validate_resize(v2d, resize, 1);
+ ui_view2d_curRect_validate_resize(v2d, resize);
}
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
{
- int scroll = view2d_scroll_mapped(v2d->scroll);
-
- UI_view2d_totRect_set_resize(v2d, width, height, 0);
-
- /* solve bad recursion... if scroller state changed,
- * mask is different, so you get different rects */
- if (scroll != view2d_scroll_mapped(v2d->scroll)) {
- UI_view2d_totRect_set_resize(v2d, width, height, 0);
- }
+ UI_view2d_totRect_set_resize(v2d, width, height, false);
}
bool UI_view2d_tab_set(View2D *v2d, int tab)
@@ -1213,7 +1188,7 @@ void UI_view2d_view_ortho(const View2D *v2d)
* \param xaxis: if non-zero, only use cur x-axis,
* otherwise use cur-yaxis (mostly this will be used for x).
*/
-void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis)
+void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis)
{
rctf curmasked;
float xofs, yofs;
@@ -1232,19 +1207,19 @@ void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis)
/* only set matrix with 'cur' coordinates on relevant axes */
if (xaxis) {
- wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, ar->winy - yofs);
+ wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, region->winy - yofs);
}
else {
- wmOrtho2(-xofs, ar->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
+ wmOrtho2(-xofs, region->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
}
}
/* Restore view matrices after drawing */
void UI_view2d_view_restore(const bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
- int width = BLI_rcti_size_x(&ar->winrct) + 1;
- int height = BLI_rcti_size_y(&ar->winrct) + 1;
+ ARegion *region = CTX_wm_region(C);
+ int width = BLI_rcti_size_x(&region->winrct) + 1;
+ int height = BLI_rcti_size_y(&region->winrct) + 1;
wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
GPU_matrix_identity_set();
@@ -1259,7 +1234,7 @@ void UI_view2d_view_restore(const bContext *C)
* \{ */
/* Draw a constant grid in given 2d-region */
-void UI_view2d_constant_grid_draw(View2D *v2d, float step)
+void UI_view2d_constant_grid_draw(const View2D *v2d, float step)
{
float start_x, start_y;
int count_x, count_y;
@@ -1331,7 +1306,8 @@ void UI_view2d_constant_grid_draw(View2D *v2d, float step)
}
/* Draw a multi-level grid in given 2d-region */
-void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels)
+void UI_view2d_multi_grid_draw(
+ const View2D *v2d, int colorid, float step, int level_size, int totlevels)
{
/* Exit if there is nothing to draw */
if (totlevels == 0) {
@@ -1343,7 +1319,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_s
uchar grid_line_color[3];
/* Make an estimate of at least how many vertices will be needed */
- unsigned vertex_count = 4;
+ uint vertex_count = 4;
vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1);
vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1);
@@ -1449,7 +1425,7 @@ View2DScrollers *UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom)
scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers");
/* Always update before drawing (for dynamically sized scrollers). */
- view2d_masks(v2d, false, mask_custom);
+ view2d_masks(v2d, mask_custom);
vert = v2d->vert;
hor = v2d->hor;
@@ -1607,7 +1583,7 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs)
* - slider bubble is large enough (no overdraw confusion)
* - scale is shown on the scroller
* (workaround to make sure that button windows don't show these,
- * and only the time-grids with their zoomability can do so)
+ * and only the time-grids with their zoom-ability can do so).
*/
if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) &&
(BLI_rcti_size_x(&slider) > V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) {
@@ -1802,7 +1778,8 @@ bool UI_view2d_view_to_region_clip(
* \param x, y: Coordinates to convert.
* \param r_region_x, r_region_y: Resultant coordinates.
*/
-void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
+void UI_view2d_view_to_region(
+ const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
{
/* step 1: express given coordinates as proportional values */
x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
@@ -1818,7 +1795,7 @@ void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *r_region_x, in
}
void UI_view2d_view_to_region_fl(
- View2D *v2d, float x, float y, float *r_region_x, float *r_region_y)
+ const View2D *v2d, float x, float y, float *r_region_x, float *r_region_y)
{
/* express given coordinates as proportional values */
x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
@@ -1829,7 +1806,7 @@ void UI_view2d_view_to_region_fl(
*r_region_y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask));
}
-void UI_view2d_view_to_region_rcti(View2D *v2d, const rctf *rect_src, rcti *rect_dst)
+void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
{
const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)};
@@ -1850,7 +1827,7 @@ void UI_view2d_view_to_region_rcti(View2D *v2d, const rctf *rect_src, rcti *rect
clamp_rctf_to_rcti(rect_dst, &rect_tmp);
}
-void UI_view2d_view_to_region_m4(View2D *v2d, float matrix[4][4])
+void UI_view2d_view_to_region_m4(const View2D *v2d, float matrix[4][4])
{
rctf mask;
unit_m4(matrix);
@@ -1858,7 +1835,7 @@ void UI_view2d_view_to_region_m4(View2D *v2d, float matrix[4][4])
BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &mask, matrix);
}
-bool UI_view2d_view_to_region_rcti_clip(View2D *v2d, const rctf *rect_src, rcti *rect_dst)
+bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
{
const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)};
const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)};
@@ -1915,18 +1892,18 @@ View2D *UI_view2d_fromcontext(const bContext *C)
/* same as above, but it returns regionwindow. Utility for pulldowns or buttons */
View2D *UI_view2d_fromcontext_rwin(const bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- if (sa == NULL) {
+ if (area == NULL) {
return NULL;
}
if (region == NULL) {
return NULL;
}
if (region->regiontype != RGN_TYPE_WINDOW) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- return ar ? &(ar->v2d) : NULL;
+ ARegion *region_win = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+ return region_win ? &(region_win->v2d) : NULL;
}
return &(region->v2d);
}
@@ -1984,7 +1961,7 @@ float UI_view2d_scale_get_y(const View2D *v2d)
/**
* Same as ``UI_view2d_scale_get() - 1.0f / x, y``
*/
-void UI_view2d_scale_get_inverse(View2D *v2d, float *r_x, float *r_y)
+void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y)
{
if (r_x) {
*r_x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
@@ -1998,7 +1975,7 @@ void UI_view2d_scale_get_inverse(View2D *v2d, float *r_x, float *r_y)
* Simple functions for consistent center offset access.
* Used by node editor to shift view center for each individual node tree.
*/
-void UI_view2d_center_get(struct View2D *v2d, float *r_x, float *r_y)
+void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
{
/* get center */
if (r_x) {
@@ -2057,7 +2034,7 @@ void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
* - 0 = not in scroller.
*/
char UI_view2d_mouse_in_scrollers_ex(
- const ARegion *ar, const View2D *v2d, int x, int y, int *r_scroll)
+ const ARegion *region, const View2D *v2d, int x, int y, int *r_scroll)
{
const int scroll = view2d_scroll_mapped(v2d->scroll);
*r_scroll = scroll;
@@ -2065,8 +2042,8 @@ char UI_view2d_mouse_in_scrollers_ex(
if (scroll) {
/* Move to region-coordinates. */
const int co[2] = {
- x - ar->winrct.xmin,
- y - ar->winrct.ymin,
+ x - region->winrct.xmin,
+ y - region->winrct.ymin,
};
if (scroll & V2D_SCROLL_HORIZONTAL) {
if (IN_2D_HORIZ_SCROLL(v2d, co)) {
@@ -2083,7 +2060,7 @@ char UI_view2d_mouse_in_scrollers_ex(
return 0;
}
-char UI_view2d_rect_in_scrollers_ex(const ARegion *ar,
+char UI_view2d_rect_in_scrollers_ex(const ARegion *region,
const View2D *v2d,
const rcti *rect,
int *r_scroll)
@@ -2094,7 +2071,7 @@ char UI_view2d_rect_in_scrollers_ex(const ARegion *ar,
if (scroll) {
/* Move to region-coordinates. */
rcti rect_region = *rect;
- BLI_rcti_translate(&rect_region, -ar->winrct.xmin, ar->winrct.ymin);
+ BLI_rcti_translate(&rect_region, -region->winrct.xmin, region->winrct.ymin);
if (scroll & V2D_SCROLL_HORIZONTAL) {
if (IN_2D_HORIZ_SCROLL_RECT(v2d, &rect_region)) {
return 'h';
@@ -2110,16 +2087,16 @@ char UI_view2d_rect_in_scrollers_ex(const ARegion *ar,
return 0;
}
-char UI_view2d_mouse_in_scrollers(const ARegion *ar, const View2D *v2d, int x, int y)
+char UI_view2d_mouse_in_scrollers(const ARegion *region, const View2D *v2d, int x, int y)
{
int scroll_dummy = 0;
- return UI_view2d_mouse_in_scrollers_ex(ar, v2d, x, y, &scroll_dummy);
+ return UI_view2d_mouse_in_scrollers_ex(region, v2d, x, y, &scroll_dummy);
}
-char UI_view2d_rect_in_scrollers(const ARegion *ar, const View2D *v2d, const rcti *rect)
+char UI_view2d_rect_in_scrollers(const ARegion *region, const View2D *v2d, const rcti *rect)
{
int scroll_dummy = 0;
- return UI_view2d_rect_in_scrollers_ex(ar, v2d, rect, &scroll_dummy);
+ return UI_view2d_rect_in_scrollers_ex(region, v2d, rect, &scroll_dummy);
}
/** \} */
@@ -2146,7 +2123,7 @@ static MemArena *g_v2d_strings_arena = NULL;
static View2DString *g_v2d_strings = NULL;
void UI_view2d_text_cache_add(
- View2D *v2d, float x, float y, const char *str, size_t str_len, const char col[4])
+ View2D *v2d, float x, float y, const char *str, size_t str_len, const uchar col[4])
{
int mval[2];
@@ -2177,7 +2154,7 @@ void UI_view2d_text_cache_add(
/* no clip (yet) */
void UI_view2d_text_cache_add_rectf(
- View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const char col[4])
+ View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const uchar col[4])
{
rcti rect;
@@ -2206,7 +2183,7 @@ void UI_view2d_text_cache_add_rectf(
}
}
-void UI_view2d_text_cache_draw(ARegion *ar)
+void UI_view2d_text_cache_draw(ARegion *region)
{
View2DString *v2s;
int col_pack_prev = 0;
@@ -2217,7 +2194,7 @@ void UI_view2d_text_cache_draw(ARegion *ar)
BLF_set_default();
const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f;
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
for (v2s = g_v2d_strings; v2s; v2s = v2s->next) {
int xofs = 0, yofs;
diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c
index 43b49825219..17a95ba3fff 100644
--- a/source/blender/editors/interface/view2d_draw.c
+++ b/source/blender/editors/interface/view2d_draw.c
@@ -32,11 +32,11 @@
#include "DNA_userdef_types.h"
#include "BLI_array.h"
-#include "BLI_utildefines.h"
-#include "BLI_rect.h"
#include "BLI_math.h"
-#include "BLI_timecode.h"
+#include "BLI_rect.h"
#include "BLI_string.h"
+#include "BLI_timecode.h"
+#include "BLI_utildefines.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
@@ -259,7 +259,7 @@ static void view2d_draw_lines(const View2D *v2d,
typedef void (*PositionToString)(
void *user_data, float v2d_pos, float v2d_step, uint max_len, char *r_str);
-static void draw_horizontal_scale_indicators(const ARegion *ar,
+static void draw_horizontal_scale_indicators(const ARegion *region,
const View2D *v2d,
float distance,
const rcti *rect,
@@ -272,7 +272,7 @@ static void draw_horizontal_scale_indicators(const ARegion *ar,
}
GPU_matrix_push_projection();
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
float start;
uint steps;
@@ -313,7 +313,7 @@ static void draw_horizontal_scale_indicators(const ARegion *ar,
GPU_matrix_pop_projection();
}
-static void draw_vertical_scale_indicators(const ARegion *ar,
+static void draw_vertical_scale_indicators(const ARegion *region,
const View2D *v2d,
float distance,
float display_offset,
@@ -327,7 +327,7 @@ static void draw_vertical_scale_indicators(const ARegion *ar,
}
GPU_matrix_push_projection();
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
float start;
uint steps;
@@ -479,51 +479,53 @@ void UI_view2d_draw_lines_x__frames_or_seconds(const View2D *v2d,
/* Scale indicator text drawing API
**************************************************/
-static void UI_view2d_draw_scale_x__discrete_values(const ARegion *ar,
+static void UI_view2d_draw_scale_x__discrete_values(const ARegion *region,
const View2D *v2d,
const rcti *rect,
int colorid)
{
float number_step = view2d_major_step_x__discrete(v2d);
draw_horizontal_scale_indicators(
- ar, v2d, number_step, rect, view_to_string__frame_number, NULL, colorid);
+ region, v2d, number_step, rect, view_to_string__frame_number, NULL, colorid);
}
static void UI_view2d_draw_scale_x__discrete_time(
- const ARegion *ar, const View2D *v2d, const rcti *rect, const Scene *scene, int colorid)
+ const ARegion *region, const View2D *v2d, const rcti *rect, const Scene *scene, int colorid)
{
float step = view2d_major_step_x__time(v2d, scene);
draw_horizontal_scale_indicators(
- ar, v2d, step, rect, view_to_string__time, (void *)scene, colorid);
+ region, v2d, step, rect, view_to_string__time, (void *)scene, colorid);
}
-static void UI_view2d_draw_scale_x__values(const ARegion *ar,
+static void UI_view2d_draw_scale_x__values(const ARegion *region,
const View2D *v2d,
const rcti *rect,
int colorid)
{
float step = view2d_major_step_x__continuous(v2d);
- draw_horizontal_scale_indicators(ar, v2d, step, rect, view_to_string__value, NULL, colorid);
+ draw_horizontal_scale_indicators(region, v2d, step, rect, view_to_string__value, NULL, colorid);
}
-void UI_view2d_draw_scale_y__values(const ARegion *ar,
+void UI_view2d_draw_scale_y__values(const ARegion *region,
const View2D *v2d,
const rcti *rect,
int colorid)
{
float step = view2d_major_step_y__continuous(v2d);
- draw_vertical_scale_indicators(ar, v2d, step, 0.0f, rect, view_to_string__value, NULL, colorid);
+ draw_vertical_scale_indicators(
+ region, v2d, step, 0.0f, rect, view_to_string__value, NULL, colorid);
}
-void UI_view2d_draw_scale_y__block(const ARegion *ar,
+void UI_view2d_draw_scale_y__block(const ARegion *region,
const View2D *v2d,
const rcti *rect,
int colorid)
{
- draw_vertical_scale_indicators(ar, v2d, 1.0f, 0.5f, rect, view_to_string__value, NULL, colorid);
+ draw_vertical_scale_indicators(
+ region, v2d, 1.0f, 0.5f, rect, view_to_string__value, NULL, colorid);
}
-void UI_view2d_draw_scale_x__discrete_frames_or_seconds(const struct ARegion *ar,
+void UI_view2d_draw_scale_x__discrete_frames_or_seconds(const struct ARegion *region,
const struct View2D *v2d,
const struct rcti *rect,
const struct Scene *scene,
@@ -531,14 +533,14 @@ void UI_view2d_draw_scale_x__discrete_frames_or_seconds(const struct ARegion *ar
int colorid)
{
if (display_seconds) {
- UI_view2d_draw_scale_x__discrete_time(ar, v2d, rect, scene, colorid);
+ UI_view2d_draw_scale_x__discrete_time(region, v2d, rect, scene, colorid);
}
else {
- UI_view2d_draw_scale_x__discrete_values(ar, v2d, rect, colorid);
+ UI_view2d_draw_scale_x__discrete_values(region, v2d, rect, colorid);
}
}
-void UI_view2d_draw_scale_x__frames_or_seconds(const struct ARegion *ar,
+void UI_view2d_draw_scale_x__frames_or_seconds(const struct ARegion *region,
const struct View2D *v2d,
const struct rcti *rect,
const struct Scene *scene,
@@ -546,9 +548,9 @@ void UI_view2d_draw_scale_x__frames_or_seconds(const struct ARegion *ar,
int colorid)
{
if (display_seconds) {
- UI_view2d_draw_scale_x__discrete_time(ar, v2d, rect, scene, colorid);
+ UI_view2d_draw_scale_x__discrete_time(region, v2d, rect, scene, colorid);
}
else {
- UI_view2d_draw_scale_x__values(ar, v2d, rect, colorid);
+ UI_view2d_draw_scale_x__values(region, v2d, rect, colorid);
}
}
diff --git a/source/blender/editors/interface/view2d_gizmo_navigate.c b/source/blender/editors/interface/view2d_gizmo_navigate.c
index d0281ad1eef..8d3f1beb947 100644
--- a/source/blender/editors/interface/view2d_gizmo_navigate.c
+++ b/source/blender/editors/interface/view2d_gizmo_navigate.c
@@ -18,12 +18,13 @@
* \ingroup edinterface
*/
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "ED_screen.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -199,9 +200,9 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *
static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
struct NavigateWidgetGroup *navgroup = gzgroup->customdata;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- const rcti *rect_visible = ED_region_visible_rect(ar);
+ const rcti *rect_visible = ED_region_visible_rect(region);
if ((navgroup->state.rect_visible.xmax == rect_visible->xmax) &&
(navgroup->state.rect_visible.ymax == rect_visible->ymax)) {
@@ -213,8 +214,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
const float icon_size = GIZMO_SIZE;
const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC;
const float co[2] = {
- rect_visible->xmax - (icon_offset_mini * 0.75f),
- rect_visible->ymax - (icon_offset_mini * 0.75f),
+ roundf(rect_visible->xmax - (icon_offset_mini * 0.75f)),
+ roundf(rect_visible->ymax - (icon_offset_mini * 0.75f)),
};
wmGizmo *gz;
@@ -227,13 +228,13 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
int icon_mini_slot = 0;
gz = navgroup->gz_array[GZ_INDEX_ZOOM];
- gz->matrix_basis[3][0] = co[0];
- gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][0] = roundf(co[0]);
+ gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
gz = navgroup->gz_array[GZ_INDEX_MOVE];
- gz->matrix_basis[3][0] = co[0];
- gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][0] = roundf(co[0]);
+ gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
}
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 5cf7cb4e7c4..5b1e5f746ef 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -29,9 +29,9 @@
#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math_base.h"
#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -43,8 +43,8 @@
#include "ED_screen.h"
-#include "UI_view2d.h"
#include "UI_interface.h"
+#include "UI_view2d.h"
#include "PIL_time.h" /* USER_ZOOM_CONT */
@@ -54,15 +54,15 @@
static bool view2d_poll(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- return (ar != NULL) && (ar->v2d.flag & V2D_IS_INITIALISED);
+ return (region != NULL) && (region->v2d.flag & V2D_IS_INITIALISED);
}
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Pan Operator
+/** \name View Pan Shared Utilities
* \{ */
/**
@@ -74,16 +74,16 @@ static bool view2d_poll(bContext *C)
* - `deltax, deltay` - define how much to move view by (relative to zoom-correction factor)
*/
-/* ------------------ Shared 'core' stuff ---------------------- */
-
-/* temp customdata for operator */
+/**
+ * Temporary custom-data for operator.
+ */
typedef struct v2dViewPanData {
/** screen where view pan was initiated */
- bScreen *sc;
+ bScreen *screen;
/** area where view pan was initiated */
- ScrArea *sa;
+ ScrArea *area;
/** region where view pan was initiated */
- ARegion *ar;
+ ARegion *region;
/** view2d we're operating in */
View2D *v2d;
@@ -105,18 +105,18 @@ typedef struct v2dViewPanData {
/* initialize panning customdata */
static int view_pan_init(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
v2dViewPanData *vpd;
View2D *v2d;
float winx, winy;
/* regions now have v2d-data by default, so check for region */
- if (ar == NULL) {
+ if (region == NULL) {
return 0;
}
/* check if panning is allowed at all */
- v2d = &ar->v2d;
+ v2d = &region->v2d;
if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) {
return 0;
}
@@ -126,14 +126,14 @@ static int view_pan_init(bContext *C, wmOperator *op)
op->customdata = vpd;
/* set pointers to owners */
- vpd->sc = CTX_wm_screen(C);
- vpd->sa = CTX_wm_area(C);
+ vpd->screen = CTX_wm_screen(C);
+ vpd->area = CTX_wm_area(C);
vpd->v2d = v2d;
- vpd->ar = ar;
+ vpd->region = region;
/* calculate translation factor - based on size of view */
- winx = (float)(BLI_rcti_size_x(&ar->winrct) + 1);
- winy = (float)(BLI_rcti_size_y(&ar->winrct) + 1);
+ winx = (float)(BLI_rcti_size_x(&region->winrct) + 1);
+ winy = (float)(BLI_rcti_size_y(&region->winrct) + 1);
vpd->facx = (BLI_rctf_size_x(&v2d->cur)) / winx;
vpd->facy = (BLI_rctf_size_y(&v2d->cur)) / winy;
@@ -143,14 +143,14 @@ static int view_pan_init(bContext *C, wmOperator *op)
#ifdef WITH_INPUT_NDOF
static bool view_pan_poll(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View2D *v2d;
/* check if there's a region in context to work with */
- if (ar == NULL) {
+ if (region == NULL) {
return 0;
}
- v2d = &ar->v2d;
+ v2d = &region->v2d;
/* check that 2d-view can pan */
if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) {
@@ -185,12 +185,12 @@ static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float
UI_view2d_curRect_validate(v2d);
/* don't rebuild full tree in outliner, since we're just changing our view */
- ED_region_tag_redraw_no_rebuild(vpd->ar);
+ ED_region_tag_redraw_no_rebuild(vpd->region);
/* request updates to be done... */
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
- UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
+ UI_view2d_sync(vpd->screen, vpd->area, v2d, V2D_LOCK_COPY);
}
static void view_pan_apply(bContext *C, wmOperator *op)
@@ -209,7 +209,11 @@ static void view_pan_exit(wmOperator *op)
}
}
-/* ------------------ Modal Drag Version (1) ---------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Pan Operator (modal drag-pan)
+ * \{ */
/* for 'redo' only, with no user input */
static int view_pan_exec(bContext *C, wmOperator *op)
@@ -306,7 +310,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
#endif
default:
- if (event->type == vpd->invoke_event || event->type == ESCKEY) {
+ if (event->type == vpd->invoke_event || event->type == EVT_ESCKEY) {
if (event->val == KM_RELEASE) {
/* calculate overall delta mouse-movement for redo */
RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx));
@@ -350,7 +354,11 @@ static void VIEW2D_OT_pan(wmOperatorType *ot)
RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
}
-/* ------------------ Scrollwheel Versions (2) ---------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Pan Operator (single step)
+ * \{ */
/* this operator only needs this single callback, where it calls the view_pan_*() methods */
static int view_scrollright_exec(bContext *C, wmOperator *op)
@@ -461,8 +469,8 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op)
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page");
if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) {
- ARegion *ar = CTX_wm_region(C);
- RNA_int_set(op->ptr, "deltay", ar->v2d.mask.ymin - ar->v2d.mask.ymax);
+ ARegion *region = CTX_wm_region(C);
+ RNA_int_set(op->ptr, "deltay", region->v2d.mask.ymin - region->v2d.mask.ymax);
}
/* apply movement, then we're done */
@@ -511,8 +519,8 @@ static int view_scrollup_exec(bContext *C, wmOperator *op)
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page");
if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) {
- ARegion *ar = CTX_wm_region(C);
- RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&ar->v2d.mask));
+ ARegion *region = CTX_wm_region(C);
+ RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&region->v2d.mask));
}
/* apply movement, then we're done */
@@ -541,7 +549,7 @@ static void VIEW2D_OT_scroll_up(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Zoom Operator (single-step)
+/** \name View Zoom Shared Utilities
* \{ */
/**
@@ -558,12 +566,12 @@ static void VIEW2D_OT_scroll_up(wmOperatorType *ot)
* amount to enlarge 'cur' by.
*/
-/* ------------------ 'Shared' stuff ------------------------ */
-
-/* temp customdata for operator */
+/**
+ * Temporary custom-data for operator.
+ */
typedef struct v2dViewZoomData {
View2D *v2d; /* view2d we're operating in */
- ARegion *ar;
+ ARegion *region;
/* needed for continuous zoom */
wmTimer *timer;
@@ -581,16 +589,16 @@ typedef struct v2dViewZoomData {
*/
static void view_zoom_axis_lock_defaults(bContext *C, bool r_do_zoom_xy[2])
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
r_do_zoom_xy[0] = true;
r_do_zoom_xy[1] = true;
/* default not to zoom the sequencer vertically */
- if (sa && sa->spacetype == SPACE_SEQ) {
- ARegion *ar = CTX_wm_region(C);
+ if (area && area->spacetype == SPACE_SEQ) {
+ ARegion *region = CTX_wm_region(C);
- if (ar && ar->regiontype == RGN_TYPE_WINDOW) {
+ if (region && region->regiontype == RGN_TYPE_WINDOW) {
r_do_zoom_xy[1] = false;
}
}
@@ -599,15 +607,15 @@ static void view_zoom_axis_lock_defaults(bContext *C, bool r_do_zoom_xy[2])
/* initialize panning customdata */
static int view_zoomdrag_init(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
v2dViewZoomData *vzd;
View2D *v2d;
/* regions now have v2d-data by default, so check for region */
- if (ar == NULL) {
+ if (region == NULL) {
return 0;
}
- v2d = &ar->v2d;
+ v2d = &region->v2d;
/* check that 2d-view is zoomable */
if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) {
@@ -620,7 +628,7 @@ static int view_zoomdrag_init(bContext *C, wmOperator *op)
/* set pointers to owners */
vzd->v2d = v2d;
- vzd->ar = ar;
+ vzd->region = region;
return 1;
}
@@ -628,11 +636,11 @@ static int view_zoomdrag_init(bContext *C, wmOperator *op)
/* check if step-zoom can be applied */
static bool view_zoom_poll(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View2D *v2d;
/* check if there's a region in context to work with */
- if (ar == NULL) {
+ if (region == NULL) {
return false;
}
@@ -641,7 +649,7 @@ static bool view_zoom_poll(bContext *C)
return false;
}
- v2d = &ar->v2d;
+ v2d = &region->v2d;
/* check that 2d-view is zoomable */
if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) {
@@ -656,11 +664,11 @@ static bool view_zoom_poll(bContext *C)
static void view_zoomstep_apply_ex(
bContext *C, v2dViewZoomData *vzd, const bool zoom_to_pos, const float facx, const float facy)
{
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
const rctf cur_old = v2d->cur;
float dx, dy;
- const int snap_test = ED_region_snap_size_test(ar);
+ const int snap_test = ED_region_snap_size_test(region);
/* calculate amount to move view by, ensuring symmetry so the
* old zoom level is restored after zooming back the same amount
@@ -749,14 +757,14 @@ static void view_zoomstep_apply_ex(
/* validate that view is in valid configuration after this operation */
UI_view2d_curRect_validate(v2d);
- if (ED_region_snap_size_apply(ar, snap_test)) {
- ScrArea *sa = CTX_wm_area(C);
- ED_area_tag_redraw(sa);
+ if (ED_region_snap_size_apply(region, snap_test)) {
+ ScrArea *area = CTX_wm_area(C);
+ ED_area_tag_redraw(area);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
}
/* request updates to be done... */
- ED_region_tag_redraw_no_rebuild(vzd->ar);
+ ED_region_tag_redraw_no_rebuild(vzd->region);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
@@ -768,7 +776,11 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
C, vzd, zoom_to_pos, RNA_float_get(op->ptr, "zoomfacx"), RNA_float_get(op->ptr, "zoomfacy"));
}
-/* --------------- Individual Operators ------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Zoom Operator (single step)
+ * \{ */
/* cleanup temp customdata */
static void view_zoomstep_exit(wmOperator *op)
@@ -816,10 +828,11 @@ static int view_zoomin_invoke(bContext *C, wmOperator *op, const wmEvent *event)
vzd = op->customdata;
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* store initial mouse position (in view space) */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d);
}
return view_zoomin_exec(C, op);
@@ -883,10 +896,11 @@ static int view_zoomout_invoke(bContext *C, wmOperator *op, const wmEvent *event
vzd = op->customdata;
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* store initial mouse position (in view space) */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d);
}
return view_zoomout_exec(C, op);
@@ -934,7 +948,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
v2dViewZoomData *vzd = op->customdata;
View2D *v2d = vzd->v2d;
float dx, dy;
- const int snap_test = ED_region_snap_size_test(vzd->ar);
+ const int snap_test = ED_region_snap_size_test(vzd->region);
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
const bool zoom_to_pos = use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS);
@@ -1002,14 +1016,14 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
/* validate that view is in valid configuration after this operation */
UI_view2d_curRect_validate(v2d);
- if (ED_region_snap_size_apply(vzd->ar, snap_test)) {
- ScrArea *sa = CTX_wm_area(C);
- ED_area_tag_redraw(sa);
+ if (ED_region_snap_size_apply(vzd->region, snap_test)) {
+ ScrArea *area = CTX_wm_area(C);
+ ED_area_tag_redraw(area);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
}
/* request updates to be done... */
- ED_region_tag_redraw_no_rebuild(vzd->ar);
+ ED_region_tag_redraw_no_rebuild(vzd->region);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
@@ -1106,10 +1120,11 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
vzd->invoke_event = event->type;
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* store initial mouse position (in view space) */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d);
}
if (v2d->keepofs & V2D_LOCKOFS_X) {
@@ -1163,16 +1178,16 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event
/* x-axis transform */
dist = BLI_rcti_size_x(&v2d->mask) / 2.0f;
- len_old[0] = fabsf(vzd->lastx - vzd->ar->winrct.xmin - dist);
- len_new[0] = fabsf(event->x - vzd->ar->winrct.xmin - dist);
+ len_old[0] = fabsf(vzd->lastx - vzd->region->winrct.xmin - dist);
+ len_new[0] = fabsf(event->x - vzd->region->winrct.xmin - dist);
len_old[0] *= zoomfac * BLI_rctf_size_x(&v2d->cur);
len_new[0] *= zoomfac * BLI_rctf_size_x(&v2d->cur);
/* y-axis transform */
dist = BLI_rcti_size_y(&v2d->mask) / 2.0f;
- len_old[1] = fabsf(vzd->lasty - vzd->ar->winrct.ymin - dist);
- len_new[1] = fabsf(event->y - vzd->ar->winrct.ymin - dist);
+ len_old[1] = fabsf(vzd->lasty - vzd->region->winrct.ymin - dist);
+ len_new[1] = fabsf(event->y - vzd->region->winrct.ymin - dist);
len_old[1] *= zoomfac * BLI_rctf_size_y(&v2d->cur);
len_new[1] *= zoomfac * BLI_rctf_size_y(&v2d->cur);
@@ -1241,7 +1256,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event
/* apply zooming */
view_zoomdrag_apply(C, op);
}
- else if (event->type == vzd->invoke_event || event->type == ESCKEY) {
+ else if (event->type == vzd->invoke_event || event->type == EVT_ESCKEY) {
if (event->val == KM_RELEASE) {
/* for redo, store the overall deltas - need to respect zoom-locks here... */
@@ -1317,8 +1332,8 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot)
static int view_borderzoom_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
rctf rect;
rctf cur_new = v2d->cur;
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
@@ -1373,7 +1388,7 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op)
}
}
- UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
+ UI_view2d_smooth_view(C, region, &cur_new, smooth_viewtx);
return OPERATOR_FINISHED;
}
@@ -1397,6 +1412,12 @@ static void VIEW2D_OT_zoom_border(wmOperatorType *ot)
WM_operator_properties_gesture_box_zoom(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Pan/Zoom Operator
+ * \{ */
+
#ifdef WITH_INPUT_NDOF
static int view2d_ndof_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -1524,12 +1545,12 @@ static float smooth_view_rect_to_fac(const rctf *rect_a, const rctf *rect_b)
/* will start timer if appropriate */
/* the arguments are the desired situation */
-void UI_view2d_smooth_view(bContext *C, ARegion *ar, const rctf *cur, const int smooth_viewtx)
+void UI_view2d_smooth_view(bContext *C, ARegion *region, const rctf *cur, const int smooth_viewtx)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
struct SmoothView2DStore sms = {{0}};
bool ok = false;
float fac = 1.0f;
@@ -1584,7 +1605,7 @@ void UI_view2d_smooth_view(bContext *C, ARegion *ar, const rctf *cur, const int
v2d->cur = sms.new_cur;
UI_view2d_curRect_validate(v2d);
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
}
@@ -1592,8 +1613,9 @@ void UI_view2d_smooth_view(bContext *C, ARegion *ar, const rctf *cur, const int
/* only meant for timer usage */
static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
struct SmoothView2DStore *sms = v2d->sms;
float step;
@@ -1616,11 +1638,11 @@ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
MEM_freeN(v2d->sms);
v2d->sms = NULL;
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), v2d->smooth_timer);
+ WM_event_remove_timer(CTX_wm_manager(C), win, v2d->smooth_timer);
v2d->smooth_timer = NULL;
/* Event handling won't know if a UI item has been moved under the pointer. */
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(win);
}
else {
/* ease in/out */
@@ -1631,7 +1653,7 @@ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
UI_view2d_curRect_validate(v2d);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
if (v2d->sms == NULL) {
UI_view2d_zoom_cache_reset();
@@ -1678,7 +1700,7 @@ typedef struct v2dScrollerMove {
/** View2D data that this operation affects */
View2D *v2d;
/** region that the scroller is in */
- ARegion *ar;
+ ARegion *region;
/** scroller that mouse is in ('h' or 'v') */
char scroller;
@@ -1727,8 +1749,6 @@ enum {
SCROLLHANDLE_MAX_OUTSIDE,
} /*eV2DScrollerHandle_Zone*/;
-/* ------------------------ */
-
/**
* Check if mouse is within scroller handle.
*
@@ -1738,46 +1758,32 @@ enum {
*/
static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_min, int sh_max)
{
- bool in_min, in_max, in_bar, out_min, out_max, in_view = 1;
-
/* firstly, check if
* - 'bubble' fills entire scroller
* - 'bubble' completely out of view on either side
*/
- if ((sh_min <= sc_min) && (sh_max >= sc_max)) {
- in_view = 0;
+ bool in_view = true;
+ if (sh_min <= sc_min && sc_max <= sh_max) {
+ in_view = false;
}
- if (sh_min == sh_max) {
- if (sh_min <= sc_min) {
- in_view = 0;
- }
- if (sh_max >= sc_max) {
- in_view = 0;
- }
- }
- else {
- if (sh_max <= sc_min) {
- in_view = 0;
- }
- if (sh_min >= sc_max) {
- in_view = 0;
- }
+ else if (sh_max <= sc_min || sc_max <= sh_min) {
+ in_view = false;
}
- if (in_view == 0) {
+ if (!in_view) {
return SCROLLHANDLE_BAR;
}
/* check if mouse is in or past either handle */
/* TODO: check if these extents are still valid or not */
- in_max = ((mouse >= (sh_max - V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) &&
- (mouse <= (sh_max + V2D_SCROLL_HANDLE_SIZE_HOTSPOT)));
- in_min = ((mouse <= (sh_min + V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) &&
- (mouse >= (sh_min - V2D_SCROLL_HANDLE_SIZE_HOTSPOT)));
- in_bar = ((mouse < (sh_max - V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) &&
- (mouse > (sh_min + V2D_SCROLL_HANDLE_SIZE_HOTSPOT)));
- out_min = mouse < (sh_min - V2D_SCROLL_HANDLE_SIZE_HOTSPOT);
- out_max = mouse > (sh_max + V2D_SCROLL_HANDLE_SIZE_HOTSPOT);
+ bool in_max = ((mouse >= (sh_max - V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) &&
+ (mouse <= (sh_max + V2D_SCROLL_HANDLE_SIZE_HOTSPOT)));
+ bool in_min = ((mouse <= (sh_min + V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) &&
+ (mouse >= (sh_min - V2D_SCROLL_HANDLE_SIZE_HOTSPOT)));
+ bool in_bar = ((mouse < (sh_max - V2D_SCROLL_HANDLE_SIZE_HOTSPOT)) &&
+ (mouse > (sh_min + V2D_SCROLL_HANDLE_SIZE_HOTSPOT)));
+ bool out_min = mouse < (sh_min - V2D_SCROLL_HANDLE_SIZE_HOTSPOT);
+ bool out_max = mouse > (sh_max + V2D_SCROLL_HANDLE_SIZE_HOTSPOT);
if (in_bar) {
return SCROLLHANDLE_BAR;
@@ -1806,12 +1812,12 @@ static bool scroller_activate_poll(bContext *C)
}
wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
wmEvent *event = win->eventstate;
/* check if mouse in scrollbars, if they're enabled */
- return (UI_view2d_mouse_in_scrollers(ar, v2d, event->x, event->y) != 0);
+ return (UI_view2d_mouse_in_scrollers(region, v2d, event->x, event->y) != 0);
}
/* initialize customdata for scroller manipulation operator */
@@ -1822,8 +1828,8 @@ static void scroller_activate_init(bContext *C,
{
v2dScrollerMove *vsm;
View2DScrollers *scrollers;
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
rctf tot_cur_union;
float mask_size;
@@ -1833,7 +1839,7 @@ static void scroller_activate_init(bContext *C,
/* set general data */
vsm->v2d = v2d;
- vsm->ar = ar;
+ vsm->region = region;
vsm->scroller = in_scroller;
/* store mouse-coordinates, and convert mouse/screen coordinates to region coordinates */
@@ -1855,7 +1861,7 @@ static void scroller_activate_init(bContext *C,
vsm->fac = BLI_rctf_size_x(&tot_cur_union) / mask_size;
/* pixel rounding */
- vsm->fac_round = (BLI_rctf_size_x(&v2d->cur)) / (float)(BLI_rcti_size_x(&ar->winrct) + 1);
+ vsm->fac_round = (BLI_rctf_size_x(&v2d->cur)) / (float)(BLI_rcti_size_x(&region->winrct) + 1);
/* get 'zone' (i.e. which part of scroller is activated) */
vsm->zone = mouse_in_scroller_handle(
@@ -1867,7 +1873,7 @@ static void scroller_activate_init(bContext *C,
}
vsm->scrollbarwidth = scrollers->hor_max - scrollers->hor_min;
- vsm->scrollbar_orig = ((scrollers->hor_max + scrollers->hor_min) / 2) + ar->winrct.xmin;
+ vsm->scrollbar_orig = ((scrollers->hor_max + scrollers->hor_min) / 2) + region->winrct.xmin;
}
else {
/* vertical scroller - calculate adjustment factor first */
@@ -1875,7 +1881,7 @@ static void scroller_activate_init(bContext *C,
vsm->fac = BLI_rctf_size_y(&tot_cur_union) / mask_size;
/* pixel rounding */
- vsm->fac_round = (BLI_rctf_size_y(&v2d->cur)) / (float)(BLI_rcti_size_y(&ar->winrct) + 1);
+ vsm->fac_round = (BLI_rctf_size_y(&v2d->cur)) / (float)(BLI_rcti_size_y(&region->winrct) + 1);
/* get 'zone' (i.e. which part of scroller is activated) */
vsm->zone = mouse_in_scroller_handle(
@@ -1887,11 +1893,11 @@ static void scroller_activate_init(bContext *C,
}
vsm->scrollbarwidth = scrollers->vert_max - scrollers->vert_min;
- vsm->scrollbar_orig = ((scrollers->vert_max + scrollers->vert_min) / 2) + ar->winrct.ymin;
+ vsm->scrollbar_orig = ((scrollers->vert_max + scrollers->vert_min) / 2) + region->winrct.ymin;
}
UI_view2d_scrollers_free(scrollers);
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
/* cleanup temp customdata */
@@ -1970,7 +1976,7 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
UI_view2d_curRect_validate(v2d);
/* request updates to be done... */
- ED_region_tag_redraw_no_rebuild(vsm->ar);
+ ED_region_tag_redraw_no_rebuild(vsm->region);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
@@ -2053,11 +2059,11 @@ static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *e
* should have occurred, so check if it happened in scrollbar */
static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
/* check if mouse in scrollbars, if they're enabled */
- const char in_scroller = UI_view2d_mouse_in_scrollers(ar, v2d, event->x, event->y);
+ const char in_scroller = UI_view2d_mouse_in_scrollers(region, v2d, event->x, event->y);
/* if in a scroller, init customdata then set modal handler which will
* catch mouse-down to start doing useful stuff */
@@ -2165,11 +2171,11 @@ static void VIEW2D_OT_scroller_activate(wmOperatorType *ot)
static int reset_exec(bContext *C, wmOperator *UNUSED(op))
{
- uiStyle *style = UI_style_get();
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ const uiStyle *style = UI_style_get();
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
int winx, winy;
- const int snap_test = ED_region_snap_size_test(ar);
+ const int snap_test = ED_region_snap_size_test(region);
/* zoom 1.0 */
winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
@@ -2204,14 +2210,14 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
/* validate that view is in valid configuration after this operation */
UI_view2d_curRect_validate(v2d);
- if (ED_region_snap_size_apply(ar, snap_test)) {
- ScrArea *sa = CTX_wm_area(C);
- ED_area_tag_redraw(sa);
+ if (ED_region_snap_size_apply(region, snap_test)) {
+ ScrArea *area = CTX_wm_area(C);
+ ED_area_tag_redraw(area);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
}
/* request updates to be done... */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
UI_view2d_zoom_cache_reset();
diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index 5afe348158f..39548449a86 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -17,16 +17,16 @@
set(INC
../include
- ../../alembic
../../blenkernel
../../blenlib
../../blentranslation
../../bmesh
- ../../collada
../../depsgraph
+ ../../io/alembic
+ ../../io/collada
+ ../../io/usd
../../makesdna
../../makesrna
- ../../usd
../../windowmanager
../../../../intern/guardedalloc
)
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index 9f9e523b57b..551f7989d53 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Blender Foundation.
@@ -30,8 +30,8 @@
# include "BLI_winstuff.h"
# endif
-# include <string.h>
# include <errno.h>
+# include <string.h>
# include "MEM_guardedalloc.h"
diff --git a/source/blender/editors/io/io_alembic.h b/source/blender/editors/io/io_alembic.h
index 881712fe630..ecd8c1818f8 100644
--- a/source/blender/editors/io/io_alembic.h
+++ b/source/blender/editors/io/io_alembic.h
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Blender Foundation.
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index ff2bc72c2f7..045a293f71b 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Blender Foundation.
@@ -32,7 +32,7 @@
#include "BKE_cachefile.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/io/io_cache.h b/source/blender/editors/io/io_cache.h
index 25548dcdbce..c6fc50a236e 100644
--- a/source/blender/editors/io/io_cache.h
+++ b/source/blender/editors/io/io_cache.h
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Blender Foundation.
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 3f51504d6ac..9091e7d8afc 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -36,8 +36,8 @@
# include "DEG_depsgraph.h"
-# include "ED_screen.h"
# include "ED_object.h"
+# include "ED_screen.h"
# include "RNA_access.h"
# include "RNA_define.h"
@@ -48,7 +48,7 @@
# include "WM_api.h"
# include "WM_types.h"
-# include "../../collada/collada.h"
+# include "collada.h"
# include "io_collada.h"
diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c
index bb527ee6a3f..262b15c63e5 100644
--- a/source/blender/editors/io/io_usd.c
+++ b/source/blender/editors/io/io_usd.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
diff --git a/source/blender/editors/io/io_usd.h b/source/blender/editors/io/io_usd.h
index 4738e1c348d..c794dc744df 100644
--- a/source/blender/editors/io/io_usd.h
+++ b/source/blender/editors/io/io_usd.h
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
diff --git a/source/blender/editors/lanpr/lanpr_cpu.c b/source/blender/editors/lanpr/lanpr_cpu.c
index 106054bb32f..38f82b53418 100644
--- a/source/blender/editors/lanpr/lanpr_cpu.c
+++ b/source/blender/editors/lanpr/lanpr_cpu.c
@@ -23,32 +23,32 @@
#include "ED_lanpr.h"
-#include "BLI_listbase.h"
+#include "BLI_alloca.h"
#include "BLI_linklist.h"
+#include "BLI_listbase.h"
#include "BLI_math_matrix.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
-#include "BLI_alloca.h"
-#include "BKE_object.h"
-#include "DNA_mesh_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_text_types.h"
-#include "DNA_lanpr_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_meshdata_types.h"
-#include "BKE_customdata.h"
-#include "DEG_depsgraph_query.h"
#include "BKE_camera.h"
-#include "BKE_gpencil.h"
#include "BKE_collection.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_gpencil.h"
+#include "BKE_object.h"
#include "BKE_report.h"
-#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "BKE_text.h"
-#include "BKE_context.h"
+#include "DEG_depsgraph_query.h"
+#include "DNA_camera_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_lanpr_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_text_types.h"
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
@@ -61,8 +61,8 @@
#include "bmesh_class.h"
#include "bmesh_tools.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "BKE_text.h"
@@ -648,8 +648,7 @@ static bool lanpr_calculation_is_canceled(void)
return is_canceled;
}
static void lanpr_calculate_line_occlusion_worker(TaskPool *__restrict UNUSED(pool),
- LANPR_RenderTaskInfo *rti,
- int UNUSED(threadid))
+ LANPR_RenderTaskInfo *rti)
{
LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared;
LinkData *lip;
@@ -703,7 +702,6 @@ static void lanpr_calculate_line_occlusion_begin(LANPR_RenderBuffer *rb)
int thread_count = rb->thread_count;
LANPR_RenderTaskInfo *rti = MEM_callocN(sizeof(LANPR_RenderTaskInfo) * thread_count,
"Task Pool");
- TaskScheduler *scheduler = BLI_task_scheduler_get();
int i;
rb->contour_managed = rb->contours.first;
@@ -712,15 +710,12 @@ static void lanpr_calculate_line_occlusion_begin(LANPR_RenderBuffer *rb)
rb->material_managed = rb->material_lines.first;
rb->edge_mark_managed = rb->edge_marks.first;
- TaskPool *tp = BLI_task_pool_create(scheduler, 0);
+ TaskPool *tp = BLI_task_pool_create(NULL, TASK_PRIORITY_HIGH);
for (i = 0; i < thread_count; i++) {
rti[i].thread_id = i;
- BLI_task_pool_push(tp,
- (TaskRunFunction)lanpr_calculate_line_occlusion_worker,
- &rti[i],
- 0,
- TASK_PRIORITY_HIGH);
+ BLI_task_pool_push(
+ tp, (TaskRunFunction)lanpr_calculate_line_occlusion_worker, &rti[i], 0, NULL);
}
BLI_task_pool_work_and_wait(tp);
BLI_task_pool_free(tp);
@@ -2004,7 +1999,7 @@ static int lanpr_triangle_line_imagespace_intersection_v2(SpinLock *UNUSED(spl),
trans[1] -= cam_shift_y * 2;
/* To accomodate k=0 and k=inf (vertical) lines. */
- if (ABS(rl->l->fbcoord[0] - rl->r->fbcoord[0]) > ABS(rl->l->fbcoord[1] - rl->r->fbcoord[1])) {
+ if (fabs(rl->l->fbcoord[0] - rl->r->fbcoord[0]) > fabs(rl->l->fbcoord[1] - rl->r->fbcoord[1])) {
cut = tmat_get_linear_ratio(rl->l->fbcoord[0], rl->r->fbcoord[0], trans[0]);
}
else {
@@ -3814,8 +3809,7 @@ typedef struct LANPR_FeatureLineWorker {
} LANPR_FeatureLineWorker;
static void lanpr_compute_feature_lines_worker(TaskPool *__restrict UNUSED(pool),
- LANPR_FeatureLineWorker *worker_data,
- int UNUSED(threadid))
+ LANPR_FeatureLineWorker *worker_data)
{
ED_lanpr_compute_feature_lines_internal(worker_data->dg, worker_data->intersection_only);
}
@@ -3842,18 +3836,16 @@ void ED_lanpr_compute_feature_lines_background(Depsgraph *dg, const int intersec
ED_lanpr_calculation_set_flag(LANPR_RENDER_RUNNING);
LANPR_FeatureLineWorker *flw = MEM_callocN(sizeof(LANPR_FeatureLineWorker), "Task Pool");
- TaskScheduler *scheduler = BLI_task_scheduler_get();
flw->dg = dg;
flw->intersection_only = intersection_only;
- TaskPool *tp = BLI_task_pool_create_background(scheduler, flw);
+ TaskPool *tp = BLI_task_pool_create_background(flw, TASK_PRIORITY_HIGH);
BLI_spin_lock(&lanpr_share.lock_render_status);
lanpr_share.background_render_task = tp;
BLI_spin_unlock(&lanpr_share.lock_render_status);
- BLI_task_pool_push(
- tp, (TaskRunFunction)lanpr_compute_feature_lines_worker, flw, true, TASK_PRIORITY_HIGH);
+ BLI_task_pool_push(tp, (TaskRunFunction)lanpr_compute_feature_lines_worker, flw, true, NULL);
}
static bool lanpr_camera_exists(bContext *c)
@@ -3998,7 +3990,7 @@ static void lanpr_generate_gpencil_from_chain(Depsgraph *depsgraph,
int array_idx = 0;
int count = ED_lanpr_count_chain(rlc);
- bGPDstroke *gps = BKE_gpencil_add_stroke(gpf, color_idx, count, thickness);
+ bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, color_idx, count, thickness, false);
float *stroke_data = BLI_array_alloca(stroke_data, count * GP_PRIM_DATABUF_SIZE);
@@ -4026,7 +4018,7 @@ static void lanpr_clear_gp_lanpr_flags(Depsgraph *dg, int frame)
bGPdata *gpd = ((Object *)o->id.orig_id)->data;
bGPDlayer *gpl;
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, frame);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_find(gpl, frame);
if (gpf == NULL) {
continue;
}
@@ -4055,7 +4047,7 @@ static void lanpr_update_gp_strokes_single(Depsgraph *dg,
if (gpl == NULL) {
gpl = BKE_gpencil_layer_addnew(gpd, "lanpr_layer", true);
}
- gpf = BKE_gpencil_layer_getframe(gpl, frame, GP_GETFRAME_ADD_NEW);
+ gpf = BKE_gpencil_layer_frame_get(gpl, frame, GP_GETFRAME_ADD_NEW);
if (gpf->strokes.first &&
!(DEG_get_evaluated_scene(dg)->lanpr.flags & LANPR_GPENCIL_OVERWRITE)) {
diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c
index 837c5b1c6bd..8751a289b9c 100644
--- a/source/blender/editors/lattice/editlattice_select.c
+++ b/source/blender/editors/lattice/editlattice_select.c
@@ -25,11 +25,11 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_rand.h"
-#include "BLI_bitmap.h"
+#include "BLI_utildefines.h"
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
@@ -43,13 +43,13 @@
#include "BKE_context.h"
#include "BKE_lattice.h"
-#include "BKE_report.h"
#include "BKE_layer.h"
+#include "BKE_report.h"
+#include "ED_lattice.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "ED_lattice.h"
#include "ED_view3d.h"
#include "WM_api.h"
diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c
index ed2560698b6..cfc9d162c37 100644
--- a/source/blender/editors/lattice/editlattice_undo.c
+++ b/source/blender/editors/lattice/editlattice_undo.c
@@ -21,16 +21,16 @@
* \ingroup edlattice
*/
+#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include "MEM_guardedalloc.h"
#include "CLG_log.h"
-#include "BLI_utildefines.h"
#include "BLI_array_utils.h"
+#include "BLI_utildefines.h"
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
@@ -44,13 +44,13 @@
#include "DEG_depsgraph.h"
-#include "ED_object.h"
#include "ED_lattice.h"
+#include "ED_object.h"
#include "ED_undo.h"
#include "ED_util.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "lattice_intern.h"
@@ -146,7 +146,8 @@ static int validate_undoLatt(void *data, void *edata)
static Object *editlatt_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
if (obedit && obedit->type == OB_LATTICE) {
Lattice *lt = obedit->data;
if (lt->editlatt != NULL) {
@@ -189,8 +190,7 @@ static bool lattice_undosys_step_encode(struct bContext *C, Main *bmain, UndoSte
* outside of this list will be moved out of edit-mode when reading back undo steps. */
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, NULL, &objects_len);
+ Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
us->elems_len = objects_len;
diff --git a/source/blender/editors/lattice/lattice_ops.c b/source/blender/editors/lattice/lattice_ops.c
index a665d138163..d5505c00132 100644
--- a/source/blender/editors/lattice/lattice_ops.c
+++ b/source/blender/editors/lattice/lattice_ops.c
@@ -28,10 +28,10 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_lattice.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "ED_object.h"
-#include "ED_lattice.h"
#include "lattice_intern.h"
diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt
index 81c861ab4e4..66c055d9426 100644
--- a/source/blender/editors/mask/CMakeLists.txt
+++ b/source/blender/editors/mask/CMakeLists.txt
@@ -40,6 +40,7 @@ set(SRC
mask_edit.c
mask_editaction.c
mask_ops.c
+ mask_query.c
mask_relationships.c
mask_select.c
mask_shapekey.c
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 5c730c74df7..767976b5ae6 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -29,176 +29,23 @@
#include "BKE_mask.h"
#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
+#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
-#include "DNA_mask_types.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_select_utils.h"
#include "ED_mask.h" /* own include */
#include "ED_screen.h"
+#include "ED_select_utils.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "mask_intern.h" /* own include */
-bool ED_mask_find_nearest_diff_point(const bContext *C,
- struct Mask *mask_orig,
- const float normal_co[2],
- int threshold,
- bool feather,
- float tangent[2],
- const bool use_deform,
- const bool use_project,
- MaskLayer **mask_layer_r,
- MaskSpline **spline_r,
- MaskSplinePoint **point_r,
- float *u_r,
- float *score_r)
-{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- MaskLayer *point_mask_layer;
- MaskSpline *point_spline;
- MaskSplinePoint *point = NULL;
- float dist_best_sq = FLT_MAX, co[2];
- int width, height;
- float u = 0.0f;
- float scalex, scaley;
-
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
-
- ED_mask_get_size(sa, &width, &height);
- ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
-
- co[0] = normal_co[0] * scalex;
- co[1] = normal_co[1] * scaley;
-
- for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first,
- *mask_layer_eval = mask_eval->masklayers.first;
- mask_layer_orig != NULL;
- mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) {
- if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (MaskSpline *spline_orig = mask_layer_orig->splines.first,
- *spline_eval = mask_layer_eval->splines.first;
- spline_orig != NULL;
- spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
- int i;
- MaskSplinePoint *cur_point_eval;
-
- for (i = 0, cur_point_eval = use_deform ? spline_eval->points_deform : spline_eval->points;
- i < spline_eval->tot_point;
- i++, cur_point_eval++) {
- unsigned int tot_diff_point;
- float *diff_points = BKE_mask_point_segment_diff(
- spline_eval, cur_point_eval, width, height, &tot_diff_point);
-
- if (diff_points) {
- int j, tot_point;
- unsigned int tot_feather_point;
- float *feather_points = NULL, *points;
-
- if (feather) {
- feather_points = BKE_mask_point_segment_feather_diff(
- spline_eval, cur_point_eval, width, height, &tot_feather_point);
-
- points = feather_points;
- tot_point = tot_feather_point;
- }
- else {
- points = diff_points;
- tot_point = tot_diff_point;
- }
-
- for (j = 0; j < tot_point - 1; j++) {
- float dist_sq, a[2], b[2];
-
- a[0] = points[2 * j] * scalex;
- a[1] = points[2 * j + 1] * scaley;
-
- b[0] = points[2 * j + 2] * scalex;
- b[1] = points[2 * j + 3] * scaley;
-
- dist_sq = dist_squared_to_line_segment_v2(co, a, b);
-
- if (dist_sq < dist_best_sq) {
- if (tangent) {
- sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]);
- }
-
- point_mask_layer = mask_layer_orig;
- point_spline = spline_orig;
- point = use_deform ?
- &spline_orig->points[(cur_point_eval - spline_eval->points_deform)] :
- &spline_orig->points[(cur_point_eval - spline_eval->points)];
- dist_best_sq = dist_sq;
- u = (float)j / tot_point;
- }
- }
-
- if (feather_points != NULL) {
- MEM_freeN(feather_points);
- }
- MEM_freeN(diff_points);
- }
- }
- }
- }
-
- if (point && dist_best_sq < threshold) {
- if (mask_layer_r) {
- *mask_layer_r = point_mask_layer;
- }
-
- if (spline_r) {
- *spline_r = point_spline;
- }
-
- if (point_r) {
- *point_r = point;
- }
-
- if (u_r) {
- /* TODO(sergey): Projection fails in some weirdo cases.. */
- if (use_project) {
- u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY);
- }
-
- *u_r = u;
- }
-
- if (score_r) {
- *score_r = dist_best_sq;
- }
-
- return true;
- }
-
- if (mask_layer_r) {
- *mask_layer_r = NULL;
- }
-
- if (spline_r) {
- *spline_r = NULL;
- }
-
- if (point_r) {
- *point_r = NULL;
- }
-
- return false;
-}
-
/******************** add vertex *********************/
static void setup_vertex_point(Mask *mask,
@@ -597,11 +444,11 @@ static void mask_point_make_pixel_space(bContext *C,
float point_normalized[2],
float point_pixel[2])
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
float scalex, scaley;
- ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
+ ED_mask_pixelspace_factor(area, region, &scalex, &scaley);
point_pixel[0] = point_normalized[0] * scalex;
point_pixel[1] = point_normalized[1] * scaley;
@@ -709,12 +556,12 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
float co[2];
- ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_mouse_pos(area, region, event->mval, co);
RNA_float_set_array(op->ptr, "location", co);
@@ -801,12 +648,12 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
static int add_feather_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
float co[2];
- ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_mouse_pos(area, region, event->mval, co);
RNA_float_set_array(op->ptr, "location", co);
@@ -846,7 +693,7 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot)
static int create_primitive_from_points(
bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Mask *mask;
MaskLayer *mask_layer;
MaskSpline *new_spline;
@@ -854,7 +701,7 @@ static int create_primitive_from_points(
int i, width, height;
int size = RNA_float_get(op->ptr, "size");
- ED_mask_get_size(sa, &width, &height);
+ ED_mask_get_size(area, &width, &height);
scale = (float)size / max_ii(width, height);
/* Get location in mask space. */
@@ -915,12 +762,12 @@ static int create_primitive_from_points(
static int primitive_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
float cursor[2];
int width, height;
- ED_mask_get_size(sa, &width, &height);
- ED_mask_cursor_location_get(sa, cursor);
+ ED_mask_get_size(area, &width, &height);
+ ED_mask_cursor_location_get(area, cursor);
cursor[0] *= width;
cursor[1] *= height;
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 71aa860d703..bea44ee89f8 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -23,17 +23,17 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_mask.h"
#include "DNA_mask_types.h"
-#include "DNA_screen_types.h"
#include "DNA_object_types.h" /* SELECT */
+#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "ED_clip.h"
@@ -44,8 +44,8 @@
#include "BIF_glutil.h"
#include "GPU_immediate.h"
-#include "GPU_shader.h"
#include "GPU_matrix.h"
+#include "GPU_shader.h"
#include "GPU_state.h"
#include "UI_interface.h"
@@ -54,12 +54,10 @@
#include "DEG_depsgraph_query.h"
-#include "mask_intern.h" /* own include */
-
static void mask_spline_color_get(MaskLayer *mask_layer,
MaskSpline *spline,
const bool is_sel,
- unsigned char r_rgb[4])
+ uchar r_rgb[4])
{
if (is_sel) {
if (mask_layer->act_spline == spline) {
@@ -81,7 +79,7 @@ static void mask_spline_color_get(MaskLayer *mask_layer,
static void mask_spline_feather_color_get(MaskLayer *UNUSED(mask_layer),
MaskSpline *UNUSED(spline),
const bool is_sel,
- unsigned char r_rgb[4])
+ uchar r_rgb[4])
{
if (is_sel) {
r_rgb[1] = 255;
@@ -126,7 +124,7 @@ static void draw_single_handle(const MaskLayer *mask_layer,
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
+ const uchar rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ubv(rgb_gray);
@@ -196,7 +194,7 @@ static void draw_spline_points(const bContext *C,
(mask_layer->restrictflag & MASK_RESTRICT_SELECT) == 0;
const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0;
- unsigned char rgb_spline[4];
+ uchar rgb_spline[4];
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
SpaceClip *sc = CTX_wm_space_clip(C);
bool undistort = false;
@@ -370,28 +368,26 @@ static void draw_spline_points(const bContext *C,
}
}
-static void mask_color_active_tint(unsigned char r_rgb[4],
- const unsigned char rgb[4],
- const bool is_active)
+static void mask_color_active_tint(uchar r_rgb[4], const uchar rgb[4], const bool is_active)
{
if (!is_active) {
- r_rgb[0] = (unsigned char)((((int)(rgb[0])) + 128) / 2);
- r_rgb[1] = (unsigned char)((((int)(rgb[1])) + 128) / 2);
- r_rgb[2] = (unsigned char)((((int)(rgb[2])) + 128) / 2);
+ r_rgb[0] = (uchar)((((int)(rgb[0])) + 128) / 2);
+ r_rgb[1] = (uchar)((((int)(rgb[1])) + 128) / 2);
+ r_rgb[2] = (uchar)((((int)(rgb[2])) + 128) / 2);
r_rgb[3] = rgb[3];
}
else {
- *(unsigned int *)r_rgb = *(const unsigned int *)rgb;
+ *(uint *)r_rgb = *(const uint *)rgb;
}
}
-static void mask_draw_array(unsigned int pos,
+static void mask_draw_array(uint pos,
GPUPrimType prim_type,
const float (*points)[2],
- unsigned int vertex_len)
+ uint vertex_len)
{
immBegin(prim_type, vertex_len);
- for (unsigned int i = 0; i < vertex_len; i++) {
+ for (uint i = 0; i < vertex_len; i++) {
immVertex2fv(pos, points[i]);
}
immEnd();
@@ -403,13 +399,13 @@ static void mask_draw_curve_type(const bContext *C,
int tot_point,
const bool is_feather,
const bool is_active,
- const unsigned char rgb_spline[4],
+ const uchar rgb_spline[4],
const char draw_type)
{
const GPUPrimType draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GPU_PRIM_LINE_LOOP :
GPU_PRIM_LINE_STRIP;
- const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
- unsigned char rgb_tmp[4];
+ const uchar rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
+ uchar rgb_tmp[4];
SpaceClip *sc = CTX_wm_space_clip(C);
float(*points)[2] = orig_points;
@@ -471,9 +467,9 @@ static void mask_draw_curve_type(const bContext *C,
}
if (is_feather) {
- rgb_tmp[0] = (unsigned char)(((short)rgb_tmp[0] + (short)rgb_spline[0]) / 2);
- rgb_tmp[1] = (unsigned char)(((short)rgb_tmp[1] + (short)rgb_spline[1]) / 2);
- rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2);
+ rgb_tmp[0] = (uchar)(((short)rgb_tmp[0] + (short)rgb_spline[0]) / 2);
+ rgb_tmp[1] = (uchar)(((short)rgb_tmp[1] + (short)rgb_spline[1]) / 2);
+ rgb_tmp[2] = (uchar)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2);
}
mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
@@ -527,20 +523,20 @@ static void draw_spline_curve(const bContext *C,
const int width,
const int height)
{
- const unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height),
- BKE_mask_spline_resolution(spline, width, height));
+ const uint resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height),
+ BKE_mask_spline_resolution(spline, width, height));
- unsigned char rgb_tmp[4];
+ uchar rgb_tmp[4];
const bool is_spline_sel = (spline->flag & SELECT) &&
(mask_layer->restrictflag & MASK_RESTRICT_SELECT) == 0;
const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0;
const bool is_fill = (spline->flag & MASK_SPLINE_NOFILL) == 0;
- unsigned int tot_diff_point;
+ uint tot_diff_point;
float(*diff_points)[2];
- unsigned int tot_feather_point;
+ uint tot_feather_point;
float(*feather_points)[2];
diff_points = BKE_mask_spline_differentiate_with_resolution(spline, &tot_diff_point, resol);
@@ -614,7 +610,7 @@ static void draw_mask_layers(const bContext *C,
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
/* draw curve itself first... */
draw_spline_curve(C, mask_layer, spline, draw_flag, draw_type, is_active, width, height);
@@ -642,7 +638,7 @@ static void draw_mask_layers(const bContext *C,
void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Mask *mask = CTX_data_edit_mask(C);
int width, height;
@@ -650,7 +646,7 @@ void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type)
return;
}
- ED_mask_get_size(sa, &width, &height);
+ ED_mask_get_size(area, &width, &height);
draw_mask_layers(C, mask, draw_flag, draw_type, width, height);
}
@@ -677,7 +673,7 @@ static float *mask_rasterize(Mask *mask, const int width, const int height)
void ED_mask_draw_region(
Depsgraph *depsgraph,
Mask *mask_,
- ARegion *ar,
+ ARegion *region,
const char draw_flag,
const char draw_type,
const char overlay_mode,
@@ -693,7 +689,7 @@ void ED_mask_draw_region(
/* optional - only used when do_post_draw is set or called from clip editor */
const bContext *C)
{
- struct View2D *v2d = &ar->v2d;
+ struct View2D *v2d = &region->v2d;
Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_->id);
/* aspect always scales vertically in movie and image spaces */
@@ -708,13 +704,13 @@ void ED_mask_draw_region(
float xofs, yofs;
/* find window pixel coordinates of origin */
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &x, &y);
/* w = BLI_rctf_size_x(&v2d->tot); */
/* h = BLI_rctf_size_y(&v2d->tot); */
- zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / BLI_rctf_size_x(&ar->v2d.cur);
- zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / BLI_rctf_size_y(&ar->v2d.cur);
+ zoomx = (float)(BLI_rcti_size_x(&region->winrct) + 1) / BLI_rctf_size_x(&region->v2d.cur);
+ zoomy = (float)(BLI_rcti_size_y(&region->winrct) + 1) / BLI_rctf_size_y(&region->v2d.cur);
if (do_scale_applied) {
zoomx /= width;
@@ -780,35 +776,36 @@ void ED_mask_draw_region(
GPU_matrix_scale_2f(maxdim, maxdim);
if (do_draw_cb) {
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
}
/* draw! */
draw_mask_layers(C, mask_eval, draw_flag, draw_type, width, height);
if (do_draw_cb) {
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
}
GPU_matrix_pop();
}
-void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra, const int efra)
+void ED_mask_draw_frames(
+ Mask *mask, ARegion *region, const int cfra, const int sfra, const int efra)
{
- const float framelen = ar->winx / (float)(efra - sfra + 1);
+ const float framelen = region->winx / (float)(efra - sfra + 1);
MaskLayer *mask_layer = BKE_mask_layer_active(mask);
if (mask_layer == NULL) {
return;
}
- unsigned int num_lines = BLI_listbase_count(&mask_layer->splines_shapes);
+ uint num_lines = BLI_listbase_count(&mask_layer->splines_shapes);
if (num_lines == 0) {
return;
}
/* Local coordinate visible rect inside region, to accommodate overlapping ui. */
- const rcti *rect_visible = ED_region_visible_rect(ar);
+ const rcti *rect_visible = ED_region_visible_rect(region);
const int region_bottom = rect_visible->ymin;
uint pos = GPU_vertformat_attr_add(
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index 56d8ef56160..663ae0097ad 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -21,39 +21,32 @@
* \ingroup edmask
*/
-#include "BLI_math.h"
-
#include "BKE_context.h"
#include "BKE_mask.h"
-#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_screen.h"
-#include "ED_select_utils.h"
-#include "ED_mask.h" /* own include */
-#include "ED_image.h"
-#include "ED_object.h" /* ED_keymap_proportional_maskmode only */
#include "ED_clip.h"
+#include "ED_image.h"
+#include "ED_mask.h" /* own include */
#include "ED_sequencer.h"
-#include "ED_transform.h"
-
-#include "UI_view2d.h"
#include "RNA_access.h"
#include "mask_intern.h" /* own include */
-/********************** generic poll functions *********************/
+/* -------------------------------------------------------------------- */
+/** \name Poll Functions
+ * \{ */
bool ED_maskedit_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if (sa) {
- switch (sa->spacetype) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area) {
+ switch (area->spacetype) {
case SPACE_CLIP:
return ED_space_clip_maskedit_poll(C);
case SPACE_SEQ:
@@ -67,9 +60,9 @@ bool ED_maskedit_poll(bContext *C)
bool ED_maskedit_mask_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if (sa) {
- switch (sa->spacetype) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area) {
+ switch (area->spacetype) {
case SPACE_CLIP:
return ED_space_clip_maskedit_mask_poll(C);
case SPACE_SEQ:
@@ -81,343 +74,11 @@ bool ED_maskedit_mask_poll(bContext *C)
return false;
}
-/********************** registration *********************/
-
-/* takes event->mval */
-void ED_mask_mouse_pos(ScrArea *sa, ARegion *ar, const int mval[2], float co[2])
-{
- if (sa) {
- switch (sa->spacetype) {
- case SPACE_CLIP: {
- SpaceClip *sc = sa->spacedata.first;
- ED_clip_mouse_pos(sc, ar, mval, co);
- BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co);
- break;
- }
- case SPACE_SEQ: {
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &co[0], &co[1]);
- break;
- }
- case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
- ED_image_mouse_pos(sima, ar, mval, co);
- BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co);
- break;
- }
- default:
- /* possible other spaces from which mask editing is available */
- BLI_assert(0);
- zero_v2(co);
- break;
- }
- }
- else {
- BLI_assert(0);
- zero_v2(co);
- }
-}
-
-/* input: x/y - mval space
- * output: xr/yr - mask point space */
-void ED_mask_point_pos(ScrArea *sa, ARegion *ar, float x, float y, float *xr, float *yr)
-{
- float co[2];
-
- if (sa) {
- switch (sa->spacetype) {
- case SPACE_CLIP: {
- SpaceClip *sc = sa->spacedata.first;
- ED_clip_point_stable_pos(sc, ar, x, y, &co[0], &co[1]);
- BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co);
- break;
- }
- case SPACE_SEQ:
- zero_v2(co); /* MASKTODO */
- break;
- case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
- ED_image_point_pos(sima, ar, x, y, &co[0], &co[1]);
- BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co);
- break;
- }
- default:
- /* possible other spaces from which mask editing is available */
- BLI_assert(0);
- zero_v2(co);
- break;
- }
- }
- else {
- BLI_assert(0);
- zero_v2(co);
- }
-
- *xr = co[0];
- *yr = co[1];
-}
-
-void ED_mask_point_pos__reverse(ScrArea *sa, ARegion *ar, float x, float y, float *xr, float *yr)
-{
- float co[2];
-
- if (sa) {
- switch (sa->spacetype) {
- case SPACE_CLIP: {
- SpaceClip *sc = sa->spacedata.first;
- co[0] = x;
- co[1] = y;
- BKE_mask_coord_to_movieclip(sc->clip, &sc->user, co, co);
- ED_clip_point_stable_pos__reverse(sc, ar, co, co);
- break;
- }
- case SPACE_SEQ:
- zero_v2(co); /* MASKTODO */
- break;
- case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
- co[0] = x;
- co[1] = y;
- BKE_mask_coord_to_image(sima->image, &sima->iuser, co, co);
- ED_image_point_pos__reverse(sima, ar, co, co);
- break;
- }
- default:
- /* possible other spaces from which mask editing is available */
- BLI_assert(0);
- zero_v2(co);
- break;
- }
- }
- else {
- BLI_assert(0);
- zero_v2(co);
- }
-
- *xr = co[0];
- *yr = co[1];
-}
-
-void ED_mask_get_size(ScrArea *sa, int *width, int *height)
-{
- if (sa && sa->spacedata.first) {
- switch (sa->spacetype) {
- case SPACE_CLIP: {
- SpaceClip *sc = sa->spacedata.first;
- ED_space_clip_get_size(sc, width, height);
- break;
- }
- case SPACE_SEQ: {
- // Scene *scene = CTX_data_scene(C);
- // *width = (scene->r.size * scene->r.xsch) / 100;
- // *height = (scene->r.size * scene->r.ysch) / 100;
- break;
- }
- case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
- ED_space_image_get_size(sima, width, height);
- break;
- }
- default:
- /* possible other spaces from which mask editing is available */
- BLI_assert(0);
- *width = 0;
- *height = 0;
- break;
- }
- }
- else {
- BLI_assert(0);
- *width = 0;
- *height = 0;
- }
-}
-
-void ED_mask_zoom(ScrArea *sa, ARegion *ar, float *zoomx, float *zoomy)
-{
- if (sa && sa->spacedata.first) {
- switch (sa->spacetype) {
- case SPACE_CLIP: {
- SpaceClip *sc = sa->spacedata.first;
- ED_space_clip_get_zoom(sc, ar, zoomx, zoomy);
- break;
- }
- case SPACE_SEQ: {
- *zoomx = *zoomy = 1.0f;
- break;
- }
- case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
- ED_space_image_get_zoom(sima, ar, zoomx, zoomy);
- break;
- }
- default:
- /* possible other spaces from which mask editing is available */
- BLI_assert(0);
- *zoomx = *zoomy = 1.0f;
- break;
- }
- }
- else {
- BLI_assert(0);
- *zoomx = *zoomy = 1.0f;
- }
-}
+/** \} */
-void ED_mask_get_aspect(ScrArea *sa, ARegion *UNUSED(ar), float *aspx, float *aspy)
-{
- if (sa && sa->spacedata.first) {
- switch (sa->spacetype) {
- case SPACE_CLIP: {
- SpaceClip *sc = sa->spacedata.first;
- ED_space_clip_get_aspect(sc, aspx, aspy);
- break;
- }
- case SPACE_SEQ: {
- *aspx = *aspy = 1.0f; /* MASKTODO - render aspect? */
- break;
- }
- case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
- ED_space_image_get_aspect(sima, aspx, aspy);
- break;
- }
- default:
- /* possible other spaces from which mask editing is available */
- BLI_assert(0);
- *aspx = *aspy = 1.0f;
- break;
- }
- }
- else {
- BLI_assert(0);
- *aspx = *aspy = 1.0f;
- }
-}
-
-void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *ar, float *scalex, float *scaley)
-{
- if (sa && sa->spacedata.first) {
- switch (sa->spacetype) {
- case SPACE_CLIP: {
- SpaceClip *sc = sa->spacedata.first;
- float aspx, aspy;
-
- UI_view2d_scale_get(&ar->v2d, scalex, scaley);
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
-
- *scalex *= aspx;
- *scaley *= aspy;
- break;
- }
- case SPACE_SEQ: {
- *scalex = *scaley = 1.0f; /* MASKTODO? */
- break;
- }
- case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
- float aspx, aspy;
-
- UI_view2d_scale_get(&ar->v2d, scalex, scaley);
- ED_space_image_get_aspect(sima, &aspx, &aspy);
-
- *scalex *= aspx;
- *scaley *= aspy;
- break;
- }
- default:
- /* possible other spaces from which mask editing is available */
- BLI_assert(0);
- *scalex = *scaley = 1.0f;
- break;
- }
- }
- else {
- BLI_assert(0);
- *scalex = *scaley = 1.0f;
- }
-}
-
-void ED_mask_cursor_location_get(ScrArea *sa, float cursor[2])
-{
- if (sa) {
- switch (sa->spacetype) {
- case SPACE_CLIP: {
- SpaceClip *space_clip = sa->spacedata.first;
- copy_v2_v2(cursor, space_clip->cursor);
- break;
- }
- case SPACE_SEQ: {
- zero_v2(cursor);
- break;
- }
- case SPACE_IMAGE: {
- SpaceImage *space_image = sa->spacedata.first;
- copy_v2_v2(cursor, space_image->cursor);
- break;
- }
- default:
- /* possible other spaces from which mask editing is available */
- BLI_assert(0);
- zero_v2(cursor);
- break;
- }
- }
- else {
- BLI_assert(0);
- zero_v2(cursor);
- }
-}
-
-bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2])
-{
- Mask *mask = CTX_data_edit_mask(C);
- bool ok = false;
-
- if (mask == NULL) {
- return ok;
- }
-
- INIT_MINMAX2(min, max);
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL;
- mask_layer = mask_layer->next) {
- if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
- for (MaskSpline *spline = mask_layer->splines.first; spline != NULL; spline = spline->next) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
- for (int i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
- MaskSplinePoint *deform_point = &points_array[i];
- BezTriple *bezt = &point->bezt;
- float handle[2];
- if (!MASKPOINT_ISSEL_ANY(point)) {
- continue;
- }
- if (bezt->f2 & SELECT) {
- minmax_v2v2_v2(min, max, deform_point->bezt.vec[1]);
- }
- if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
- BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_STICK, handle);
- minmax_v2v2_v2(min, max, handle);
- }
- else {
- if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) {
- BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_LEFT, handle);
- minmax_v2v2_v2(min, max, handle);
- }
- if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) {
- BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_RIGHT, handle);
- minmax_v2v2_v2(min, max, handle);
- }
- }
- ok = true;
- }
- }
- }
- return ok;
-}
-
-/********************** registration *********************/
+/* -------------------------------------------------------------------- */
+/** \name Registration
+ * \{ */
void ED_operatortypes_mask(void)
{
@@ -521,3 +182,5 @@ void ED_operatormacros_mask(void)
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
RNA_boolean_set(otmacro->ptr, "mirror", false);
}
+
+/** \} */
diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c
index 33f4bab14ec..31fc403b157 100644
--- a/source/blender/editors/mask/mask_editaction.c
+++ b/source/blender/editors/mask/mask_editaction.c
@@ -21,11 +21,11 @@
* \ingroup edmask
*/
+#include <math.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <stddef.h>
-#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -40,8 +40,8 @@
#include "ED_anim_api.h"
#include "ED_keyframes_edit.h"
-#include "ED_mask.h" /* own include */
#include "ED_markers.h"
+#include "ED_mask.h" /* own include */
/* ***************************************** */
/* NOTE ABOUT THIS FILE:
diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h
index 7cf92a9051a..6a45af4d2a6 100644
--- a/source/blender/editors/mask/mask_intern.h
+++ b/source/blender/editors/mask/mask_intern.h
@@ -31,20 +31,6 @@ struct wmOperatorType;
/* internal exports only */
/* mask_add.c */
-bool ED_mask_find_nearest_diff_point(const struct bContext *C,
- struct Mask *mask,
- const float normal_co[2],
- int threshold,
- bool feather,
- float tangent[2],
- const bool use_deform,
- const bool use_project,
- struct MaskLayer **mask_layer_r,
- struct MaskSpline **spline_r,
- struct MaskSplinePoint **point_r,
- float *u_r,
- float *score_r);
-
void MASK_OT_add_vertex(struct wmOperatorType *ot);
void MASK_OT_add_feather_vertex(struct wmOperatorType *ot);
void MASK_OT_primitive_circle_add(struct wmOperatorType *ot);
@@ -72,25 +58,6 @@ void MASK_OT_normals_make_consistent(struct wmOperatorType *ot);
void MASK_OT_handle_type_set(struct wmOperatorType *ot);
-bool ED_mask_feather_find_nearest(const struct bContext *C,
- struct Mask *mask,
- const float normal_co[2],
- const float threshold,
- struct MaskLayer **mask_layer_r,
- struct MaskSpline **spline_r,
- struct MaskSplinePoint **point_r,
- struct MaskSplinePointUW **uw_r,
- float *score);
-
-struct MaskSplinePoint *ED_mask_point_find_nearest(const struct bContext *C,
- struct Mask *mask,
- const float normal_co[2],
- const float threshold,
- struct MaskLayer **mask_layer_r,
- struct MaskSpline **spline_r,
- eMaskWhichHandle *which_handle_r,
- float *score);
-
void MASK_OT_layer_move(struct wmOperatorType *ot);
void MASK_OT_duplicate(struct wmOperatorType *ot);
@@ -113,9 +80,9 @@ void MASK_OT_select_linked(struct wmOperatorType *ot);
void MASK_OT_select_more(struct wmOperatorType *ot);
void MASK_OT_select_less(struct wmOperatorType *ot);
-bool ED_mask_spline_select_check(struct MaskSpline *spline);
-bool ED_mask_layer_select_check(struct MaskLayer *mask_layer);
-bool ED_mask_select_check(struct Mask *mask);
+bool ED_mask_spline_select_check(const struct MaskSpline *spline);
+bool ED_mask_layer_select_check(const struct MaskLayer *mask_layer);
+bool ED_mask_select_check(const struct Mask *mask);
void ED_mask_spline_select_set(struct MaskSpline *spline, const bool do_select);
void ED_mask_layer_select_set(struct MaskLayer *mask_layer, const bool do_select);
@@ -126,6 +93,38 @@ void ED_mask_select_flush_all(struct Mask *mask);
bool ED_maskedit_poll(struct bContext *C);
bool ED_maskedit_mask_poll(struct bContext *C);
+/* mask_query.c */
+bool ED_mask_find_nearest_diff_point(const struct bContext *C,
+ struct Mask *mask,
+ const float normal_co[2],
+ int threshold,
+ bool feather,
+ float tangent[2],
+ const bool use_deform,
+ const bool use_project,
+ struct MaskLayer **r_mask_layer,
+ struct MaskSpline **r_spline,
+ struct MaskSplinePoint **r_point,
+ float *r_u,
+ float *r_score);
+bool ED_mask_feather_find_nearest(const struct bContext *C,
+ struct Mask *mask,
+ const float normal_co[2],
+ const float threshold,
+ struct MaskLayer **r_mask_layer,
+ struct MaskSpline **r_spline,
+ struct MaskSplinePoint **r_point,
+ struct MaskSplinePointUW **r_uw,
+ float *r_score);
+struct MaskSplinePoint *ED_mask_point_find_nearest(const struct bContext *C,
+ struct Mask *mask,
+ const float normal_co[2],
+ const float threshold,
+ struct MaskLayer **r_mask_layer,
+ struct MaskSpline **r_spline,
+ eMaskWhichHandle *r_which_handle,
+ float *r_score);
+
/* mask_shapekey.c */
void MASK_OT_shape_key_insert(struct wmOperatorType *ot);
void MASK_OT_shape_key_clear(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 3a982b255f0..68dfe0d151f 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -31,11 +31,10 @@
#include "BKE_mask.h"
#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
-#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
#include "DNA_object_types.h" /* SELECT */
+#include "DNA_scene_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -52,312 +51,20 @@
#include "mask_intern.h" /* own include */
-/******************** utility functions *********************/
-
-static void mask_point_scaled_handle(/*const*/ MaskSplinePoint *point,
- /*const*/ eMaskWhichHandle which_handle,
- const float scalex,
- const float scaley,
- float handle[2])
-{
- BKE_mask_point_handle(point, which_handle, handle);
- handle[0] *= scalex;
- handle[1] *= scaley;
-}
-
-MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
- Mask *mask_orig,
- const float normal_co[2],
- const float threshold,
- MaskLayer **mask_layer_r,
- MaskSpline **spline_r,
- eMaskWhichHandle *which_handle_r,
- float *score)
-{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- MaskLayer *point_mask_layer = NULL;
- MaskSpline *point_spline = NULL;
- MaskSplinePoint *point = NULL;
- float co[2];
- const float threshold_sq = threshold * threshold;
- float len_sq = FLT_MAX, scalex, scaley;
- eMaskWhichHandle which_handle = MASK_WHICH_HANDLE_NONE;
- int width, height;
-
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
-
- ED_mask_get_size(sa, &width, &height);
- ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
-
- co[0] = normal_co[0] * scalex;
- co[1] = normal_co[1] * scaley;
-
- for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first,
- *mask_layer_eval = mask_eval->masklayers.first;
- mask_layer_orig != NULL;
- mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) {
-
- if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (MaskSpline *spline_orig = mask_layer_orig->splines.first,
- *spline_eval = mask_layer_eval->splines.first;
- spline_orig != NULL;
- spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval);
-
- for (int i = 0; i < spline_orig->tot_point; i++) {
- MaskSplinePoint *cur_point_orig = &spline_orig->points[i];
- MaskSplinePoint *cur_point_deform_eval = &points_array[i];
- eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE;
- BezTriple *bezt = &cur_point_deform_eval->bezt;
- float cur_len_sq, vec[2];
-
- vec[0] = bezt->vec[1][0] * scalex;
- vec[1] = bezt->vec[1][1] * scaley;
-
- cur_len_sq = len_squared_v2v2(co, vec);
-
- if (cur_len_sq < len_sq) {
- point_spline = spline_orig;
- point_mask_layer = mask_layer_orig;
- point = cur_point_orig;
- len_sq = cur_len_sq;
- which_handle = MASK_WHICH_HANDLE_NONE;
- }
-
- if (BKE_mask_point_handles_mode_get(cur_point_deform_eval) == MASK_HANDLE_MODE_STICK) {
- float handle[2];
- mask_point_scaled_handle(
- cur_point_deform_eval, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle);
- cur_len_sq = len_squared_v2v2(co, handle);
- cur_which_handle = MASK_WHICH_HANDLE_STICK;
- }
- else {
- float handle_left[2], handle_right[2];
- float len_left_sq, len_right_sq;
- mask_point_scaled_handle(
- cur_point_deform_eval, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left);
- mask_point_scaled_handle(
- cur_point_deform_eval, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right);
-
- len_left_sq = len_squared_v2v2(co, handle_left);
- len_right_sq = len_squared_v2v2(co, handle_right);
- if (i == 0) {
- if (len_left_sq <= len_right_sq) {
- if (bezt->h1 != HD_VECT) {
- cur_which_handle = MASK_WHICH_HANDLE_LEFT;
- cur_len_sq = len_left_sq;
- }
- }
- else if (bezt->h2 != HD_VECT) {
- cur_which_handle = MASK_WHICH_HANDLE_RIGHT;
- cur_len_sq = len_right_sq;
- }
- }
- else {
- if (len_right_sq <= len_left_sq) {
- if (bezt->h2 != HD_VECT) {
- cur_which_handle = MASK_WHICH_HANDLE_RIGHT;
- cur_len_sq = len_right_sq;
- }
- }
- else if (bezt->h1 != HD_VECT) {
- cur_which_handle = MASK_WHICH_HANDLE_LEFT;
- cur_len_sq = len_left_sq;
- }
- }
- }
-
- if (cur_len_sq <= len_sq && cur_which_handle != MASK_WHICH_HANDLE_NONE) {
- point_mask_layer = mask_layer_orig;
- point_spline = spline_orig;
- point = cur_point_orig;
- len_sq = cur_len_sq;
- which_handle = cur_which_handle;
- }
- }
- }
- }
-
- if (len_sq < threshold_sq) {
- if (mask_layer_r) {
- *mask_layer_r = point_mask_layer;
- }
-
- if (spline_r) {
- *spline_r = point_spline;
- }
-
- if (which_handle_r) {
- *which_handle_r = which_handle;
- }
-
- if (score) {
- *score = sqrtf(len_sq);
- }
-
- return point;
- }
-
- if (mask_layer_r) {
- *mask_layer_r = NULL;
- }
-
- if (spline_r) {
- *spline_r = NULL;
- }
-
- if (which_handle_r) {
- *which_handle_r = MASK_WHICH_HANDLE_NONE;
- }
-
- return NULL;
-}
-
-bool ED_mask_feather_find_nearest(const bContext *C,
- Mask *mask_orig,
- const float normal_co[2],
- const float threshold,
- MaskLayer **mask_layer_r,
- MaskSpline **spline_r,
- MaskSplinePoint **point_r,
- MaskSplinePointUW **uw_r,
- float *score)
-{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- MaskLayer *point_mask_layer = NULL;
- MaskSpline *point_spline = NULL;
- MaskSplinePoint *point = NULL;
- MaskSplinePointUW *uw = NULL;
- const float threshold_sq = threshold * threshold;
- float len = FLT_MAX, co[2];
- float scalex, scaley;
- int width, height;
-
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
-
- ED_mask_get_size(sa, &width, &height);
- ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
-
- co[0] = normal_co[0] * scalex;
- co[1] = normal_co[1] * scaley;
-
- for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first,
- *mask_layer_eval = mask_eval->masklayers.first;
- mask_layer_orig != NULL;
- mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) {
-
- for (MaskSpline *spline_orig = mask_layer_orig->splines.first,
- *spline_eval = mask_layer_eval->splines.first;
- spline_orig != NULL;
- spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
- // MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
-
- int i, tot_feather_point;
- float(*feather_points)[2], (*fp)[2];
-
- if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- feather_points = fp = BKE_mask_spline_feather_points(spline_eval, &tot_feather_point);
-
- for (i = 0; i < spline_orig->tot_point; i++) {
- int j;
- MaskSplinePoint *cur_point_orig = &spline_orig->points[i];
- MaskSplinePoint *cur_point_eval = &spline_eval->points[i];
-
- for (j = 0; j <= cur_point_eval->tot_uw; j++) {
- float cur_len_sq, vec[2];
-
- vec[0] = (*fp)[0] * scalex;
- vec[1] = (*fp)[1] * scaley;
-
- cur_len_sq = len_squared_v2v2(vec, co);
-
- if (point == NULL || cur_len_sq < len) {
- if (j == 0) {
- uw = NULL;
- }
- else {
- uw = &cur_point_orig->uw[j - 1];
- }
-
- point_mask_layer = mask_layer_orig;
- point_spline = spline_orig;
- point = cur_point_orig;
- len = cur_len_sq;
- }
-
- fp++;
- }
- }
-
- MEM_freeN(feather_points);
- }
- }
-
- if (len < threshold_sq) {
- if (mask_layer_r) {
- *mask_layer_r = point_mask_layer;
- }
-
- if (spline_r) {
- *spline_r = point_spline;
- }
-
- if (point_r) {
- *point_r = point;
- }
-
- if (uw_r) {
- *uw_r = uw;
- }
-
- if (score) {
- *score = sqrtf(len);
- }
-
- return true;
- }
-
- if (mask_layer_r) {
- *mask_layer_r = NULL;
- }
-
- if (spline_r) {
- *spline_r = NULL;
- }
-
- if (point_r) {
- *point_r = NULL;
- }
-
- return false;
-}
-
/******************** create new mask *********************/
Mask *ED_mask_new(bContext *C, const char *name)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Main *bmain = CTX_data_main(C);
Mask *mask;
mask = BKE_mask_new(bmain, name);
- if (sa && sa->spacedata.first) {
- switch (sa->spacetype) {
+ if (area && area->spacedata.first) {
+ switch (area->spacetype) {
case SPACE_CLIP: {
- SpaceClip *sc = sa->spacedata.first;
+ SpaceClip *sc = area->spacedata.first;
ED_space_clip_set_mask(C, sc, mask);
break;
}
@@ -366,7 +73,7 @@ Mask *ED_mask_new(bContext *C, const char *name)
break;
}
case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
ED_space_image_set_mask(C, sima, mask);
break;
}
@@ -549,11 +256,11 @@ static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float c
static bool spline_under_mouse_get(const bContext *C,
Mask *mask,
const float co[2],
- MaskLayer **mask_layer_r,
- MaskSpline **mask_spline_r)
+ MaskLayer **r_mask_layer,
+ MaskSpline **r_mask_spline)
{
const float threshold = 19.0f;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceClip *sc = CTX_wm_space_clip(C);
int width, height;
float pixel_co[2];
@@ -561,9 +268,9 @@ static bool spline_under_mouse_get(const bContext *C,
MaskLayer *closest_layer = NULL;
MaskSpline *closest_spline = NULL;
bool undistort = false;
- *mask_layer_r = NULL;
- *mask_spline_r = NULL;
- ED_mask_get_size(sa, &width, &height);
+ *r_mask_layer = NULL;
+ *r_mask_spline = NULL;
+ ED_mask_get_size(area, &width, &height);
pixel_co[0] = co[0] * width;
pixel_co[1] = co[1] * height;
if (sc != NULL) {
@@ -614,7 +321,7 @@ static bool spline_under_mouse_get(const bContext *C,
}
}
}
- if (closest_dist_squared < SQUARE(threshold) && closest_spline != NULL) {
+ if (closest_dist_squared < square_f(threshold) && closest_spline != NULL) {
float diff_score;
if (ED_mask_find_nearest_diff_point(C,
mask,
@@ -629,13 +336,13 @@ static bool spline_under_mouse_get(const bContext *C,
NULL,
NULL,
&diff_score)) {
- if (SQUARE(diff_score) < closest_dist_squared) {
+ if (square_f(diff_score) < closest_dist_squared) {
return false;
}
}
- *mask_layer_r = closest_layer;
- *mask_spline_r = closest_spline;
+ *r_mask_layer = closest_layer;
+ *r_mask_spline = closest_spline;
return true;
}
return false;
@@ -713,8 +420,8 @@ static void check_sliding_handle_type(MaskSplinePoint *point, eMaskWhichHandle w
static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
Mask *mask = CTX_data_edit_mask(C);
SlidePointData *customdata = NULL;
@@ -728,8 +435,8 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
const float threshold = 19;
eMaskWhichHandle which_handle;
- ED_mask_mouse_pos(sa, ar, event->mval, co);
- ED_mask_get_size(sa, &width, &height);
+ ED_mask_mouse_pos(area, region, event->mval, co);
+ ED_mask_get_size(area, &width, &height);
cv_point = ED_mask_point_find_nearest(
C, mask, co, threshold, &cv_mask_layer, &cv_spline, &which_handle, &cv_score);
@@ -827,7 +534,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
}
customdata->which_handle = which_handle;
- ED_mask_mouse_pos(sa, ar, event->mval, customdata->prev_mouse_coord);
+ ED_mask_mouse_pos(area, region, event->mval, customdata->prev_mouse_coord);
}
return customdata;
@@ -932,11 +639,11 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
float co[2];
switch (event->type) {
- case LEFTALTKEY:
- case RIGHTALTKEY:
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- if (ELEM(event->type, LEFTALTKEY, RIGHTALTKEY)) {
+ case EVT_LEFTALTKEY:
+ case EVT_RIGHTALTKEY:
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
+ if (ELEM(event->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY)) {
if (data->action == SLIDE_ACTION_FEATHER) {
data->is_overall_feather = (event->val == KM_PRESS);
}
@@ -945,17 +652,17 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
- if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
+ if (ELEM(event->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY)) {
data->is_accurate = (event->val == KM_PRESS);
}
ATTR_FALLTHROUGH; /* update CV position */
case MOUSEMOVE: {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
float delta[2];
- ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_mouse_pos(area, region, event->mval, co);
sub_v2_v2v2(delta, co, data->prev_mouse_coord);
if (data->is_accurate) {
mul_v2_fl(delta, 0.2f);
@@ -1165,7 +872,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
- case ESCKEY:
+ case EVT_ESCKEY:
cancel_slide_point(op->customdata);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
@@ -1419,15 +1126,15 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve
float u = slide_data->u;
switch (event->type) {
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY:
- if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
+ case EVT_LEFTCTRLKEY:
+ case EVT_RIGHTCTRLKEY:
+ if (ELEM(event->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY)) {
slide_data->accurate = (event->val == KM_PRESS);
}
- if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) {
+ if (ELEM(event->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY)) {
if (event->val == KM_PRESS) {
slide_data->adjust_bezt->h1 = slide_data->adjust_bezt->h2 = HD_FREE;
if ((u > margin && u < 0.5f) || (u >= 0.5f && u < 1.0f - margin)) {
@@ -1551,7 +1258,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve
break;
- case ESCKEY:
+ case EVT_ESCKEY:
cancel_slide_spline_curvature(slide_data);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
@@ -1586,12 +1293,12 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
Mask *mask = CTX_data_edit_mask(C);
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
if (ED_mask_spline_select_check(spline)) {
spline->flag ^= MASK_SPLINE_CYCLIC;
}
@@ -1664,7 +1371,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op))
Mask *mask = CTX_data_edit_mask(C);
bool changed = false;
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
MaskSpline *spline;
int mask_layer_shape_ofs = 0;
@@ -1786,14 +1493,14 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
bool changed = false;
/* do actual selection */
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
bool changed_layer = false;
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
if (ED_mask_spline_select_check(spline)) {
BKE_mask_spline_direction_switch(mask_layer, spline);
changed = true;
@@ -1844,14 +1551,14 @@ static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op)
bool changed = false;
/* do actual selection */
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
bool changed_layer = false;
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
for (int i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
@@ -1907,12 +1614,12 @@ static int set_handle_type_exec(bContext *C, wmOperator *op)
bool changed = false;
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
for (int i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
@@ -1988,7 +1695,7 @@ static int mask_hide_view_clear_exec(bContext *C, wmOperator *op)
bool changed = false;
const bool select = RNA_boolean_get(op->ptr, "select");
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & OB_RESTRICT_VIEWPORT) {
ED_mask_layer_select_set(mask_layer, select);
@@ -2032,7 +1739,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
const bool unselected = RNA_boolean_get(op->ptr, "unselected");
bool changed = false;
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) {
continue;
@@ -2094,12 +1801,12 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
Mask *mask = CTX_data_edit_mask(C);
bool changed = false;
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
for (int i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
@@ -2228,7 +1935,7 @@ static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
Mask *mask = CTX_data_edit_mask(C);
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
for (MaskSpline *spline = mask_layer->splines.last; spline; spline = spline->prev) {
MaskSplinePoint *point = spline->points;
int i = 0;
diff --git a/source/blender/editors/mask/mask_query.c b/source/blender/editors/mask/mask_query.c
new file mode 100644
index 00000000000..cf5997d8a18
--- /dev/null
+++ b/source/blender/editors/mask/mask_query.c
@@ -0,0 +1,833 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edmask
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_mask.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "DNA_mask_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "ED_clip.h"
+#include "ED_image.h"
+#include "ED_mask.h" /* own include */
+
+#include "UI_view2d.h"
+
+#include "mask_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name Spatial Queries
+ * \{ */
+
+bool ED_mask_find_nearest_diff_point(const bContext *C,
+ struct Mask *mask_orig,
+ const float normal_co[2],
+ int threshold,
+ bool feather,
+ float tangent[2],
+ const bool use_deform,
+ const bool use_project,
+ MaskLayer **r_mask_layer,
+ MaskSpline **r_spline,
+ MaskSplinePoint **r_point,
+ float *r_u,
+ float *r_score)
+{
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+
+ MaskLayer *point_mask_layer;
+ MaskSpline *point_spline;
+ MaskSplinePoint *point = NULL;
+ float dist_best_sq = FLT_MAX, co[2];
+ int width, height;
+ float u = 0.0f;
+ float scalex, scaley;
+
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
+
+ ED_mask_get_size(area, &width, &height);
+ ED_mask_pixelspace_factor(area, region, &scalex, &scaley);
+
+ co[0] = normal_co[0] * scalex;
+ co[1] = normal_co[1] * scaley;
+
+ for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first,
+ *mask_layer_eval = mask_eval->masklayers.first;
+ mask_layer_orig != NULL;
+ mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) {
+ if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (MaskSpline *spline_orig = mask_layer_orig->splines.first,
+ *spline_eval = mask_layer_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
+ int i;
+ MaskSplinePoint *cur_point_eval;
+
+ for (i = 0, cur_point_eval = use_deform ? spline_eval->points_deform : spline_eval->points;
+ i < spline_eval->tot_point;
+ i++, cur_point_eval++) {
+ uint tot_diff_point;
+ float *diff_points = BKE_mask_point_segment_diff(
+ spline_eval, cur_point_eval, width, height, &tot_diff_point);
+
+ if (diff_points) {
+ int j, tot_point;
+ uint tot_feather_point;
+ float *feather_points = NULL, *points;
+
+ if (feather) {
+ feather_points = BKE_mask_point_segment_feather_diff(
+ spline_eval, cur_point_eval, width, height, &tot_feather_point);
+
+ points = feather_points;
+ tot_point = tot_feather_point;
+ }
+ else {
+ points = diff_points;
+ tot_point = tot_diff_point;
+ }
+
+ for (j = 0; j < tot_point - 1; j++) {
+ float dist_sq, a[2], b[2];
+
+ a[0] = points[2 * j] * scalex;
+ a[1] = points[2 * j + 1] * scaley;
+
+ b[0] = points[2 * j + 2] * scalex;
+ b[1] = points[2 * j + 3] * scaley;
+
+ dist_sq = dist_squared_to_line_segment_v2(co, a, b);
+
+ if (dist_sq < dist_best_sq) {
+ if (tangent) {
+ sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]);
+ }
+
+ point_mask_layer = mask_layer_orig;
+ point_spline = spline_orig;
+ point = use_deform ?
+ &spline_orig->points[(cur_point_eval - spline_eval->points_deform)] :
+ &spline_orig->points[(cur_point_eval - spline_eval->points)];
+ dist_best_sq = dist_sq;
+ u = (float)j / tot_point;
+ }
+ }
+
+ if (feather_points != NULL) {
+ MEM_freeN(feather_points);
+ }
+ MEM_freeN(diff_points);
+ }
+ }
+ }
+ }
+
+ if (point && dist_best_sq < threshold) {
+ if (r_mask_layer) {
+ *r_mask_layer = point_mask_layer;
+ }
+
+ if (r_spline) {
+ *r_spline = point_spline;
+ }
+
+ if (r_point) {
+ *r_point = point;
+ }
+
+ if (r_u) {
+ /* TODO(sergey): Projection fails in some weirdo cases.. */
+ if (use_project) {
+ u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY);
+ }
+
+ *r_u = u;
+ }
+
+ if (r_score) {
+ *r_score = dist_best_sq;
+ }
+
+ return true;
+ }
+
+ if (r_mask_layer) {
+ *r_mask_layer = NULL;
+ }
+
+ if (r_spline) {
+ *r_spline = NULL;
+ }
+
+ if (r_point) {
+ *r_point = NULL;
+ }
+
+ return false;
+}
+
+static void mask_point_scaled_handle(const MaskSplinePoint *point,
+ const eMaskWhichHandle which_handle,
+ const float scalex,
+ const float scaley,
+ float handle[2])
+{
+ BKE_mask_point_handle(point, which_handle, handle);
+ handle[0] *= scalex;
+ handle[1] *= scaley;
+}
+
+MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
+ Mask *mask_orig,
+ const float normal_co[2],
+ const float threshold,
+ MaskLayer **r_mask_layer,
+ MaskSpline **r_spline,
+ eMaskWhichHandle *r_which_handle,
+ float *r_score)
+{
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+
+ MaskLayer *point_mask_layer = NULL;
+ MaskSpline *point_spline = NULL;
+ MaskSplinePoint *point = NULL;
+ float co[2];
+ const float threshold_sq = threshold * threshold;
+ float len_sq = FLT_MAX, scalex, scaley;
+ eMaskWhichHandle which_handle = MASK_WHICH_HANDLE_NONE;
+ int width, height;
+
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
+
+ ED_mask_get_size(area, &width, &height);
+ ED_mask_pixelspace_factor(area, region, &scalex, &scaley);
+
+ co[0] = normal_co[0] * scalex;
+ co[1] = normal_co[1] * scaley;
+
+ for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first,
+ *mask_layer_eval = mask_eval->masklayers.first;
+ mask_layer_orig != NULL;
+ mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) {
+
+ if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (MaskSpline *spline_orig = mask_layer_orig->splines.first,
+ *spline_eval = mask_layer_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval);
+
+ for (int i = 0; i < spline_orig->tot_point; i++) {
+ MaskSplinePoint *cur_point_orig = &spline_orig->points[i];
+ const MaskSplinePoint *cur_point_deform_eval = &points_array[i];
+ eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE;
+ const BezTriple *bezt = &cur_point_deform_eval->bezt;
+ float cur_len_sq, vec[2];
+
+ vec[0] = bezt->vec[1][0] * scalex;
+ vec[1] = bezt->vec[1][1] * scaley;
+
+ cur_len_sq = len_squared_v2v2(co, vec);
+
+ if (cur_len_sq < len_sq) {
+ point_spline = spline_orig;
+ point_mask_layer = mask_layer_orig;
+ point = cur_point_orig;
+ len_sq = cur_len_sq;
+ which_handle = MASK_WHICH_HANDLE_NONE;
+ }
+
+ if (BKE_mask_point_handles_mode_get(cur_point_deform_eval) == MASK_HANDLE_MODE_STICK) {
+ float handle[2];
+ mask_point_scaled_handle(
+ cur_point_deform_eval, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle);
+ cur_len_sq = len_squared_v2v2(co, handle);
+ cur_which_handle = MASK_WHICH_HANDLE_STICK;
+ }
+ else {
+ float handle_left[2], handle_right[2];
+ float len_left_sq, len_right_sq;
+ mask_point_scaled_handle(
+ cur_point_deform_eval, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left);
+ mask_point_scaled_handle(
+ cur_point_deform_eval, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right);
+
+ len_left_sq = len_squared_v2v2(co, handle_left);
+ len_right_sq = len_squared_v2v2(co, handle_right);
+ if (i == 0) {
+ if (len_left_sq <= len_right_sq) {
+ if (bezt->h1 != HD_VECT) {
+ cur_which_handle = MASK_WHICH_HANDLE_LEFT;
+ cur_len_sq = len_left_sq;
+ }
+ }
+ else if (bezt->h2 != HD_VECT) {
+ cur_which_handle = MASK_WHICH_HANDLE_RIGHT;
+ cur_len_sq = len_right_sq;
+ }
+ }
+ else {
+ if (len_right_sq <= len_left_sq) {
+ if (bezt->h2 != HD_VECT) {
+ cur_which_handle = MASK_WHICH_HANDLE_RIGHT;
+ cur_len_sq = len_right_sq;
+ }
+ }
+ else if (bezt->h1 != HD_VECT) {
+ cur_which_handle = MASK_WHICH_HANDLE_LEFT;
+ cur_len_sq = len_left_sq;
+ }
+ }
+ }
+
+ if (cur_len_sq <= len_sq && cur_which_handle != MASK_WHICH_HANDLE_NONE) {
+ point_mask_layer = mask_layer_orig;
+ point_spline = spline_orig;
+ point = cur_point_orig;
+ len_sq = cur_len_sq;
+ which_handle = cur_which_handle;
+ }
+ }
+ }
+ }
+
+ if (len_sq < threshold_sq) {
+ if (r_mask_layer) {
+ *r_mask_layer = point_mask_layer;
+ }
+
+ if (r_spline) {
+ *r_spline = point_spline;
+ }
+
+ if (r_which_handle) {
+ *r_which_handle = which_handle;
+ }
+
+ if (r_score) {
+ *r_score = sqrtf(len_sq);
+ }
+
+ return point;
+ }
+
+ if (r_mask_layer) {
+ *r_mask_layer = NULL;
+ }
+
+ if (r_spline) {
+ *r_spline = NULL;
+ }
+
+ if (r_which_handle) {
+ *r_which_handle = MASK_WHICH_HANDLE_NONE;
+ }
+
+ return NULL;
+}
+
+bool ED_mask_feather_find_nearest(const bContext *C,
+ Mask *mask_orig,
+ const float normal_co[2],
+ const float threshold,
+ MaskLayer **r_mask_layer,
+ MaskSpline **r_spline,
+ MaskSplinePoint **r_point,
+ MaskSplinePointUW **r_uw,
+ float *r_score)
+{
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+
+ MaskLayer *point_mask_layer = NULL;
+ MaskSpline *point_spline = NULL;
+ MaskSplinePoint *point = NULL;
+ MaskSplinePointUW *uw = NULL;
+ const float threshold_sq = threshold * threshold;
+ float len = FLT_MAX, co[2];
+ float scalex, scaley;
+ int width, height;
+
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
+
+ ED_mask_get_size(area, &width, &height);
+ ED_mask_pixelspace_factor(area, region, &scalex, &scaley);
+
+ co[0] = normal_co[0] * scalex;
+ co[1] = normal_co[1] * scaley;
+
+ for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first,
+ *mask_layer_eval = mask_eval->masklayers.first;
+ mask_layer_orig != NULL;
+ mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) {
+
+ for (MaskSpline *spline_orig = mask_layer_orig->splines.first,
+ *spline_eval = mask_layer_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
+ // MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+
+ int i, tot_feather_point;
+ float(*feather_points)[2], (*fp)[2];
+
+ if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ feather_points = fp = BKE_mask_spline_feather_points(spline_eval, &tot_feather_point);
+
+ for (i = 0; i < spline_orig->tot_point; i++) {
+ int j;
+ MaskSplinePoint *cur_point_orig = &spline_orig->points[i];
+ MaskSplinePoint *cur_point_eval = &spline_eval->points[i];
+
+ for (j = 0; j <= cur_point_eval->tot_uw; j++) {
+ float cur_len_sq, vec[2];
+
+ vec[0] = (*fp)[0] * scalex;
+ vec[1] = (*fp)[1] * scaley;
+
+ cur_len_sq = len_squared_v2v2(vec, co);
+
+ if (point == NULL || cur_len_sq < len) {
+ if (j == 0) {
+ uw = NULL;
+ }
+ else {
+ uw = &cur_point_orig->uw[j - 1];
+ }
+
+ point_mask_layer = mask_layer_orig;
+ point_spline = spline_orig;
+ point = cur_point_orig;
+ len = cur_len_sq;
+ }
+
+ fp++;
+ }
+ }
+
+ MEM_freeN(feather_points);
+ }
+ }
+
+ if (len < threshold_sq) {
+ if (r_mask_layer) {
+ *r_mask_layer = point_mask_layer;
+ }
+
+ if (r_spline) {
+ *r_spline = point_spline;
+ }
+
+ if (r_point) {
+ *r_point = point;
+ }
+
+ if (r_uw) {
+ *r_uw = uw;
+ }
+
+ if (r_score) {
+ *r_score = sqrtf(len);
+ }
+
+ return true;
+ }
+
+ if (r_mask_layer) {
+ *r_mask_layer = NULL;
+ }
+
+ if (r_spline) {
+ *r_spline = NULL;
+ }
+
+ if (r_point) {
+ *r_point = NULL;
+ }
+
+ return false;
+}
+
+/* takes event->mval */
+void ED_mask_mouse_pos(ScrArea *area, ARegion *region, const int mval[2], float co[2])
+{
+ if (area) {
+ switch (area->spacetype) {
+ case SPACE_CLIP: {
+ SpaceClip *sc = area->spacedata.first;
+ ED_clip_mouse_pos(sc, region, mval, co);
+ BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co);
+ break;
+ }
+ case SPACE_SEQ: {
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &co[0], &co[1]);
+ break;
+ }
+ case SPACE_IMAGE: {
+ SpaceImage *sima = area->spacedata.first;
+ ED_image_mouse_pos(sima, region, mval, co);
+ BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co);
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ zero_v2(co);
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ zero_v2(co);
+ }
+}
+
+/* input: x/y - mval space
+ * output: xr/yr - mask point space */
+void ED_mask_point_pos(ScrArea *area, ARegion *region, float x, float y, float *xr, float *yr)
+{
+ float co[2];
+
+ if (area) {
+ switch (area->spacetype) {
+ case SPACE_CLIP: {
+ SpaceClip *sc = area->spacedata.first;
+ ED_clip_point_stable_pos(sc, region, x, y, &co[0], &co[1]);
+ BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co);
+ break;
+ }
+ case SPACE_SEQ:
+ zero_v2(co); /* MASKTODO */
+ break;
+ case SPACE_IMAGE: {
+ SpaceImage *sima = area->spacedata.first;
+ ED_image_point_pos(sima, region, x, y, &co[0], &co[1]);
+ BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co);
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ zero_v2(co);
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ zero_v2(co);
+ }
+
+ *xr = co[0];
+ *yr = co[1];
+}
+
+void ED_mask_point_pos__reverse(
+ ScrArea *area, ARegion *region, float x, float y, float *xr, float *yr)
+{
+ float co[2];
+
+ if (area) {
+ switch (area->spacetype) {
+ case SPACE_CLIP: {
+ SpaceClip *sc = area->spacedata.first;
+ co[0] = x;
+ co[1] = y;
+ BKE_mask_coord_to_movieclip(sc->clip, &sc->user, co, co);
+ ED_clip_point_stable_pos__reverse(sc, region, co, co);
+ break;
+ }
+ case SPACE_SEQ:
+ zero_v2(co); /* MASKTODO */
+ break;
+ case SPACE_IMAGE: {
+ SpaceImage *sima = area->spacedata.first;
+ co[0] = x;
+ co[1] = y;
+ BKE_mask_coord_to_image(sima->image, &sima->iuser, co, co);
+ ED_image_point_pos__reverse(sima, region, co, co);
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ zero_v2(co);
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ zero_v2(co);
+ }
+
+ *xr = co[0];
+ *yr = co[1];
+}
+
+bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2])
+{
+ Mask *mask = CTX_data_edit_mask(C);
+ bool ok = false;
+
+ if (mask == NULL) {
+ return ok;
+ }
+
+ INIT_MINMAX2(min, max);
+ for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL;
+ mask_layer = mask_layer->next) {
+ if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+ for (MaskSpline *spline = mask_layer->splines.first; spline != NULL; spline = spline->next) {
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
+ for (int i = 0; i < spline->tot_point; i++) {
+ const MaskSplinePoint *point = &spline->points[i];
+ const MaskSplinePoint *deform_point = &points_array[i];
+ const BezTriple *bezt = &point->bezt;
+ float handle[2];
+ if (!MASKPOINT_ISSEL_ANY(point)) {
+ continue;
+ }
+ if (bezt->f2 & SELECT) {
+ minmax_v2v2_v2(min, max, deform_point->bezt.vec[1]);
+ }
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_STICK, handle);
+ minmax_v2v2_v2(min, max, handle);
+ }
+ else {
+ if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) {
+ BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_LEFT, handle);
+ minmax_v2v2_v2(min, max, handle);
+ }
+ if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) {
+ BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_RIGHT, handle);
+ minmax_v2v2_v2(min, max, handle);
+ }
+ }
+ ok = true;
+ }
+ }
+ }
+ return ok;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic 2D View Queries
+ * \{ */
+
+void ED_mask_get_size(ScrArea *area, int *width, int *height)
+{
+ if (area && area->spacedata.first) {
+ switch (area->spacetype) {
+ case SPACE_CLIP: {
+ SpaceClip *sc = area->spacedata.first;
+ ED_space_clip_get_size(sc, width, height);
+ break;
+ }
+ case SPACE_SEQ: {
+ // Scene *scene = CTX_data_scene(C);
+ // *width = (scene->r.size * scene->r.xsch) / 100;
+ // *height = (scene->r.size * scene->r.ysch) / 100;
+ break;
+ }
+ case SPACE_IMAGE: {
+ SpaceImage *sima = area->spacedata.first;
+ ED_space_image_get_size(sima, width, height);
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ *width = 0;
+ *height = 0;
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ *width = 0;
+ *height = 0;
+ }
+}
+
+void ED_mask_zoom(ScrArea *area, ARegion *region, float *zoomx, float *zoomy)
+{
+ if (area && area->spacedata.first) {
+ switch (area->spacetype) {
+ case SPACE_CLIP: {
+ SpaceClip *sc = area->spacedata.first;
+ ED_space_clip_get_zoom(sc, region, zoomx, zoomy);
+ break;
+ }
+ case SPACE_SEQ: {
+ *zoomx = *zoomy = 1.0f;
+ break;
+ }
+ case SPACE_IMAGE: {
+ SpaceImage *sima = area->spacedata.first;
+ ED_space_image_get_zoom(sima, region, zoomx, zoomy);
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ *zoomx = *zoomy = 1.0f;
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ *zoomx = *zoomy = 1.0f;
+ }
+}
+
+void ED_mask_get_aspect(ScrArea *area, ARegion *UNUSED(region), float *aspx, float *aspy)
+{
+ if (area && area->spacedata.first) {
+ switch (area->spacetype) {
+ case SPACE_CLIP: {
+ SpaceClip *sc = area->spacedata.first;
+ ED_space_clip_get_aspect(sc, aspx, aspy);
+ break;
+ }
+ case SPACE_SEQ: {
+ *aspx = *aspy = 1.0f; /* MASKTODO - render aspect? */
+ break;
+ }
+ case SPACE_IMAGE: {
+ SpaceImage *sima = area->spacedata.first;
+ ED_space_image_get_aspect(sima, aspx, aspy);
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ *aspx = *aspy = 1.0f;
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ *aspx = *aspy = 1.0f;
+ }
+}
+
+void ED_mask_pixelspace_factor(ScrArea *area, ARegion *region, float *scalex, float *scaley)
+{
+ if (area && area->spacedata.first) {
+ switch (area->spacetype) {
+ case SPACE_CLIP: {
+ SpaceClip *sc = area->spacedata.first;
+ float aspx, aspy;
+
+ UI_view2d_scale_get(&region->v2d, scalex, scaley);
+ ED_space_clip_get_aspect(sc, &aspx, &aspy);
+
+ *scalex *= aspx;
+ *scaley *= aspy;
+ break;
+ }
+ case SPACE_SEQ: {
+ *scalex = *scaley = 1.0f; /* MASKTODO? */
+ break;
+ }
+ case SPACE_IMAGE: {
+ SpaceImage *sima = area->spacedata.first;
+ float aspx, aspy;
+
+ UI_view2d_scale_get(&region->v2d, scalex, scaley);
+ ED_space_image_get_aspect(sima, &aspx, &aspy);
+
+ *scalex *= aspx;
+ *scaley *= aspy;
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ *scalex = *scaley = 1.0f;
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ *scalex = *scaley = 1.0f;
+ }
+}
+
+void ED_mask_cursor_location_get(ScrArea *area, float cursor[2])
+{
+ if (area) {
+ switch (area->spacetype) {
+ case SPACE_CLIP: {
+ SpaceClip *space_clip = area->spacedata.first;
+ copy_v2_v2(cursor, space_clip->cursor);
+ break;
+ }
+ case SPACE_SEQ: {
+ zero_v2(cursor);
+ break;
+ }
+ case SPACE_IMAGE: {
+ SpaceImage *space_image = area->spacedata.first;
+ copy_v2_v2(cursor, space_image->cursor);
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ zero_v2(cursor);
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ zero_v2(cursor);
+ }
+}
+
+/** \} */
diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c
index 130ebb61a90..971e1c948c9 100644
--- a/source/blender/editors/mask/mask_relationships.c
+++ b/source/blender/editors/mask/mask_relationships.c
@@ -21,6 +21,7 @@
* \ingroup edmask
*/
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
@@ -35,8 +36,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_screen.h"
#include "ED_clip.h" /* frame remapping functions */
+#include "ED_screen.h"
#include "mask_intern.h" /* own include */
@@ -44,12 +45,12 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Mask *mask = CTX_data_edit_mask(C);
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
for (int i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
@@ -136,12 +137,12 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
for (int i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c
index 656c055a7d9..c8cddced99c 100644
--- a/source/blender/editors/mask/mask_select.c
+++ b/source/blender/editors/mask/mask_select.c
@@ -23,10 +23,11 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
-#include "BLI_rect.h"
#include "BLI_lasso_2d.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_rect.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_mask.h"
@@ -37,9 +38,8 @@
#include "WM_types.h"
#include "ED_clip.h"
-#include "ED_screen.h"
-#include "ED_select_utils.h"
#include "ED_mask.h" /* own include */
+#include "ED_select_utils.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -53,7 +53,7 @@
* \{ */
/* 'check' select */
-bool ED_mask_spline_select_check(MaskSpline *spline)
+bool ED_mask_spline_select_check(const MaskSpline *spline)
{
int i;
@@ -68,13 +68,13 @@ bool ED_mask_spline_select_check(MaskSpline *spline)
return false;
}
-bool ED_mask_layer_select_check(MaskLayer *mask_layer)
+bool ED_mask_layer_select_check(const MaskLayer *mask_layer)
{
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
return false;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (const MaskSpline *, spline, &mask_layer->splines) {
if (ED_mask_spline_select_check(spline)) {
return true;
}
@@ -83,9 +83,9 @@ bool ED_mask_layer_select_check(MaskLayer *mask_layer)
return false;
}
-bool ED_mask_select_check(Mask *mask)
+bool ED_mask_select_check(const Mask *mask)
{
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (const MaskLayer *, mask_layer, &mask->masklayers) {
if (ED_mask_layer_select_check(mask_layer)) {
return true;
}
@@ -121,7 +121,7 @@ void ED_mask_layer_select_set(MaskLayer *mask_layer, const bool do_select)
}
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
ED_mask_spline_select_set(spline, do_select);
}
}
@@ -137,7 +137,7 @@ void ED_mask_select_toggle_all(Mask *mask, int action)
}
}
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & MASK_RESTRICT_VIEW) {
continue;
@@ -150,7 +150,7 @@ void ED_mask_select_toggle_all(Mask *mask, int action)
if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
int i;
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
@@ -166,8 +166,8 @@ void ED_mask_select_toggle_all(Mask *mask, int action)
void ED_mask_select_flush_all(Mask *mask)
{
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
spline->flag &= ~SELECT;
/* intentionally _dont_ do this in the mask layer loop
@@ -385,12 +385,12 @@ static int select_exec(bContext *C, wmOperator *op)
static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
float co[2];
- ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_mouse_pos(area, region, event->mval, co);
RNA_float_set_array(op->ptr, "location", co);
@@ -435,8 +435,8 @@ void MASK_OT_select(wmOperatorType *ot)
static int box_select_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
Mask *mask = CTX_data_edit_mask(C);
@@ -454,16 +454,16 @@ static int box_select_exec(bContext *C, wmOperator *op)
/* get rectangle from operator */
WM_operator_properties_border_to_rcti(op, &rect);
- ED_mask_point_pos(sa, ar, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
- ED_mask_point_pos(sa, ar, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
+ ED_mask_point_pos(area, region, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
+ ED_mask_point_pos(area, region, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
/* do actual selection */
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
for (int i = 0; i < spline->tot_point; i++) {
@@ -521,12 +521,12 @@ void MASK_OT_select_box(wmOperatorType *ot)
* \{ */
static bool do_lasso_select_mask(bContext *C,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
Mask *mask = CTX_data_edit_mask(C);
@@ -540,15 +540,15 @@ static bool do_lasso_select_mask(bContext *C,
}
/* get rectangle from operator */
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
/* do actual selection */
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
for (int i = 0; i < spline->tot_point; i++) {
@@ -565,15 +565,15 @@ static bool do_lasso_select_mask(bContext *C,
float screen_co[2];
/* point in screen coords */
- ED_mask_point_pos__reverse(sa,
- ar,
+ ED_mask_point_pos__reverse(area,
+ region,
point_deform->bezt.vec[1][0],
point_deform->bezt.vec[1][1],
&screen_co[0],
&screen_co[1]);
if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
- BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) {
+ BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co[0], screen_co[1], INT_MAX)) {
BKE_mask_point_select_set(point, select);
BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
changed = true;
@@ -594,14 +594,14 @@ static bool do_lasso_select_mask(bContext *C,
static int clip_lasso_select_exec(bContext *C, wmOperator *op)
{
- int mcords_tot;
- const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+ int mcoords_len;
+ const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len);
- if (mcords) {
+ if (mcoords) {
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- do_lasso_select_mask(C, mcords, mcords_tot, sel_op);
+ do_lasso_select_mask(C, mcoords, mcoords_len, sel_op);
- MEM_freeN((void *)mcords);
+ MEM_freeN((void *)mcoords);
return OPERATOR_FINISHED;
}
@@ -651,8 +651,8 @@ static int mask_spline_point_inside_ellipse(BezTriple *bezt,
static int circle_select_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
Mask *mask = CTX_data_edit_mask(C);
int i;
@@ -667,14 +667,14 @@ static int circle_select_exec(bContext *C, wmOperator *op)
const int radius = RNA_int_get(op->ptr, "radius");
/* compute ellipse and position in unified coordinates */
- ED_mask_get_size(sa, &width, &height);
- ED_mask_zoom(sa, ar, &zoomx, &zoomy);
+ ED_mask_get_size(area, &width, &height);
+ ED_mask_zoom(area, region, &zoomx, &zoomy);
width = height = max_ii(width, height);
ellipse[0] = width * zoomx / radius;
ellipse[1] = height * zoomy / radius;
- ED_mask_point_pos(sa, ar, x, y, &offset[0], &offset[1]);
+ ED_mask_point_pos(area, region, x, y, &offset[0], &offset[1]);
const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
WM_gesture_is_modal_first(op->customdata));
@@ -685,12 +685,12 @@ static int circle_select_exec(bContext *C, wmOperator *op)
}
/* do actual selection */
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
for (i = 0; i < spline->tot_point; i++) {
@@ -748,8 +748,8 @@ void MASK_OT_select_circle(wmOperatorType *ot)
static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *mask_layer;
@@ -760,7 +760,7 @@ static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
const float threshold = 19;
bool changed = false;
- ED_mask_mouse_pos(sa, ar, event->mval, co);
+ ED_mask_mouse_pos(area, region, event->mval, co);
point = ED_mask_point_find_nearest(C, mask, co, threshold, &mask_layer, &spline, NULL, NULL);
@@ -814,12 +814,12 @@ static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
bool changed = false;
/* do actual selection */
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
if (ED_mask_spline_select_check(spline)) {
ED_mask_spline_select_set(spline, true);
changed = true;
@@ -864,12 +864,12 @@ static int mask_select_more_less(bContext *C, bool more)
{
Mask *mask = CTX_data_edit_mask(C);
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
const bool cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0;
bool start_sel, end_sel, prev_sel, cur_sel;
int i;
diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c
index 2300289fd3b..f264e67d35c 100644
--- a/source/blender/editors/mask/mask_shapekey.c
+++ b/source/blender/editors/mask/mask_shapekey.c
@@ -23,15 +23,15 @@
#include <stdlib.h>
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_mask.h"
-#include "DNA_object_types.h"
#include "DNA_mask_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DEG_depsgraph.h"
@@ -53,7 +53,7 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op))
Mask *mask = CTX_data_edit_mask(C);
bool changed = false;
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
MaskLayerShape *mask_layer_shape;
if (!ED_mask_layer_select_check(mask_layer)) {
@@ -98,7 +98,7 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
Mask *mask = CTX_data_edit_mask(C);
bool changed = false;
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
MaskLayerShape *mask_layer_shape;
if (!ED_mask_layer_select_check(mask_layer)) {
@@ -146,7 +146,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op)
Mask *mask = CTX_data_edit_mask(C);
bool changed = false;
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
@@ -172,7 +172,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op)
shape_ele_src = (MaskLayerShapeElem *)mask_layer_shape_reset->data;
shape_ele_dst = (MaskLayerShapeElem *)mask_layer_shape->data;
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
for (int i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
@@ -243,7 +243,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
const bool do_feather = RNA_boolean_get(op->ptr, "feather");
const bool do_location = RNA_boolean_get(op->ptr, "location");
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
@@ -324,7 +324,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
shape_ele_src = (MaskLayerShapeElem *)mask_layer_shape_tmp->data;
shape_ele_dst = (MaskLayerShapeElem *)mask_layer_shape_tmp_rekey->data;
- for (MaskSpline *spline = mask_layer->splines.first; spline; spline = spline->next) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
for (int i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
@@ -404,7 +404,7 @@ bool ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame)
{
bool changed = false;
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
ED_mask_layer_shape_auto_key(mask_layer, frame);
changed = true;
}
@@ -416,7 +416,7 @@ bool ED_mask_layer_shape_auto_key_select(Mask *mask, const int frame)
{
bool changed = false;
- for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
if (!ED_mask_layer_select_check(mask_layer)) {
continue;
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 5c9fb866df7..b303c4c7e4e 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -20,21 +20,22 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_bitmap.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
+#include "BKE_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -80,8 +81,8 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
return;
}
- Mesh *me_orig = ob_eval->runtime.mesh_orig;
- Mesh *me_eval = ob_eval->runtime.mesh_eval;
+ Mesh *me_orig = (Mesh *)ob_eval->runtime.data_orig;
+ Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval;
bool updated = false;
if (me_orig != NULL && me_eval != NULL && me_orig->totpoly == me->totpoly) {
@@ -189,7 +190,7 @@ void paintface_reveal(bContext *C, Object *ob, const bool select)
/* Set tface seams based on edge data, uses hash table to find seam edges. */
-static void select_linked_tfaces_with_seams(Mesh *me, const unsigned int index, const bool select)
+static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bool select)
{
MPoly *mp;
MLoop *ml;
@@ -200,7 +201,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const unsigned int index,
BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__);
BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__);
- if (index != (unsigned int)-1) {
+ if (index != (uint)-1) {
/* only put face under cursor in array */
mp = &me->mpoly[index];
BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
@@ -266,7 +267,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const unsigned int index,
void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const bool select)
{
Mesh *me;
- unsigned int index = (unsigned int)-1;
+ uint index = (uint)-1;
me = BKE_mesh_from_object(ob);
if (me == NULL || me->totpoly == 0) {
@@ -443,7 +444,7 @@ bool paintface_mouse_select(
void paintvert_flush_flags(Object *ob)
{
Mesh *me = BKE_mesh_from_object(ob);
- Mesh *me_eval = ob->runtime.mesh_eval;
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
MVert *mvert_eval, *mv;
const int *index_array = NULL;
int totvert;
@@ -492,8 +493,10 @@ void paintvert_tag_select_update(struct bContext *C, struct Object *ob)
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
}
-/* note: if the caller passes false to flush_flags,
- * then they will need to run paintvert_flush_flags(ob) themselves */
+/**
+ * \note if the caller passes false to flush_flags,
+ * then they will need to run #paintvert_flush_flags(ob) themselves.
+ */
bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
{
Mesh *me;
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 7a0124e72bb..1484dcfa92d 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -33,15 +33,15 @@
#include "BKE_context.h"
#include "BKE_editmesh.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_mesh.h"
-#include "ED_screen.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "ED_uvedit.h"
#include "mesh_intern.h" /* own include */
diff --git a/source/blender/editors/mesh/editmesh_add_gizmo.c b/source/blender/editors/mesh/editmesh_add_gizmo.c
index c748560ae1b..e7a99ca9e08 100644
--- a/source/blender/editors/mesh/editmesh_add_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_add_gizmo.c
@@ -69,8 +69,8 @@ static void calc_initial_placement_point_from_view(bContext *C,
{
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
bool use_mouse_project = true; /* TODO: make optional */
@@ -99,7 +99,7 @@ static void calc_initial_placement_point_from_view(bContext *C,
if (use_mouse_project) {
float plane[4];
plane_from_point_normal_v3(plane, cursor_matrix[3], orient_matrix[2]);
- if (ED_view3d_win_to_3d_on_plane(ar, plane, mval, true, r_location)) {
+ if (ED_view3d_win_to_3d_on_plane(region, plane, mval, true, r_location)) {
copy_m3_m3(r_rotation, orient_matrix);
return;
}
@@ -212,7 +212,7 @@ static void gizmo_mesh_placement_modal_from_setup(const bContext *C, wmGizmoGrou
/* Start off dragging. */
{
wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
wmGizmo *gz = ggd->cage;
{
@@ -220,8 +220,8 @@ static void gizmo_mesh_placement_modal_from_setup(const bContext *C, wmGizmoGrou
float location[3];
calc_initial_placement_point_from_view((bContext *)C,
(float[2]){
- win->eventstate->x - ar->winrct.xmin,
- win->eventstate->y - ar->winrct.ymin,
+ win->eventstate->x - region->winrct.xmin,
+ win->eventstate->y - region->winrct.ymin,
},
location,
mat3);
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 42fa3db7c57..e94412233ff 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -22,24 +22,24 @@
#include "DNA_object_types.h"
-#include "BLI_string.h"
#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_global.h"
+#include "BKE_curveprofile.h"
#include "BKE_editmesh.h"
-#include "BKE_unit.h"
+#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_mesh.h"
-#include "BKE_curveprofile.h"
+#include "BKE_unit.h"
-#include "DNA_mesh_types.h"
#include "DNA_curveprofile_types.h"
+#include "DNA_mesh_types.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -299,7 +299,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
/* avoid the cost of allocating a bm copy */
if (is_modal) {
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
Object *obedit = opdata->ob_store[ob_index].ob;
@@ -307,7 +307,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
opdata->ob_store[ob_index].mesh_backup = EDBM_redo_state_store(em);
}
opdata->draw_handle_pixel = ED_region_draw_cb_activate(
- ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
+ region->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
G.moving = G_TRANSFORM_EDIT;
if (v3d) {
@@ -416,10 +416,10 @@ static bool edbm_bevel_calc(wmOperator *op)
static void edbm_bevel_exit(bContext *C, wmOperator *op)
{
BevelData *opdata = op->customdata;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- if (sa) {
- ED_area_status_text(sa, NULL);
+ if (area) {
+ ED_area_status_text(area, NULL);
}
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
@@ -433,11 +433,11 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op)
if (opdata->is_modal) {
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false);
}
- ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel);
+ ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel);
if (v3d) {
v3d->gizmo_flag = opdata->gizmo_flag;
}
@@ -690,14 +690,14 @@ wmKeyMap *bevel_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Bevel Modal Map");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Bevel Modal Map");
/* This function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return NULL;
}
- keymap = WM_modalkeymap_add(keyconf, "Bevel Modal Map", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "Bevel Modal Map", modal_items);
WM_modalkeymap_assign(keymap, "MESH_OT_bevel");
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index b2af58e47f2..bc8c456889d 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -29,22 +29,22 @@
#include "BLT_translation.h"
-#include "BKE_global.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_report.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_gizmo_utils.h"
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_gizmo_utils.h"
#include "UI_resources.h"
@@ -81,8 +81,8 @@ static void mesh_bisect_interactive_calc(bContext *C,
float plane_no[3])
{
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
int x_start = RNA_int_get(op->ptr, "xstart");
int y_start = RNA_int_get(op->ptr, "ystart");
@@ -96,18 +96,18 @@ static void mesh_bisect_interactive_calc(bContext *C,
const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
/* view vector */
- ED_view3d_win_to_vector(ar, co_a_ss, co_a);
+ ED_view3d_win_to_vector(region, co_a_ss, co_a);
/* view delta */
sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss);
- ED_view3d_win_to_delta(ar, co_delta_ss, co_b, zfac);
+ ED_view3d_win_to_delta(region, co_delta_ss, co_b, zfac);
/* cross both to get a normal */
cross_v3_v3v3(plane_no, co_a, co_b);
normalize_v3(plane_no); /* not needed but nicer for user */
/* point on plane, can use either start or endpoint */
- ED_view3d_win_to_3d(v3d, ar, co_ref, co_a_ss, plane_co);
+ ED_view3d_win_to_3d(v3d, region, co_ref, co_a_ss, plane_co);
}
static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index b653484322a..bf6c5a2f829 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -24,19 +24,19 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
-#include "BKE_layer.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
+#include "BKE_report.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -226,6 +226,7 @@ static bool edbm_extrude_ex(Object *obedit,
char htype,
const char hflag,
const bool use_normal_flip,
+ const bool use_dissolve_ortho_edges,
const bool use_mirror,
const bool use_select_history)
{
@@ -241,6 +242,7 @@ static bool edbm_extrude_ex(Object *obedit,
BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region");
BMO_slot_bool_set(extop.slots_in, "use_normal_flip", use_normal_flip);
+ BMO_slot_bool_set(extop.slots_in, "use_dissolve_ortho_edges", use_dissolve_ortho_edges);
BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history);
BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag);
@@ -274,11 +276,27 @@ static bool edbm_extrude_ex(Object *obedit,
static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "offset");
const int steps = RNA_int_get(op->ptr, "steps");
- const float offs = RNA_float_get(op->ptr, "offset");
- float dvec[3], tmat[3][3], bmat[3][3];
- short a;
+ const float scale_offset = RNA_float_get(op->ptr, "scale_offset");
+ float offset[3];
+
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d != NULL) {
+ normalize_v3_v3(offset, rv3d->persinv[2]);
+ }
+ else {
+ copy_v3_v3(offset, (const float[3]){0, 0, 1});
+ }
+ RNA_property_float_set_array(op->ptr, prop, offset);
+ }
+ else {
+ RNA_property_float_get_array(op->ptr, prop, offset);
+ }
+
+ mul_v3_fl(offset, scale_offset);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
@@ -286,22 +304,19 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
view_layer, CTX_wm_view3d(C), &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ float offset_local[3], tmat[3][3];
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- /* dvec */
- normalize_v3_v3_length(dvec, rv3d->persinv[2], offs);
-
- /* base correction */
- copy_m3_m4(bmat, obedit->obmat);
- invert_m3_m3(tmat, bmat);
- mul_m3_v3(tmat, dvec);
+ copy_m3_m4(tmat, obedit->obmat);
+ invert_m3(tmat);
+ mul_v3_m3v3(offset_local, tmat, offset);
- for (a = 0; a < steps; a++) {
- edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false);
-
- BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", dvec, BM_ELEM_SELECT);
+ for (int a = 0; a < steps; a++) {
+ edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false, true);
+ BMO_op_callf(
+ em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", offset_local, BM_ELEM_SELECT);
}
EDBM_mesh_normals_update(em);
@@ -317,20 +332,23 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
void MESH_OT_extrude_repeat(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Extrude Repeat Mesh";
+ ot->name = "Extrude Repeat";
ot->description = "Extrude selected vertices, edges or faces repeatedly";
ot->idname = "MESH_OT_extrude_repeat";
/* api callbacks */
ot->exec = edbm_extrude_repeat_exec;
- ot->poll = ED_operator_editmesh_view3d;
+ ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_float_distance(ot->srna, "offset", 2.0f, 0.0f, 1e12f, "Offset", "", 0.0f, 100.0f);
RNA_def_int(ot->srna, "steps", 10, 0, 1000000, "Steps", "", 0, 180);
+ PropertyRNA *prop = RNA_def_float_vector_xyz(
+ ot->srna, "offset", 3, NULL, -100000, 100000, "Offset", "Offset vector", -1000.0f, 1000.0f);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_float(ot->srna, "scale_offset", 1.0f, 0.0f, 1e12f, "Scale Offset", "", 0.0f, 100.0f);
}
/** \} */
@@ -343,6 +361,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
{
const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip");
+ const bool use_dissolve_ortho_edges = RNA_boolean_get(op->ptr, "use_dissolve_ortho_edges");
const char htype = edbm_extrude_htype_from_em_select(em);
enum { NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY } nr;
bool changed = false;
@@ -385,7 +404,14 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
case NONE:
return false;
case ELEM_FLAG:
- changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, use_normal_flip, true, true);
+ changed = edbm_extrude_ex(obedit,
+ em,
+ htype,
+ BM_ELEM_SELECT,
+ use_normal_flip,
+ use_dissolve_ortho_edges,
+ true,
+ true);
break;
case VERT_ONLY:
changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
@@ -449,6 +475,7 @@ void MESH_OT_extrude_region(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
+ RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", "");
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
@@ -503,6 +530,7 @@ void MESH_OT_extrude_context(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
+ RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", "");
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
@@ -746,9 +774,9 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
float co1[2], co2[2];
- if ((ED_view3d_project_float_object(vc.ar, eed->v1->co, co1, V3D_PROJ_TEST_NOP) ==
+ if ((ED_view3d_project_float_object(vc.region, eed->v1->co, co1, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK) &&
- (ED_view3d_project_float_object(vc.ar, eed->v2->co, co2, V3D_PROJ_TEST_NOP) ==
+ (ED_view3d_project_float_object(vc.region, eed->v2->co, co2, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK)) {
/* 2D rotate by 90d while adding.
* (x, y) = (y, -x)
@@ -786,7 +814,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
copy_v3_v3(ofs, local_center);
mul_m4_v3(vc.obedit->obmat, ofs); /* view space */
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, ofs, event->mval, ofs);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.region, ofs, event->mval, ofs);
mul_m4_v3(vc.obedit->imat, ofs); // back in object space
sub_v3_v3(ofs, local_center);
@@ -820,11 +848,11 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
/* also project the source, for retopo workflow */
if (use_proj) {
- EDBM_project_snap_verts(C, depsgraph, vc.ar, vc.obedit, vc.em);
+ EDBM_project_snap_verts(C, depsgraph, vc.region, vc.obedit, vc.em);
}
}
- edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, true, true);
+ edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, false, true, true);
EDBM_op_callf(
vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, local_center, mat);
EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v", BM_ELEM_SELECT, ofs);
@@ -836,7 +864,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
BMOIter oiter;
copy_v3_v3(local_center, cursor);
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, local_center, event->mval, local_center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.region, local_center, event->mval, local_center);
mul_m4_v3(vc.obedit->imat, local_center); // back in object space
@@ -853,7 +881,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
}
if (use_proj) {
- EDBM_project_snap_verts(C, depsgraph, vc.ar, vc.obedit, vc.em);
+ EDBM_project_snap_verts(C, depsgraph, vc.region, vc.obedit, vc.em);
}
/* This normally happens when pushing undo but modal operators
diff --git a/source/blender/editors/mesh/editmesh_extrude_screw.c b/source/blender/editors/mesh/editmesh_extrude_screw.c
index ef393acdb4e..4cffd12cb34 100644
--- a/source/blender/editors/mesh/editmesh_extrude_screw.c
+++ b/source/blender/editors/mesh/editmesh_extrude_screw.c
@@ -32,8 +32,8 @@
#include "BKE_layer.h"
#include "BKE_report.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "WM_types.h"
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c
index 69274f77049..9f1d499bb6a 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin.c
@@ -26,12 +26,12 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
+#include "BKE_report.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "WM_api.h"
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
index af46d83265e..feb6b5aaca9 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
@@ -18,19 +18,20 @@
* \ingroup edmesh
*/
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_scene.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "ED_gizmo_utils.h"
#include "ED_screen.h"
@@ -429,11 +430,11 @@ static void gizmo_mesh_spin_init_message_subscribe(const bContext *C,
{
GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* Subscribe to view properties */
wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
+ .owner = region,
.user_data = gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
};
@@ -905,8 +906,8 @@ static void gizmo_mesh_spin_redo_setup(const bContext *C, wmGizmoGroup *gzgroup)
* Initialize the orientation from the spin gizmo if possible.
*/
{
- ARegion *ar = CTX_wm_region(C);
- wmGizmoMap *gzmap = ar->gizmo_map;
+ ARegion *region = CTX_wm_region(C);
+ wmGizmoMap *gzmap = region->gizmo_map;
wmGizmoGroup *gzgroup_init = WM_gizmomap_group_find(gzmap, "MESH_GGT_spin");
if (gzgroup_init) {
GizmoGroupData_SpinInit *ggd_init = gzgroup_init->customdata;
@@ -926,7 +927,7 @@ static void gizmo_mesh_spin_redo_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
const wmEvent *event = win->eventstate;
float plane_co[3], plane_no[3];
RNA_property_float_get_array(op->ptr, ggd->data.prop_axis_co, plane_co);
@@ -937,11 +938,11 @@ static void gizmo_mesh_spin_redo_setup(const bContext *C, wmGizmoGroup *gzgroup)
/* Use cursor as fallback if it's not set by the 'ortho_axis_active'. */
if (is_zero_v3(ggd->data.orient_axis_relative)) {
float cursor_co[3];
- const int mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+ const int mval[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin};
float plane[4];
plane_from_point_normal_v3(plane, plane_co, plane_no);
- if (UNLIKELY(!ED_view3d_win_to_3d_on_plane_int(ar, plane, mval, false, cursor_co))) {
- ED_view3d_win_to_3d_int(v3d, ar, plane, mval, cursor_co);
+ if (UNLIKELY(!ED_view3d_win_to_3d_on_plane_int(region, plane, mval, false, cursor_co))) {
+ ED_view3d_win_to_3d_int(v3d, region, plane, mval, cursor_co);
}
sub_v3_v3v3(ggd->data.orient_axis_relative, cursor_co, plane_co);
}
@@ -1010,8 +1011,8 @@ static void gizmo_mesh_spin_redo_setup(const bContext *C, wmGizmoGroup *gzgroup)
if (win && win->active) {
bScreen *screen = WM_window_get_active_screen(win);
if (screen->active_region) {
- ARegion *ar = CTX_wm_region(C);
- if (screen->active_region == ar) {
+ ARegion *region = CTX_wm_region(C);
+ if (screen->active_region == region) {
/* Become modal as soon as it's started. */
gizmo_mesh_spin_redo_modal_from_setup(C, gzgroup);
}
@@ -1030,7 +1031,7 @@ static void gizmo_mesh_spin_redo_draw_prepare(const bContext *UNUSED(C), wmGizmo
* could shift because of float precision.
* Updates in this case are also redundant. */
bool is_modal = false;
- for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
if (gz->state & WM_GIZMO_STATE_MODAL) {
is_modal = true;
break;
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index a1b1ea31ead..2eeada95eda 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -22,19 +22,19 @@
#include "DNA_object_types.h"
-#include "BLI_string.h"
#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_global.h"
#include "BKE_editmesh.h"
-#include "BKE_unit.h"
+#include "BKE_global.h"
#include "BKE_layer.h"
+#include "BKE_unit.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -88,10 +88,10 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
"(%s)");
char msg[UI_MAX_DRAW_STR];
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Scene *sce = CTX_data_scene(C);
- if (sa) {
+ if (area) {
char flts_str[NUM_STR_REP_LEN * 2];
if (hasNumInput(&opdata->num_input)) {
outputNumInput(&opdata->num_input, flts_str, &sce->unit);
@@ -111,7 +111,7 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
WM_bool_as_string(RNA_boolean_get(op->ptr, "use_boundary")),
WM_bool_as_string(RNA_boolean_get(op->ptr, "use_individual")));
- ED_area_status_text(sa, msg);
+ ED_area_status_text(area, msg);
}
}
@@ -166,7 +166,7 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
if (is_modal) {
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
Object *obedit = opdata->ob_store[ob_index].ob;
@@ -175,7 +175,7 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
}
opdata->draw_handle_pixel = ED_region_draw_cb_activate(
- ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
+ region->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
G.moving = G_TRANSFORM_EDIT;
if (v3d) {
opdata->gizmo_flag = v3d->gizmo_flag;
@@ -189,25 +189,25 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
static void edbm_inset_exit(bContext *C, wmOperator *op)
{
InsetData *opdata;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
opdata = op->customdata;
if (opdata->is_modal) {
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false);
}
- ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel);
+ ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel);
if (v3d) {
v3d->gizmo_flag = opdata->gizmo_flag;
}
G.moving = 0;
}
- if (sa) {
- ED_area_status_text(sa, NULL);
+ if (area) {
+ ED_area_status_text(area, NULL);
}
MEM_SAFE_FREE(opdata->ob_store);
@@ -401,7 +401,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
else {
bool handled = false;
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
case RIGHTMOUSE:
edbm_inset_cancel(C, op);
return OPERATOR_CANCELLED;
@@ -450,8 +450,8 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
case LEFTMOUSE:
- case PADENTER:
- case RETKEY:
+ case EVT_PADENTER:
+ case EVT_RETKEY:
if ((event->val == KM_PRESS) ||
((event->val == KM_RELEASE) && RNA_boolean_get(op->ptr, "release_confirm"))) {
edbm_inset_calc(op);
@@ -459,8 +459,8 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
break;
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
if (event->val == KM_PRESS) {
if (opdata->modify_depth) {
opdata->shift_amount = RNA_float_get(op->ptr, "depth");
@@ -478,8 +478,8 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
break;
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY: {
+ case EVT_LEFTCTRLKEY:
+ case EVT_RIGHTCTRLKEY: {
float mlen[2];
mlen[0] = opdata->mcenter[0] - event->mval[0];
@@ -506,7 +506,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
- case OKEY:
+ case EVT_OKEY:
if (event->val == KM_PRESS) {
const bool use_outset = RNA_boolean_get(op->ptr, "use_outset");
RNA_boolean_set(op->ptr, "use_outset", !use_outset);
@@ -520,7 +520,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
handled = true;
}
break;
- case BKEY:
+ case EVT_BKEY:
if (event->val == KM_PRESS) {
const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
RNA_boolean_set(op->ptr, "use_boundary", !use_boundary);
@@ -534,7 +534,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
handled = true;
}
break;
- case IKEY:
+ case EVT_IKEY:
if (event->val == KM_PRESS) {
const bool use_individual = RNA_boolean_get(op->ptr, "use_individual");
RNA_boolean_set(op->ptr, "use_individual", !use_individual);
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index 847a8ecacc3..fd7cc2733ec 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -22,17 +22,17 @@
#include "DNA_object_types.h"
+#include "BLI_buffer.h"
+#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_stack.h"
-#include "BLI_buffer.h"
-#include "BLI_linklist_stack.h"
-#include "BKE_layer.h"
-#include "BKE_editmesh_bvh.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "BKE_editmesh.h"
+#include "BKE_editmesh_bvh.h"
+#include "BKE_layer.h"
+#include "BKE_report.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -479,7 +479,7 @@ static bool bm_vert_in_faces_radial(BMVert *v, BMEdge *e_radial, BMFace *f_ignor
struct LinkBase {
LinkNode *list;
- unsigned int list_len;
+ uint list_len;
};
static void ghash_insert_face_edge_link(GHash *gh,
@@ -535,7 +535,7 @@ static void bm_face_split_by_edges_island_connect(
}
{
- unsigned int edge_arr_holes_len;
+ uint edge_arr_holes_len;
BMEdge **edge_arr_holes;
if (BM_face_split_edgenet_connect_islands(bm,
f,
@@ -704,6 +704,8 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
BMEdge *e;
BMIter iter;
+ BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+
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(
@@ -717,8 +719,6 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
- BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
-
{
BMVert *v;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -765,7 +765,7 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
BMIter liter;
BMLoop *l;
- unsigned int loop_stack_len;
+ uint loop_stack_len;
BMLoop *l_best = NULL;
BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index bad24eaa47c..f94cd778e13 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -29,14 +29,14 @@
#include "MEM_guardedalloc.h"
-#include "BLI_listbase.h"
-#include "BLI_string.h"
-#include "BLI_array.h"
#include "BLI_alloca.h"
+#include "BLI_array.h"
#include "BLI_linklist.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_smallhash.h"
#include "BLI_memarena.h"
+#include "BLI_smallhash.h"
+#include "BLI_string.h"
#include "BLT_translation.h"
@@ -50,10 +50,10 @@
#include "GPU_matrix.h"
#include "GPU_state.h"
+#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_view3d.h"
-#include "ED_mesh.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -153,7 +153,7 @@ typedef struct KnifePosData {
/* struct for properties used while drawing */
typedef struct KnifeTool_OpData {
- ARegion *ar; /* region that knifetool was activated in */
+ ARegion *region; /* region that knifetool was activated in */
void *draw_handle; /* for drawing preview loop */
ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */
float mval[2]; /* mouse value with snapping applied */
@@ -307,7 +307,7 @@ static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *k
static void knife_project_v2(const KnifeTool_OpData *kcd, const float co[3], float sco[2])
{
- ED_view3d_project_float_v2_m4(kcd->ar, co, sco, (float(*)[4])kcd->projmat);
+ ED_view3d_project_float_v2_m4(kcd->region, co, sco, (float(*)[4])kcd->projmat);
}
/* use when lambda is in screen-space */
@@ -997,7 +997,7 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
copy_v3_v3(co_depth, kcd->prev.cage);
mul_m4_v3(kcd->ob->obmat, co_depth);
- ED_view3d_win_to_3d(kcd->vc.v3d, kcd->ar, co_depth, kcd->curr.mval, curr_cage_adjust);
+ ED_view3d_win_to_3d(kcd->vc.v3d, kcd->region, co_depth, kcd->curr.mval, curr_cage_adjust);
mul_m4_v3(kcd->ob->imat, curr_cage_adjust);
sub_v3_v3v3(ray_dir, curr_cage_adjust, kcd->prev.cage);
@@ -1031,7 +1031,7 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColor(TH_TRANSFORM);
+ immUniformThemeColor3(TH_TRANSFORM);
GPU_line_width(2.0);
immBegin(GPU_PRIM_LINES, 2);
@@ -1058,7 +1058,7 @@ static void knife_init_colors(KnifeColors *colors)
}
/* modal loop selection drawing callback */
-static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
{
const KnifeTool_OpData *kcd = arg;
GPU_depth_test(false);
@@ -1134,7 +1134,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
if (kcd->totlinehit > 0) {
KnifeLineHit *lh;
- int i, v, vs;
+ int i, snapped_verts_count, other_verts_count;
float fcol[4];
GPU_blend(true);
@@ -1145,12 +1145,12 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
GPU_vertbuf_data_alloc(vert, kcd->totlinehit);
lh = kcd->linehits;
- for (i = 0, v = 0, vs = kcd->totlinehit - 1; i < kcd->totlinehit; i++, lh++) {
+ for (i = 0, snapped_verts_count = 0, other_verts_count = 0; i < kcd->totlinehit; i++, lh++) {
if (lh->v) {
- GPU_vertbuf_attr_set(vert, pos, v++, lh->cagehit);
+ GPU_vertbuf_attr_set(vert, pos, snapped_verts_count++, lh->cagehit);
}
else {
- GPU_vertbuf_attr_set(vert, pos, vs--, lh->cagehit);
+ GPU_vertbuf_attr_set(vert, pos, kcd->totlinehit - 1 - other_verts_count++, lh->cagehit);
}
}
@@ -1162,14 +1162,19 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
rgba_uchar_to_float(fcol, kcd->colors.point_a);
GPU_batch_uniform_4fv(batch, "color", fcol);
GPU_matrix_bind(batch->interface);
+ GPU_shader_set_srgb_uniform(batch->interface);
GPU_point_size(11);
- GPU_batch_draw_advanced(batch, 0, v - 1, 0, 0);
+ if (snapped_verts_count > 0) {
+ GPU_batch_draw_advanced(batch, 0, snapped_verts_count, 0, 0);
+ }
/* now draw the rest */
rgba_uchar_to_float(fcol, kcd->colors.curpoint_a);
GPU_batch_uniform_4fv(batch, "color", fcol);
GPU_point_size(7);
- GPU_batch_draw_advanced(batch, vs + 1, kcd->totlinehit - (vs + 1), 0, 0);
+ if (other_verts_count > 0) {
+ GPU_batch_draw_advanced(batch, snapped_verts_count, other_verts_count, 0, 0);
+ }
GPU_batch_program_use_end(batch);
GPU_batch_discard(batch);
@@ -1471,7 +1476,7 @@ static bool point_is_visible(KnifeTool_OpData *kcd,
float view[3], p_ofs[3];
/* TODO: I think there's a simpler way to get the required raycast ray */
- ED_view3d_unproject(kcd->vc.ar, s[0], s[1], 0.0f, view);
+ ED_view3d_unproject(kcd->vc.region, s[0], s[1], 0.0f, view);
mul_m4_v3(kcd->ob->imat, view);
@@ -1575,7 +1580,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
float line_tol, line_tol_sq;
float face_tol, face_tol_sq;
int isect_kind;
- unsigned int tot;
+ uint tot;
int i;
const bool use_hit_prev = true;
const bool use_hit_curr = (kcd->is_drag_hold == false);
@@ -1605,8 +1610,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
/* unproject screen line */
- ED_view3d_win_to_segment_clipped(kcd->vc.depsgraph, kcd->ar, kcd->vc.v3d, s1, v1, v3, true);
- ED_view3d_win_to_segment_clipped(kcd->vc.depsgraph, kcd->ar, kcd->vc.v3d, s2, v2, v4, true);
+ ED_view3d_win_to_segment_clipped(kcd->vc.depsgraph, kcd->region, kcd->vc.v3d, s1, v1, v3, true);
+ ED_view3d_win_to_segment_clipped(kcd->vc.depsgraph, kcd->region, kcd->vc.v3d, s2, v2, v4, true);
mul_m4_v3(kcd->ob->imat, v1);
mul_m4_v3(kcd->ob->imat, v2);
@@ -1852,8 +1857,8 @@ static void knife_input_ray_segment(KnifeTool_OpData *kcd,
float r_origin_ofs[3])
{
/* unproject to find view ray */
- ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], 0.0f, r_origin);
- ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], ofs, r_origin_ofs);
+ ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], 0.0f, r_origin);
+ ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], ofs, r_origin_ofs);
/* transform into object space */
invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
@@ -2415,7 +2420,7 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
edge_array_len = i;
#ifdef USE_NET_ISLAND_CONNECT
- unsigned int edge_array_holes_len;
+ uint edge_array_holes_len;
BMEdge **edge_array_holes;
if (BM_face_split_edgenet_connect_islands(bm,
f,
@@ -2578,7 +2583,7 @@ static void knifetool_finish(wmOperator *op)
static void knife_recalc_projmat(KnifeTool_OpData *kcd)
{
invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
- ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, kcd->projmat);
+ ED_view3d_ob_project_mat_get(kcd->region->regiondata, kcd->ob, kcd->projmat);
invert_m4_m4(kcd->projmat_inv, kcd->projmat);
mul_v3_mat3_m4v3(kcd->proj_zaxis, kcd->ob->imat, kcd->vc.rv3d->viewinv[2]);
@@ -2599,7 +2604,7 @@ static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
WM_cursor_modal_restore(CTX_wm_window(C));
/* deactivate the extra drawing stuff in 3D-View */
- ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle);
+ ED_region_draw_cb_exit(kcd->region->type, kcd->draw_handle);
}
/* free the custom data */
@@ -2619,7 +2624,7 @@ static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
BLI_gset_free(kcd->edgenet.edge_visit, NULL);
/* tag for redraw */
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
knifetool_free_bmbvh(kcd);
@@ -2643,7 +2648,7 @@ static void knifetool_update_mval(KnifeTool_OpData *kcd, const float mval[2])
copy_v2_v2(kcd->mval, mval);
if (knife_update_active(kcd)) {
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
}
}
@@ -2698,7 +2703,7 @@ static void knifetool_init(bContext *C,
/* assign the drawing handle for drawing preview line... */
kcd->scene = scene;
kcd->ob = obedit;
- kcd->ar = CTX_wm_region(C);
+ kcd->region = CTX_wm_region(C);
em_setup_viewcontext(C, &kcd->vc);
@@ -2722,7 +2727,7 @@ static void knifetool_init(bContext *C,
knife_recalc_projmat(kcd);
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
kcd->refs = BLI_mempool_create(sizeof(Ref), 0, 2048, 0);
kcd->kverts = BLI_mempool_create(sizeof(KnifeVert), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
@@ -2741,7 +2746,7 @@ static void knifetool_init(bContext *C,
if (is_interactive) {
kcd->draw_handle = ED_region_draw_cb_activate(
- kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
+ kcd->region->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
knife_init_colors(&kcd->colors);
}
@@ -2820,14 +2825,14 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Knife Tool Modal Map");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Knife Tool Modal Map");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return NULL;
}
- keymap = WM_modalkeymap_add(keyconf, "Knife Tool Modal Map", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "Knife Tool Modal Map", modal_items);
WM_modalkeymap_assign(keymap, "MESH_OT_knife_tool");
@@ -2847,7 +2852,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
em_setup_viewcontext(C, &kcd->vc);
- kcd->ar = kcd->vc.ar;
+ kcd->region = kcd->vc.region;
view3d_operator_needs_opengl(C);
ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */
@@ -2861,7 +2866,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->val) {
case KNF_MODAL_CANCEL:
/* finish */
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
knifetool_exit(C, op);
ED_workspace_status_text(C, NULL);
@@ -2869,7 +2874,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
case KNF_MODAL_CONFIRM:
/* finish */
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
knifetool_finish(op);
knifetool_exit(C, op);
@@ -2882,7 +2887,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
knife_recalc_projmat(kcd);
knife_update_active(kcd);
knife_update_header(C, op, kcd);
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
do_refresh = true;
break;
case KNF_MODAL_MIDPOINT_OFF:
@@ -2891,17 +2896,17 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
knife_recalc_projmat(kcd);
knife_update_active(kcd);
knife_update_header(C, op, kcd);
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
do_refresh = true;
break;
case KNF_MODEL_IGNORE_SNAP_ON:
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = true;
knife_update_header(C, op, kcd);
do_refresh = true;
break;
case KNF_MODEL_IGNORE_SNAP_OFF:
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = false;
knife_update_header(C, op, kcd);
do_refresh = true;
@@ -2917,7 +2922,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
do_refresh = true;
break;
case KNF_MODAL_NEW_CUT:
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
knife_finish_cut(kcd);
kcd->mode = MODE_IDLE;
break;
@@ -2947,7 +2952,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
knifetool_update_mval(kcd, kcd->curr.mval);
}
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
break;
case KNF_MODAL_ADD_CUT_CLOSED:
if (kcd->mode == MODE_DRAGGING) {
@@ -2982,7 +2987,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
kcd->mode = kcd->prevmode;
}
- ED_region_tag_redraw(kcd->ar);
+ ED_region_tag_redraw(kcd->region);
return OPERATOR_PASS_THROUGH;
}
}
@@ -3149,7 +3154,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
knifetool_init_bmbvh(kcd);
}
- ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, projmat);
+ ED_view3d_ob_project_mat_get(kcd->region->regiondata, kcd->ob, projmat);
/* use face-loop tag to store if we have intersected */
#define F_ISECT_IS_UNKNOWN(f) BM_elem_flag_test(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index ebd1e62e596..10e8bfa529f 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -24,23 +24,23 @@
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
-#include "BLI_math.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
-#include "BKE_mesh.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_editmesh.h"
+#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
+#include "BKE_object.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "MEM_guardedalloc.h"
@@ -58,13 +58,13 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C,
LinkNode *polys)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
struct Mesh *me_eval;
bool me_eval_needs_free;
- if (ob->type == OB_MESH || ob->runtime.mesh_eval) {
+ if (ob->type == OB_MESH || ob->runtime.data_eval) {
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- me_eval = ob_eval->runtime.mesh_eval;
+ me_eval = BKE_object_get_evaluated_mesh(ob_eval);
if (me_eval == NULL) {
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
@@ -87,7 +87,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C,
BKE_mesh_to_curve_nurblist(me_eval, &nurbslist, 0); /* wire */
BKE_mesh_to_curve_nurblist(me_eval, &nurbslist, 1); /* boundary */
- ED_view3d_ob_project_mat_get(ar->regiondata, ob, projmat);
+ ED_view3d_ob_project_mat_get(region->regiondata, ob, projmat);
if (nurbslist.first) {
Nurb *nu;
@@ -99,7 +99,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C,
float(*mval)[2] = MEM_mallocN(sizeof(*mval) * (nu->pntsu + is_cyclic), __func__);
for (bp = nu->bp, a = 0; a < nu->pntsu; a++, bp++) {
- ED_view3d_project_float_v2_m4(ar, bp->vec, mval[a], projmat);
+ ED_view3d_project_float_v2_m4(region, bp->vec, mval[a], projmat);
}
if (is_cyclic) {
copy_v2_v2(mval[a], mval[0]);
@@ -153,7 +153,9 @@ static int knifeproject_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
else {
- BKE_report(op->reports, RPT_ERROR, "No other selected objects found to use for projection");
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "No other selected objects have wire or boundary edges to use for projection");
return OPERATOR_CANCELLED;
}
}
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index ef05eb4ffda..3861676c2cf 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -25,27 +25,27 @@
#include "MEM_guardedalloc.h"
-#include "BLI_string.h"
#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLT_translation.h"
#include "DNA_mesh_types.h"
#include "BKE_context.h"
+#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_modifier.h"
#include "BKE_report.h"
-#include "BKE_editmesh.h"
#include "BKE_unit.h"
-#include "BKE_layer.h"
#include "UI_interface.h"
+#include "ED_mesh.h"
+#include "ED_numinput.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_view3d.h"
-#include "ED_mesh.h"
-#include "ED_numinput.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -66,7 +66,7 @@
/* struct for properties used while drawing */
typedef struct RingSelOpData {
- ARegion *ar; /* region that ringsel was activated in */
+ ARegion *region; /* region that ringsel was activated in */
void *draw_handle; /* for drawing preview loop */
struct EditMesh_PreSelEdgeRing *presel_edgering;
@@ -94,7 +94,7 @@ typedef struct RingSelOpData {
} RingSelOpData;
/* modal loop selection drawing callback */
-static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
{
RingSelOpData *lcd = arg;
EDBM_preselect_edgering_draw(lcd->presel_edgering, lcd->ob->obmat);
@@ -244,13 +244,13 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
RingSelOpData *lcd = op->customdata;
/* deactivate the extra drawing stuff in 3D-View */
- ED_region_draw_cb_exit(lcd->ar->type, lcd->draw_handle);
+ ED_region_draw_cb_exit(lcd->region->type, lcd->draw_handle);
EDBM_preselect_edgering_destroy(lcd->presel_edgering);
MEM_freeN(lcd->bases);
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
/* free the custom data */
MEM_freeN(lcd);
@@ -271,9 +271,9 @@ static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
lcd->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
/* assign the drawing handle for drawing preview line... */
- lcd->ar = CTX_wm_region(C);
+ lcd->region = CTX_wm_region(C);
lcd->draw_handle = ED_region_draw_cb_activate(
- lcd->ar->type, ringsel_draw, lcd, REGION_DRAW_POST_VIEW);
+ lcd->region->type, ringsel_draw, lcd, REGION_DRAW_POST_VIEW);
lcd->presel_edgering = EDBM_preselect_edgering_create();
/* Initialize once the cursor is over a mesh. */
lcd->ob = NULL;
@@ -291,7 +291,7 @@ static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
lcd->num.unit_type[0] = B_UNIT_NONE;
lcd->num.unit_type[1] = B_UNIT_NONE;
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
return 1;
}
@@ -372,7 +372,8 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
if (is_interactive) {
for (uint base_index = 0; base_index < bases_len; base_index++) {
Object *ob_iter = bases[base_index]->object;
- if (modifiers_isDeformedByLattice(ob_iter) || modifiers_isDeformedByArmature(ob_iter)) {
+ if (BKE_modifiers_is_deformed_by_lattice(ob_iter) ||
+ BKE_modifiers_is_deformed_by_armature(ob_iter)) {
BKE_report(
op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display");
break;
@@ -461,8 +462,8 @@ static int ringcut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
/* When accessed as a tool, get the active edge from the preselection gizmo. */
{
- ARegion *ar = CTX_wm_region(C);
- wmGizmoMap *gzmap = ar->gizmo_map;
+ ARegion *region = CTX_wm_region(C);
+ wmGizmoMap *gzmap = region->gizmo_map;
wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap,
"VIEW3D_GGT_mesh_preselect_edgering") :
NULL;
@@ -491,7 +492,7 @@ static int loopcut_exec(bContext *C, wmOperator *op)
static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
{
/* finish */
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
ED_workspace_status_text(C, NULL);
if (lcd->eed) {
@@ -521,7 +522,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
const bool has_numinput = hasNumInput(&lcd->num);
em_setup_viewcontext(C, &lcd->vc);
- lcd->ar = lcd->vc.ar;
+ lcd->region = lcd->vc.region;
view3d_operator_needs_opengl(C);
@@ -536,33 +537,33 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
else {
bool handled = false;
switch (event->type) {
- case RETKEY:
- case PADENTER:
+ case EVT_RETKEY:
+ case EVT_PADENTER:
case LEFTMOUSE: /* confirm */ // XXX hardcoded
if (event->val == KM_PRESS) {
return loopcut_finish(lcd, C, op);
}
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
handled = true;
break;
case RIGHTMOUSE: /* abort */ // XXX hardcoded
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
ringsel_exit(C, op);
ED_workspace_status_text(C, NULL);
return OPERATOR_CANCELLED;
- case ESCKEY:
+ case EVT_ESCKEY:
if (event->val == KM_RELEASE) {
/* cancel */
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
ED_workspace_status_text(C, NULL);
ringcut_cancel(C, op);
return OPERATOR_CANCELLED;
}
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
handled = true;
break;
case MOUSEPAN:
@@ -577,8 +578,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
handled = true;
break;
- case PADPLUSKEY:
- case PAGEUPKEY:
+ case EVT_PADPLUSKEY:
+ case EVT_PAGEUPKEY:
case WHEELUPMOUSE: /* change number of cuts */
if (event->val == KM_RELEASE) {
break;
@@ -591,8 +592,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
handled = true;
break;
- case PADMINUS:
- case PAGEDOWNKEY:
+ case EVT_PADMINUS:
+ case EVT_PAGEDOWNKEY:
case WHEELDOWNMOUSE: /* change number of cuts */
if (event->val == KM_RELEASE) {
break;
@@ -619,7 +620,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
lcd->vc.mval[1] = event->mval[1];
loopcut_mouse_move(lcd, (int)lcd->cuts);
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
handled = true;
} break;
}
@@ -640,14 +641,14 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
RNA_int_set(op->ptr, "number_cuts", (int)lcd->cuts);
ringsel_find_edge(lcd, (int)lcd->cuts);
show_cuts = true;
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
}
if (smoothness != lcd->smoothness) {
lcd->smoothness = clamp_f(smoothness, -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
RNA_float_set(op->ptr, "smoothness", lcd->smoothness);
show_cuts = true;
- ED_region_tag_redraw(lcd->ar);
+ ED_region_tag_redraw(lcd->region);
}
if (show_cuts) {
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index 139f05db01c..eed2cbcce39 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -30,7 +30,7 @@
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_paint.h"
@@ -40,15 +40,15 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "ED_mesh.h"
-#include "ED_screen.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_view3d.h"
@@ -63,14 +63,14 @@ static bool paint_mask_extract_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
if (ob != NULL && ob->mode == OB_MODE_SCULPT) {
if (ob->sculpt->bm) {
- CTX_wm_operator_poll_msg_set(C, "The mask can not be extracted with dyntopo activated.");
+ CTX_wm_operator_poll_msg_set(C, "The mask can not be extracted with dyntopo activated");
return false;
}
else {
- return true;
+ return ED_operator_object_active_editable_mesh(C);
}
}
- return ED_operator_object_active_editable_mesh(C);
+ return false;
}
static int paint_mask_extract_exec(bContext *C, wmOperator *op)
@@ -80,6 +80,9 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
+ ED_object_sculptmode_exit(C, depsgraph);
+
BKE_sculpt_mask_layers_ensure(ob, NULL);
Mesh *mesh = ob->data;
@@ -209,6 +212,11 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
Object *new_ob = ED_object_add_type(C, OB_MESH, NULL, ob->loc, ob->rot, false, local_view_bits);
BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob, &CD_MASK_EVERYTHING, true);
+ /* Remove the Face Sets as they need to be recreated when entering Sculpt Mode in the new object.
+ * TODO(pablodobarro): In the future we can try to preserve them from the original mesh. */
+ Mesh *new_ob_mesh = new_ob->data;
+ CustomData_free_layers(&new_ob_mesh->pdata, CD_SCULPT_FACE_SETS, new_ob_mesh->totpoly);
+
if (RNA_boolean_get(op->ptr, "apply_shrinkwrap")) {
BKE_shrinkwrap_mesh_nearest_surface_deform(C, new_ob, ob);
}
@@ -216,7 +224,7 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
if (RNA_boolean_get(op->ptr, "add_solidify")) {
ED_object_modifier_add(
op->reports, bmain, scene, new_ob, "mask_extract_solidify", eModifierType_Solidify);
- SolidifyModifierData *sfmd = (SolidifyModifierData *)modifiers_findByName(
+ SolidifyModifierData *sfmd = (SolidifyModifierData *)BKE_modifiers_findny_name(
new_ob, "mask_extract_solidify");
if (sfmd) {
sfmd->offset = -0.05f;
@@ -348,6 +356,10 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
if (ob->mode == OB_MODE_SCULPT) {
ED_sculpt_undo_geometry_begin(ob, "mask slice");
+ /* TODO: The ideal functionality would be to preserve the current face sets and add a new one
+ * for the new triangles, but this data-layer needs to be rebuild in order to make sculpt mode
+ * not crash when modifying the geometry. */
+ CustomData_free_layers(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->totpoly);
}
BMesh *bm;
@@ -420,6 +432,13 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
if (ob->mode == OB_MODE_SCULPT) {
ED_sculpt_undo_geometry_end(ob);
+ SculptSession *ss = ob->sculpt;
+ /* Rebuild a new valid Face Set layer for the object. */
+ ss->face_sets = CustomData_add_layer(
+ &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, mesh->totpoly);
+ for (int i = 0; i < mesh->totpoly; i++) {
+ ss->face_sets[i] = 1;
+ }
}
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index e09bcaf4edc..7cde233c6b6 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -23,25 +23,25 @@
#include "MEM_guardedalloc.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
#ifdef WITH_FREESTYLE
# include "DNA_meshdata_types.h"
#endif
-#include "BLI_math.h"
#include "BLI_linklist.h"
+#include "BLI_math.h"
-#include "BKE_layer.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_report.h"
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c
index 781e77de34a..c7bb45ccfe3 100644
--- a/source/blender/editors/mesh/editmesh_polybuild.c
+++ b/source/blender/editors/mesh/editmesh_polybuild.c
@@ -28,15 +28,15 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "BKE_editmesh.h"
-#include "BKE_mesh.h"
#include "BKE_layer.h"
+#include "BKE_mesh.h"
+#include "BKE_report.h"
#include "WM_types.h"
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_transform.h"
@@ -87,10 +87,10 @@ static void edbm_flag_disable_all_multi(ViewLayer *view_layer, View3D *v3d, cons
/* When accessed as a tool, get the active edge from the preselection gizmo. */
static bool edbm_preselect_or_active(bContext *C, const View3D *v3d, Base **r_base, BMElem **r_ele)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
const bool show_gizmo = !((v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)));
- wmGizmoMap *gzmap = show_gizmo ? ar->gizmo_map : NULL;
+ wmGizmoMap *gzmap = show_gizmo ? region->gizmo_map : NULL;
wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_mesh_preselect_elem") :
NULL;
if (gzgroup != NULL) {
@@ -162,7 +162,7 @@ static int edbm_polybuild_transform_at_cursor_invoke(bContext *C,
}
}
BM_select_history_store(bm, ele_act);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(vc.win);
return OPERATOR_FINISHED;
}
@@ -244,7 +244,7 @@ static int edbm_polybuild_delete_at_cursor_invoke(bContext *C,
ED_object_base_activate(C, basact);
}
}
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(vc.win);
return OPERATOR_FINISHED;
}
else {
@@ -296,7 +296,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
/* Just add vert */
copy_v3_v3(center, vc.scene->cursor.location);
mul_v3_m4v3(center, vc.obedit->obmat, center);
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
@@ -311,7 +311,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
mul_m4_v3(vc.obedit->obmat, center);
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
if (f_reference->len == 3 && RNA_boolean_get(op->ptr, "create_quads")) {
const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
@@ -366,7 +366,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
BMFace *f_reference = e_pair[0]->l ? e_pair[0]->l->f : NULL;
mul_v3_m4v3(center, vc.obedit->obmat, v_act->co);
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
BMVert *v_quad[4];
@@ -388,7 +388,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
else {
/* Just add edge */
mul_m4_v3(vc.obedit->obmat, center);
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, v_act->co, event->mval, center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.region, v_act->co, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
@@ -411,7 +411,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
}
}
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(vc.win);
return OPERATOR_FINISHED;
}
@@ -436,7 +436,7 @@ void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot)
RNA_def_boolean(ot->srna,
"create_quads",
true,
- "Create quads",
+ "Create Quads",
"Automatically split edges in triangles to maintain quad topology");
/* to give to transform */
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
@@ -474,7 +474,7 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C,
BMEdge *e_act = (BMEdge *)ele_act;
mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
mul_m4_v3(vc.obedit->obmat, center);
- ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
@@ -495,7 +495,7 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C,
EDBM_mesh_normals_update(em);
EDBM_update_generic(vc.obedit->data, true, true);
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(vc.win);
if (vc.view_layer->basact != basact) {
ED_object_base_activate(C, basact);
@@ -592,7 +592,7 @@ static int edbm_polybuild_dissolve_at_cursor_invoke(bContext *C,
ED_object_base_activate(C, basact);
}
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(vc.win);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_preselect_edgering.c b/source/blender/editors/mesh/editmesh_preselect_edgering.c
index 92a8c7da71d..50af79fc5e1 100644
--- a/source/blender/editors/mesh/editmesh_preselect_edgering.c
+++ b/source/blender/editors/mesh/editmesh_preselect_edgering.c
@@ -20,8 +20,8 @@
#include "MEM_guardedalloc.h"
-#include "BLI_stack.h"
#include "BLI_math.h"
+#include "BLI_stack.h"
#include "BKE_editmesh.h"
diff --git a/source/blender/editors/mesh/editmesh_preselect_elem.c b/source/blender/editors/mesh/editmesh_preselect_elem.c
index 05c4da68355..d53a1e2b55c 100644
--- a/source/blender/editors/mesh/editmesh_preselect_elem.c
+++ b/source/blender/editors/mesh/editmesh_preselect_elem.c
@@ -258,7 +258,7 @@ static void view3d_preselect_update_preview_triangle_from_vert(struct EditMesh_P
if (e_pair[1] != NULL) {
mul_v3_m4v3(center, vc->obedit->obmat, v_act->co);
- ED_view3d_win_to_3d_int(vc->v3d, vc->ar, center, mval, center);
+ ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
mul_m4_v3(vc->obedit->imat, center);
psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris) * 2, __func__);
@@ -326,7 +326,7 @@ static void view3d_preselect_update_preview_triangle_from_edge(struct EditMesh_P
psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 3, __func__);
mid_v3_v3v3(center, eed->v1->co, eed->v2->co);
mul_m4_v3(vc->obedit->obmat, center);
- ED_view3d_win_to_3d_int(vc->v3d, vc->ar, center, mval, center);
+ ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
mul_m4_v3(vc->obedit->imat, center);
copy_v3_v3(psel->preview_tris[0][0], eed->v1->co);
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 71bf77cc788..5d9923c6a7d 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -25,16 +25,16 @@
#include "DNA_object_types.h"
-#include "BLI_math.h"
#include "BLI_array.h"
+#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
+#include "BKE_report.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "WM_types.h"
@@ -56,7 +56,7 @@
* point and would result in the same distance.
*/
#define INSET_DEFAULT 0.00001f
-static float edbm_rip_edgedist_squared(ARegion *ar,
+static float edbm_rip_edgedist_squared(ARegion *region,
float mat[4][4],
const float co1[3],
const float co2[3],
@@ -65,8 +65,8 @@ static float edbm_rip_edgedist_squared(ARegion *ar,
{
float vec1[2], vec2[2], dist_sq;
- ED_view3d_project_float_v2_m4(ar, co1, vec1, mat);
- ED_view3d_project_float_v2_m4(ar, co2, vec2, mat);
+ ED_view3d_project_float_v2_m4(region, co1, vec1, mat);
+ ED_view3d_project_float_v2_m4(region, co2, vec2, mat);
if (inset != 0.0f) {
const float dist_2d = len_v2v2(vec1, vec2);
@@ -86,12 +86,12 @@ static float edbm_rip_edgedist_squared(ARegion *ar,
#if 0
static float edbm_rip_linedist(
- ARegion *ar, float mat[4][4], const float co1[3], const float co2[3], const float mvalf[2])
+ ARegion *region, float mat[4][4], const float co1[3], const float co2[3], const float mvalf[2])
{
float vec1[2], vec2[2];
- ED_view3d_project_float_v2_m4(ar, co1, vec1, mat);
- ED_view3d_project_float_v2_m4(ar, co2, vec2, mat);
+ ED_view3d_project_float_v2_m4(region, co1, vec1, mat);
+ ED_view3d_project_float_v2_m4(region, co2, vec2, mat);
return dist_to_line_v2(mvalf, vec1, vec2);
}
@@ -110,7 +110,7 @@ static void edbm_calc_loop_co(BMLoop *l, float l_mid_co[3])
}
static float edbm_rip_edge_side_measure(
- BMEdge *e, BMLoop *e_l, ARegion *ar, float projectMat[4][4], const float fmval[2])
+ BMEdge *e, BMLoop *e_l, ARegion *region, float projectMat[4][4], const float fmval[2])
{
float cent[3] = {0, 0, 0}, mid[3];
@@ -137,11 +137,11 @@ static float edbm_rip_edge_side_measure(
mid_v3_v3v3(cent, v1_other->co, v2_other->co);
mid_v3_v3v3(mid, e->v1->co, e->v2->co);
- ED_view3d_project_float_v2_m4(ar, cent, cent, projectMat);
- ED_view3d_project_float_v2_m4(ar, mid, mid, projectMat);
+ ED_view3d_project_float_v2_m4(region, cent, cent, projectMat);
+ ED_view3d_project_float_v2_m4(region, mid, mid, projectMat);
- ED_view3d_project_float_v2_m4(ar, e->v1->co, e_v1_co, projectMat);
- ED_view3d_project_float_v2_m4(ar, e->v2->co, e_v2_co, projectMat);
+ ED_view3d_project_float_v2_m4(region, e->v1->co, e_v1_co, projectMat);
+ ED_view3d_project_float_v2_m4(region, e->v2->co, e_v2_co, projectMat);
sub_v2_v2v2(vec, cent, mid);
normalize_v2_length(vec, 0.01f);
@@ -346,7 +346,7 @@ static BMVert *edbm_ripsel_edloop_pair_start_vert(BMEdge *e)
}
static void edbm_ripsel_deselect_helper(
- BMesh *bm, EdgeLoopPair *eloop_pairs, ARegion *ar, float projectMat[4][4], float fmval[2])
+ BMesh *bm, EdgeLoopPair *eloop_pairs, ARegion *region, float projectMat[4][4], float fmval[2])
{
EdgeLoopPair *lp;
@@ -360,12 +360,12 @@ static void edbm_ripsel_deselect_helper(
e = lp->l_a->e;
v_prev = edbm_ripsel_edloop_pair_start_vert(e);
for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) {
- score_a += edbm_rip_edge_side_measure(e, e->l, ar, projectMat, fmval);
+ score_a += edbm_rip_edge_side_measure(e, e->l, region, projectMat, fmval);
}
e = lp->l_b->e;
v_prev = edbm_ripsel_edloop_pair_start_vert(e);
for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) {
- score_b += edbm_rip_edge_side_measure(e, e->l, ar, projectMat, fmval);
+ score_b += edbm_rip_edge_side_measure(e, e->l, region, projectMat, fmval);
}
e = (score_a > score_b) ? lp->l_a->e : lp->l_b->e;
@@ -402,7 +402,7 @@ static UnorderedLoopPair *edbm_tagged_loop_pairs_to_fill(BMesh *bm)
BMIter iter;
BMEdge *e;
- unsigned int total_tag = 0;
+ uint total_tag = 0;
/* count tags, could be pre-calculated */
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
@@ -441,8 +441,8 @@ static UnorderedLoopPair *edbm_tagged_loop_pairs_to_fill(BMesh *bm)
static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *uloop_pairs)
{
UnorderedLoopPair *ulp;
- unsigned int total_tag = MEM_allocN_len(uloop_pairs) / sizeof(UnorderedLoopPair);
- unsigned int i;
+ uint total_tag = MEM_allocN_len(uloop_pairs) / sizeof(UnorderedLoopPair);
+ uint i;
for (i = 0, ulp = uloop_pairs; i < total_tag; i++, ulp++) {
if ((ulp->l_pair[0] && ulp->l_pair[1]) && (ulp->l_pair[0]->e != ulp->l_pair[1]->e)) {
@@ -514,7 +514,7 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u
static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obedit, bool do_fill)
{
UnorderedLoopPair *fill_uloop_pairs = NULL;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -568,7 +568,7 @@ static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obed
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
if ((is_manifold_region == false) || BM_edge_is_manifold(e)) {
d = edbm_rip_edgedist_squared(
- ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
+ region, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
if ((e_best == NULL) || (d < dist_sq)) {
dist_sq = d;
e_best = e;
@@ -619,7 +619,7 @@ static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obed
float l_mid_co[3];
l = l_all[i1];
edbm_calc_loop_co(l, l_mid_co);
- d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
+ d = edbm_rip_edgedist_squared(region, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
if ((e_best == NULL) || (d < dist_sq)) {
dist_sq = d;
@@ -678,7 +678,8 @@ static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obed
float l_mid_co[3];
edbm_calc_loop_co(l, l_mid_co);
- d = edbm_rip_edgedist_squared(ar, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT);
+ d = edbm_rip_edgedist_squared(
+ region, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT);
if (d < dist_sq) {
dist_sq = d;
@@ -695,7 +696,8 @@ static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obed
float e_mid_co[3];
mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co);
- d = edbm_rip_edgedist_squared(ar, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT);
+ d = edbm_rip_edgedist_squared(
+ region, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT);
if (d < dist_sq) {
dist_sq = d;
@@ -837,7 +839,7 @@ static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obed
/* check if v_best is null in the _rare_ case there are numeric issues */
edbm_calc_loop_co(l, l_corner_co);
d = edbm_rip_edgedist_squared(
- ar, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT);
+ region, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT);
if ((v_best == NULL) || (d < dist_sq)) {
v_best = v;
dist_sq = d;
@@ -872,7 +874,7 @@ static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obed
static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obedit, bool do_fill)
{
UnorderedLoopPair *fill_uloop_pairs = NULL;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -933,8 +935,8 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed
/* find the best face to follow, this way the edge won't point away from
* the mouse when there are more than 4 (takes the shortest face fan around) */
- l = (edbm_rip_edge_side_measure(e_best, l_a, ar, projectMat, fmval) <
- edbm_rip_edge_side_measure(e_best, l_b, ar, projectMat, fmval)) ?
+ l = (edbm_rip_edge_side_measure(e_best, l_a, region, projectMat, fmval) <
+ edbm_rip_edge_side_measure(e_best, l_b, region, projectMat, fmval)) ?
l_a :
l_b;
@@ -977,7 +979,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed
* edge did not split even though it was tagged which would not work
* as expected (but not crash), however there are checks to ensure
* tagged edges will split. So far its not been an issue. */
- edbm_ripsel_deselect_helper(bm, eloop_pairs, ar, projectMat, fmval);
+ edbm_ripsel_deselect_helper(bm, eloop_pairs, region, projectMat, fmval);
MEM_freeN(eloop_pairs);
/* deselect loose verts */
diff --git a/source/blender/editors/mesh/editmesh_rip_edge.c b/source/blender/editors/mesh/editmesh_rip_edge.c
index 5dd3c85f34f..6775cb85ef9 100644
--- a/source/blender/editors/mesh/editmesh_rip_edge.c
+++ b/source/blender/editors/mesh/editmesh_rip_edge.c
@@ -27,9 +27,9 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
+#include "BKE_report.h"
#include "WM_types.h"
@@ -47,7 +47,7 @@
static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
@@ -86,7 +86,7 @@ static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
float v_sco[2];
- ED_view3d_project_float_v2_m4(ar, v->co, v_sco, projectMat);
+ ED_view3d_project_float_v2_m4(region, v->co, v_sco, projectMat);
add_v2_v2(cent_sco, v_sco);
cent_tot += 1;
@@ -108,8 +108,8 @@ static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
float cent_sco_test[2];
float dist_sq_test;
- ED_view3d_project_float_v2_m4(ar, e->v1->co, e_sco[0], projectMat);
- ED_view3d_project_float_v2_m4(ar, e->v2->co, e_sco[1], projectMat);
+ ED_view3d_project_float_v2_m4(region, e->v1->co, e_sco[0], projectMat);
+ ED_view3d_project_float_v2_m4(region, e->v2->co, e_sco[1], projectMat);
closest_to_line_segment_v2(cent_sco_test, mval_fl, e_sco[0], e_sco[1]);
dist_sq_test = len_squared_v2v2(cent_sco_test, mval_fl);
@@ -167,7 +167,7 @@ static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
goto found_edge;
}
#endif
- ED_view3d_project_float_v2_m4(ar, v->co, v_sco, projectMat);
+ ED_view3d_project_float_v2_m4(region, v->co, v_sco, projectMat);
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
@@ -175,7 +175,7 @@ static int edbm_rip_edge_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
float v_other_sco[2];
float angle_test;
- ED_view3d_project_float_v2_m4(ar, v_other->co, v_other_sco, projectMat);
+ ED_view3d_project_float_v2_m4(region, v_other->co, v_other_sco, projectMat);
/* avoid comparing with view-axis aligned edges (less than a pixel) */
if (len_squared_v2v2(v_sco, v_other_sco) > 1.0f) {
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 6eabb079f4e..6b029cdef16 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -23,21 +23,21 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array.h"
#include "BLI_bitmap.h"
-#include "BLI_listbase.h"
+#include "BLI_heap.h"
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_bits.h"
#include "BLI_rand.h"
-#include "BLI_array.h"
-#include "BLI_heap.h"
#include "BLI_utildefines_stack.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
+#include "BKE_report.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -46,11 +46,11 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_screen.h"
-#include "ED_transform.h"
#include "ED_select_utils.h"
+#include "ED_transform.h"
#include "ED_view3d.h"
#include "DNA_mesh_types.h"
@@ -286,7 +286,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region, *r_dist);
uint index;
BMVert *eve;
@@ -295,7 +295,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_VERTEX);
index = DRW_select_buffer_find_nearest_to_point(
- vc->depsgraph, vc->ar, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px);
+ vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px);
if (index) {
eve = (BMVert *)edbm_select_id_bm_elem_get(bases, index, &base_index);
@@ -509,7 +509,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region, *r_dist);
uint index;
BMEdge *eed;
@@ -518,7 +518,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_EDGE);
index = DRW_select_buffer_find_nearest_to_point(
- vc->depsgraph, vc->ar, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px);
+ vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px);
if (index) {
eed = (BMEdge *)edbm_select_id_bm_elem_get(bases, index, &base_index);
@@ -724,7 +724,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
{
DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_FACE);
- index = DRW_select_buffer_sample_point(vc->depsgraph, vc->ar, vc->v3d, vc->mval);
+ index = DRW_select_buffer_sample_point(vc->depsgraph, vc->region, vc->v3d, vc->mval);
if (index) {
efa = (BMFace *)edbm_select_id_bm_elem_get(bases, index, &base_index);
@@ -1042,7 +1042,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
} best_face = {0, NULL};
if (ED_view3d_win_to_ray_clipped(
- vc->depsgraph, vc->ar, vc->v3d, mval_fl, ray_origin, ray_direction, true)) {
+ vc->depsgraph, vc->region, vc->v3d, mval_fl, ray_origin, ray_direction, true)) {
float dist_sq_best = FLT_MAX;
float dist_sq_best_vert = FLT_MAX;
float dist_sq_best_edge = FLT_MAX;
@@ -1733,12 +1733,12 @@ static bool mouse_mesh_loop(
/* We can't be sure this has already been set... */
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
- if (ED_view3d_project_float_object(vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) ==
+ if (ED_view3d_project_float_object(vc.region, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) ==
V3D_PROJ_RET_OK) {
length_1 = len_squared_v2v2(mvalf, v1_co);
}
- if (ED_view3d_project_float_object(vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) ==
+ if (ED_view3d_project_float_object(vc.region, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) ==
V3D_PROJ_RET_OK) {
length_2 = len_squared_v2v2(mvalf, v2_co);
}
@@ -1768,7 +1768,7 @@ static bool mouse_mesh_loop(
float co[2], tdist;
BM_face_calc_center_median(f, cent);
- if (ED_view3d_project_float_object(vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) ==
+ if (ED_view3d_project_float_object(vc.region, cent, co, V3D_PROJ_TEST_CLIP_NEAR) ==
V3D_PROJ_RET_OK) {
tdist = len_squared_v2v2(mvalf, co);
if (tdist < best_dist) {
@@ -2335,6 +2335,8 @@ void EDBM_selectmode_convert(BMEditMesh *em,
BM_edge_select_set(bm, eed, false);
}
}
+ /* Deselect faces without edges selected. */
+ BM_mesh_deselect_flush(bm);
}
else if (selectmode_new == SCE_SELECT_VERTEX) {
/* flush down (face -> vert) */
@@ -2668,8 +2670,9 @@ bool EDBM_selectmode_disable_multi_ex(Scene *scene,
Object *ob_iter = base_iter->object;
BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- EDBM_selectmode_disable(scene, em_iter, selectmode_disable, selectmode_fallback);
- changed_multi = true;
+ if (EDBM_selectmode_disable(scene, em_iter, selectmode_disable, selectmode_fallback)) {
+ changed_multi = true;
+ }
}
return changed_multi;
}
@@ -3201,8 +3204,12 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
BMEdge *e;
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BMO_edge_flag_test(bm, e, BMO_ELE_TAG)) {
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+ /* Check the edge for selected faces,
+ * this supports stepping off isolated vertices which would otherwise be ignored. */
+ if (BM_edge_is_any_face_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+ }
}
}
}
@@ -3258,10 +3265,13 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
if (delimit) {
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(
- e,
- BM_ELEM_TAG,
- (BM_elem_flag_test(e, BM_ELEM_SELECT) && BMO_edge_flag_test(bm, e, BMO_ELE_TAG)));
+ /* Check the edge for selected faces,
+ * this supports stepping off isolated edges which would otherwise be ignored. */
+ BM_elem_flag_set(e,
+ BM_ELEM_TAG,
+ (BM_elem_flag_test(e, BM_ELEM_SELECT) &&
+ (BMO_edge_flag_test(bm, e, BMO_ELE_TAG) ||
+ !BM_edge_is_any_face_flag_test(e, BM_ELEM_SELECT))));
}
}
else {
diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c
index cee048b9513..365c5b5d264 100644
--- a/source/blender/editors/mesh/editmesh_select_similar.c
+++ b/source/blender/editors/mesh/editmesh_select_similar.c
@@ -229,7 +229,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
if (ob->totcol == 0) {
continue;
}
- material_array = give_matarar(ob);
+ material_array = BKE_object_material_array_p(ob);
break;
}
case SIMFACE_FREESTYLE: {
@@ -353,7 +353,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
if (ob->totcol == 0) {
continue;
}
- material_array = give_matarar(ob);
+ material_array = BKE_object_material_array_p(ob);
break;
}
case SIMFACE_FREESTYLE: {
@@ -1059,7 +1059,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
if (type == SIMVERT_VGROUP) {
/* We store the names of the vertex groups, so we can select
- * vertex groups with the same name in different objects. */
+ * vertex groups with the same name in different objects. */
const int dvert_tot = BLI_listbase_count(&ob->defbase);
for (int i = 0; i < dvert_tot; i++) {
if (dvert_selected & (1 << i)) {
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 43a787481b1..1096c5836d1 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -35,20 +35,20 @@
#include "BLI_bitmap.h"
#include "BLI_heap_simple.h"
-#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_sort_utils.h"
#include "BLI_string.h"
-#include "BKE_editmesh.h"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_editmesh.h"
#include "BKE_key.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -60,8 +60,8 @@
#include "BLT_translation.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "WM_api.h"
@@ -69,9 +69,9 @@
#include "ED_mesh.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_transform.h"
-#include "ED_transform_snap_object_context.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
@@ -410,44 +410,6 @@ void MESH_OT_unsubdivide(wmOperatorType *ot)
ot->srna, "iterations", 2, 1, 1000, "Iterations", "Number of times to unsubdivide", 1, 100);
}
-void EDBM_project_snap_verts(
- bContext *C, Depsgraph *depsgraph, ARegion *ar, Object *obedit, BMEditMesh *em)
-{
- Main *bmain = CTX_data_main(C);
- BMIter iter;
- BMVert *eve;
-
- ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
-
- struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, CTX_data_scene(C), depsgraph, 0, ar, CTX_wm_view3d(C));
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- float mval[2], co_proj[3];
- if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) ==
- V3D_PROJ_RET_OK) {
- if (ED_transform_snap_object_project_view3d(snap_context,
- SCE_SNAP_MODE_FACE,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_NOT_ACTIVE,
- .use_object_edit_cage = false,
- .use_occlusion_test = true,
- },
- mval,
- NULL,
- NULL,
- co_proj,
- NULL)) {
- mul_v3_m4v3(eve->co, obedit->imat, co_proj);
- }
- }
- }
- }
-
- ED_transform_snap_object_context_destroy(snap_context);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -730,8 +692,10 @@ static int edbm_collapse_edge_exec(bContext *C, wmOperator *op)
void MESH_OT_edge_collapse(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Edge Collapse";
- ot->description = "Collapse selected edges";
+ ot->name = "Collapse Edges & Faces";
+ ot->description =
+ "Collapse isolated edges & faces regions, merging data such as UV's and vertex colors. "
+ "This can collapse edge-rings as well as regions of connected faces into vertices";
ot->idname = "MESH_OT_edge_collapse";
/* api callbacks */
@@ -753,7 +717,7 @@ static bool edbm_add_edge_face__smooth_get(BMesh *bm)
BMEdge *e;
BMIter iter;
- unsigned int vote_on_smooth[2] = {0, 0};
+ uint vote_on_smooth[2] = {0, 0};
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_SELECT) && e->l) {
@@ -1183,6 +1147,12 @@ void MESH_OT_mark_sharp(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Connect Vertex Path Operator
+ * \{ */
+
static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator *op)
{
BMesh *bm = em->bm;
@@ -1308,7 +1278,7 @@ void MESH_OT_vert_connect(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Split Concave Faces Operator
+/** \name Connect Vertex Path Operator
* \{ */
/**
@@ -1597,6 +1567,12 @@ void MESH_OT_vert_connect_path(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Connect Concave Operator
+ * \{ */
+
static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1770,8 +1746,93 @@ void MESH_OT_face_make_planar(wmOperatorType *ot)
/** \name Split Edge Operator
* \{ */
+static bool edbm_edge_split_selected_edges(wmOperator *op, Object *obedit, BMEditMesh *em)
+{
+ BMesh *bm = em->bm;
+ if (bm->totedgesel == 0) {
+ return false;
+ }
+ if (!EDBM_op_call_and_selectf(
+ em, op, "edges.out", false, "split_edges edges=%he", BM_ELEM_SELECT)) {
+ return false;
+ }
+
+ EDBM_select_flush(em);
+ EDBM_update_generic(obedit->data, true, true);
+
+ return true;
+}
+
+static bool edbm_edge_split_selected_verts(wmOperator *op, Object *obedit, BMEditMesh *em)
+{
+ BMesh *bm = em->bm;
+
+ /* Note that tracking vertices through the 'split_edges' operator is complicated.
+ * Instead, tag loops for selection. */
+ if (bm->totvertsel == 0) {
+ return false;
+ }
+
+ /* Flush from vertices to edges. */
+ BMIter iter;
+ BMEdge *eed;
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_disable(eed, BM_ELEM_TAG);
+ if (eed->l != NULL) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) &&
+ (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) {
+ BM_elem_flag_enable(eed, BM_ELEM_TAG);
+ }
+ /* Store selection in loop tags. */
+ BMLoop *l_iter = eed->l;
+ do {
+ BM_elem_flag_set(l_iter, BM_ELEM_TAG, BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT));
+ } while ((l_iter = l_iter->radial_next) != eed->l);
+ }
+ }
+
+ if (!EDBM_op_callf(em,
+ op,
+ "split_edges edges=%he verts=%hv use_verts=%b",
+ BM_ELEM_TAG,
+ BM_ELEM_SELECT,
+ true)) {
+ return false;
+ }
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (eed->l != NULL) {
+ BMLoop *l_iter = eed->l;
+ do {
+ if (BM_elem_flag_test(l_iter, BM_ELEM_TAG)) {
+ BM_vert_select_set(em->bm, l_iter->v, true);
+ }
+ } while ((l_iter = l_iter->radial_next) != eed->l);
+ }
+ else {
+ /* Split out wire. */
+ for (int i = 0; i < 2; i++) {
+ BMVert *v = *(&eed->v1 + i);
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ if (eed != BM_DISK_EDGE_NEXT(eed, v)) {
+ BM_vert_separate(bm, v, &eed, 1, true, NULL, NULL);
+ }
+ }
+ }
+ }
+ }
+
+ EDBM_select_flush(em);
+ EDBM_update_generic(obedit->data, true, true);
+
+ return true;
+}
+
static int edbm_edge_split_exec(bContext *C, wmOperator *op)
{
+ const int type = RNA_enum_get(op->ptr, "type");
+
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(
@@ -1779,20 +1840,21 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totedgesel == 0) {
- continue;
- }
- if (!EDBM_op_call_and_selectf(
- em, op, "edges.out", false, "split_edges edges=%he", BM_ELEM_SELECT)) {
- continue;
- }
-
- if (em->selectmode == SCE_SELECT_FACE) {
- EDBM_select_flush(em);
+ switch (type) {
+ case BM_VERT:
+ if (!edbm_edge_split_selected_verts(op, obedit, em)) {
+ continue;
+ }
+ break;
+ case BM_EDGE:
+ if (!edbm_edge_split_selected_edges(op, obedit, em)) {
+ continue;
+ }
+ break;
+ default:
+ BLI_assert(0);
}
-
- EDBM_update_generic(obedit->data, true, true);
}
MEM_freeN(objects);
@@ -1812,6 +1874,20 @@ void MESH_OT_edge_split(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ static const EnumPropertyItem merge_type_items[] = {
+ {BM_EDGE, "EDGE", 0, "Faces by Edges", "Split faces along selected edges"},
+ {BM_VERT,
+ "VERT",
+ 0,
+ "Faces & Edges by Vertices",
+ "Split faces & edges connected to selected vertices"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", merge_type_items, BM_EDGE, "Type", "Method to use for splitting");
}
/** \} */
@@ -1894,6 +1970,84 @@ void MESH_OT_duplicate(wmOperatorType *ot)
RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
}
+static BMLoopNorEditDataArray *flip_custom_normals_init_data(BMesh *bm)
+{
+ BMLoopNorEditDataArray *lnors_ed_arr = NULL;
+ if (CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
+ /* The mesh has custom normal data, update these too.
+ * Otherwise they will be left in a mangled state.
+ */
+ BM_lnorspace_update(bm);
+ lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, true);
+ }
+
+ return lnors_ed_arr;
+}
+
+static bool flip_custom_normals(BMesh *bm, BMLoopNorEditDataArray *lnors_ed_arr)
+{
+ if (!lnors_ed_arr) {
+ return false;
+ }
+
+ if (lnors_ed_arr->totloop == 0) {
+ /* No loops normals to flip, exit early! */
+ return false;
+ }
+
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BM_lnorspace_update(bm);
+
+ /* We need to recreate the custom normal array because the clnors_data will
+ * be mangled because we swapped the loops around when we flipped the faces. */
+ BMLoopNorEditDataArray *lnors_ed_arr_new_full = BM_loop_normal_editdata_array_init(bm, true);
+
+ {
+ /* We need to recalculate all loop normals in the affected area. Even the ones that are not
+ * going to be flipped because the clnors data is mangled. */
+
+ BMLoopNorEditData *lnor_ed_new_full = lnors_ed_arr_new_full->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr_new_full->totloop; i++, lnor_ed_new_full++) {
+
+ BMLoopNorEditData *lnor_ed =
+ lnors_ed_arr->lidx_to_lnor_editdata[lnor_ed_new_full->loop_index];
+
+ BLI_assert(lnor_ed != NULL);
+
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed_new_full->loop_index],
+ lnor_ed->nloc,
+ lnor_ed_new_full->clnors_data);
+ }
+ }
+
+ BMFace *f;
+ BMLoop *l;
+ BMIter iter_f, iter_l;
+ BM_ITER_MESH (f, &iter_f, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ continue;
+ }
+ /* Flip all the custom loop normals on the selected faces. */
+
+ BM_ITER_ELEM (l, &iter_l, f, BM_LOOPS_OF_FACE) {
+
+ int loop_index = BM_elem_index_get(l);
+
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lidx_to_lnor_editdata[loop_index];
+ BMLoopNorEditData *lnor_ed_new = lnors_ed_arr_new_full->lidx_to_lnor_editdata[loop_index];
+ BLI_assert(lnor_ed != NULL && lnor_ed_new != NULL);
+
+ negate_v3(lnor_ed->nloc);
+
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[loop_index], lnor_ed->nloc, lnor_ed_new->clnors_data);
+ }
+ }
+ BM_loop_normal_editdata_array_free(lnors_ed_arr_new_full);
+ return true;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1901,6 +2055,8 @@ void MESH_OT_duplicate(wmOperatorType *ot)
* \{ */
static int edbm_flip_normals_exec(bContext *C, wmOperator *op)
{
+ const bool only_clnors = RNA_boolean_get(op->ptr, "only_clnors");
+
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(
@@ -1910,15 +2066,48 @@ static int edbm_flip_normals_exec(bContext *C, wmOperator *op)
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
+ if (only_clnors) {
+ if (CustomData_has_layer(&em->bm->ldata, CD_CUSTOMLOOPNORMAL)) {
+ /* The mesh has custom normal data, flip them. */
+ BMesh *bm = em->bm;
+
+ BM_lnorspace_update(bm);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ negate_v3(lnor_ed->nloc);
+
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ lnor_ed->nloc,
+ lnor_ed->clnors_data);
+ }
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ EDBM_update_generic(obedit->data, true, false);
+ }
continue;
}
- if (!EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true)) {
+ if (em->bm->totfacesel == 0) {
continue;
}
- EDBM_update_generic(obedit->data, true, false);
+ bool has_flipped_faces = false;
+
+ /* See if we have any custom normals to flip. */
+ BMLoopNorEditDataArray *lnors_ed_arr = flip_custom_normals_init_data(em->bm);
+
+ if (EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true)) {
+ has_flipped_faces = true;
+ }
+
+ if (flip_custom_normals(em->bm, lnors_ed_arr) || has_flipped_faces) {
+ EDBM_update_generic(obedit->data, true, false);
+ }
+
+ if (lnors_ed_arr != NULL) {
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ }
}
MEM_freeN(objects);
@@ -1938,6 +2127,12 @@ void MESH_OT_flip_normals(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna,
+ "only_clnors",
+ false,
+ "Custom Normals Only",
+ "Only flip the custom loop normals of the selected elements");
}
/** \} */
@@ -2200,6 +2395,7 @@ void MESH_OT_reveal(wmOperatorType *ot)
static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool inside = RNA_boolean_get(op->ptr, "inside");
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
@@ -2212,11 +2408,23 @@ static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op)
continue;
}
+ BMLoopNorEditDataArray *lnors_ed_arr = NULL;
+
+ if (inside) {
+ /* Save custom normal data for later so we can flip them correctly. */
+ lnors_ed_arr = flip_custom_normals_init_data(em->bm);
+ }
+
if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf", BM_ELEM_SELECT)) {
continue;
}
- if (RNA_boolean_get(op->ptr, "inside")) {
+
+ if (inside) {
EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true);
+ flip_custom_normals(em->bm, lnors_ed_arr);
+ if (lnors_ed_arr != NULL) {
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ }
}
EDBM_update_generic(obedit->data, true, false);
@@ -3107,7 +3315,7 @@ void MESH_OT_merge(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Remove Doubles Operator
+/** \name Merge By Distance Operator
* \{ */
static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
@@ -3381,11 +3589,9 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
if (use_add) {
/* In add mode, we add relative shape key offset. */
- if (kb) {
- const float *rco = CustomData_bmesh_get_n(
- &em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative);
- sub_v3_v3v3(co, co, rco);
- }
+ const float *rco = CustomData_bmesh_get_n(
+ &em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative);
+ sub_v3_v3v3(co, co, rco);
madd_v3_v3fl(eve->co, co, blend);
}
@@ -3750,7 +3956,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
BMVert *bv;
BMIter iter;
BMEdge *be;
@@ -3764,8 +3970,8 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
/* allocd vars */
float(*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2];
- /* edit-object needed for matrix, and ar->regiondata for projections to work */
- if (ELEM(NULL, obedit, ar, ar->regiondata)) {
+ /* edit-object needed for matrix, and region->regiondata for projections to work */
+ if (ELEM(NULL, obedit, region, region->regiondata)) {
return OPERATOR_CANCELLED;
}
@@ -3790,7 +3996,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
RNA_END;
/* for ED_view3d_project_float_object */
- ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
+ ED_view3d_init_mats_rv3d(obedit, region->regiondata);
/* TODO, investigate using index lookup for screen_vert_coords() rather then a hash table */
@@ -3799,7 +4005,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
screen_vert_coords = sco = MEM_mallocN(bm->totvert * sizeof(float) * 2, __func__);
BM_ITER_MESH_INDEX (bv, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (ED_view3d_project_float_object(ar, bv->co, *sco, V3D_PROJ_TEST_CLIP_NEAR) !=
+ if (ED_view3d_project_float_object(region, bv->co, *sco, V3D_PROJ_TEST_CLIP_NEAR) !=
V3D_PROJ_RET_OK) {
copy_v2_fl(*sco, FLT_MAX); /* set error value */
}
@@ -3929,13 +4135,18 @@ static Base *mesh_separate_tagged(
CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE);
- base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, USER_DUP_MESH);
+ /* Take into account user preferences for duplicating actions. */
+ short dupflag = USER_DUP_MESH | (U.dupflag & USER_DUP_ACT);
+ base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, dupflag);
/* normally would call directly after but in this case delay recalc */
/* DAG_relations_tag_update(bmain); */
/* new in 2.5 */
- assign_matarar(bmain, base_new->object, give_matarar(obedit), *give_totcolp(obedit));
+ BKE_object_material_array_assign(bmain,
+ base_new->object,
+ BKE_object_material_array_p(obedit),
+ *BKE_object_material_len_p(obedit));
ED_object_base_select(base_new, BA_SELECT);
@@ -3996,13 +4207,18 @@ static Base *mesh_separate_arrays(Main *bmain,
CustomData_bmesh_init_pool(&bm_new->ldata, faces_len * 3, BM_LOOP);
CustomData_bmesh_init_pool(&bm_new->pdata, faces_len, BM_FACE);
- base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, USER_DUP_MESH);
+ /* Take into account user preferences for duplicating actions. */
+ short dupflag = USER_DUP_MESH | (U.dupflag & USER_DUP_ACT);
+ base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, dupflag);
/* normally would call directly after but in this case delay recalc */
/* DAG_relations_tag_update(bmain); */
/* new in 2.5 */
- assign_matarar(bmain, base_new->object, give_matarar(obedit), *give_totcolp(obedit));
+ BKE_object_material_array_assign(bmain,
+ base_new->object,
+ BKE_object_material_array_p(obedit),
+ *BKE_object_material_len_p(obedit));
ED_object_base_select(base_new, BA_SELECT);
@@ -4046,8 +4262,8 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const
Material ***matarar;
const short *totcolp;
- totcolp = give_totcolp_id(obdata);
- matarar = give_matarar_id(obdata);
+ totcolp = BKE_id_material_len_p(obdata);
+ matarar = BKE_id_material_array_p(obdata);
if ((totcolp && matarar) == 0) {
BLI_assert(0);
@@ -4075,9 +4291,9 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const
ma_obdata = NULL;
}
- BKE_material_clear_id(bmain, obdata);
- BKE_material_resize_object(bmain, ob, 1, true);
- BKE_material_resize_id(bmain, obdata, 1, true);
+ BKE_id_material_clear(bmain, obdata);
+ BKE_object_material_resize(bmain, ob, 1, true);
+ BKE_id_material_resize(bmain, obdata, 1, true);
ob->mat[0] = ma_ob;
id_us_plus((ID *)ma_ob);
@@ -4086,9 +4302,9 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const
id_us_plus((ID *)ma_obdata);
}
else {
- BKE_material_clear_id(bmain, obdata);
- BKE_material_resize_object(bmain, ob, 0, true);
- BKE_material_resize_id(bmain, obdata, 0, true);
+ BKE_id_material_clear(bmain, obdata);
+ BKE_object_material_resize(bmain, ob, 0, true);
+ BKE_id_material_resize(bmain, obdata, 0, true);
}
}
@@ -4321,6 +4537,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
/* delay depsgraph recalc until all objects are duplicated */
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+ ED_outliner_select_sync_from_object_tag(C);
return OPERATOR_FINISHED;
}
@@ -4446,7 +4663,7 @@ void MESH_OT_fill(wmOperatorType *ot)
static bool bm_edge_test_fill_grid_cb(BMEdge *e, void *UNUSED(bm_v))
{
- return BM_elem_flag_test_bool(e, BM_ELEM_TAG);
+ return BM_elem_flag_test_bool(e, BM_ELEM_SELECT);
}
static float edbm_fill_grid_vert_tag_angle(BMVert *v)
@@ -4468,7 +4685,7 @@ static float edbm_fill_grid_vert_tag_angle(BMVert *v)
/**
* non-essential utility function to select 2 open edge loops from a closed loop.
*/
-static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span_calc)
+static bool edbm_fill_grid_prepare(BMesh *bm, int offset, int *span_p, const bool span_calc)
{
/* angle differences below this value are considered 'even'
* in that they shouldn't be used to calculate corners used for the 'span' */
@@ -4476,28 +4693,48 @@ static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span
BMEdge *e;
BMIter iter;
int count;
- int span = *r_span;
+ int span = *span_p;
ListBase eloops = {NULL};
struct BMEdgeLoopStore *el_store;
// LinkData *el_store;
- /* select -> tag */
+ count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_fill_grid_cb, bm);
+ el_store = eloops.first;
+
+ if (count != 1) {
+ /* Let the operator use the selection flags,
+ * most likely failing with an error in this case. */
+ BM_mesh_edgeloops_free(&eloops);
+ return false;
+ }
+
+ /* Only tag edges that are part of a loop. */
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ }
+ const int verts_len = BM_edgeloop_length_get(el_store);
+ const int edges_len = verts_len - (BM_edgeloop_is_closed(el_store) ? 0 : 1);
+ BMEdge **edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
+ BM_edgeloop_edges_get(el_store, edges);
+ for (int i = 0; i < edges_len; i++) {
+ BM_elem_flag_enable(edges[i], BM_ELEM_TAG);
}
- count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_fill_grid_cb, bm);
- el_store = eloops.first;
+ if (span_calc) {
+ span = verts_len / 4;
+ }
+ else {
+ span = min_ii(span, (verts_len / 2) - 1);
+ }
+ offset = mod_i(offset, verts_len);
+
+ if ((count == 1) && ((verts_len & 1) == 0) && (verts_len == edges_len)) {
- if (count == 1 && BM_edgeloop_is_closed(el_store) &&
- (BM_edgeloop_length_get(el_store) & 1) == 0) {
/* be clever! detect 2 edge loops from one closed edge loop */
- const int verts_len = BM_edgeloop_length_get(el_store);
ListBase *verts = BM_edgeloop_verts_get(el_store);
BMVert *v_act = BM_mesh_active_vert_get(bm);
LinkData *v_act_link;
- BMEdge **edges = MEM_mallocN(sizeof(*edges) * verts_len, __func__);
int i;
if (v_act && (v_act_link = BLI_findptr(verts, v_act, offsetof(LinkData, data)))) {
@@ -4528,6 +4765,7 @@ static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span
BLI_listbase_rotate_first(verts, v_act_link);
}
+ /* Run again to update the edge order from the rotated vertex list. */
BM_edgeloop_edges_get(el_store, edges);
if (span_calc) {
@@ -4580,18 +4818,19 @@ static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span
BM_elem_flag_disable(edges[i], BM_ELEM_TAG);
BM_elem_flag_disable(edges[(verts_len / 2) + i], BM_ELEM_TAG);
}
- MEM_freeN(edges);
}
/* else let the bmesh-operator handle it */
BM_mesh_edgeloops_free(&eloops);
+ MEM_freeN(edges);
+
+ *span_p = span;
- *r_span = span;
+ return true;
}
static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
{
- const bool use_prepare = true;
const bool use_interp_simple = RNA_boolean_get(op->ptr, "use_interp_simple");
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -4603,6 +4842,7 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ bool use_prepare = true;
const bool use_smooth = edbm_add_edge_face__smooth_get(em->bm);
const int totedge_orig = em->bm->totedge;
const int totface_orig = em->bm->totface;
@@ -4617,7 +4857,6 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
PropertyRNA *prop_offset = RNA_struct_find_property(op->ptr, "offset");
bool calc_span;
- const int clamp = em->bm->totvertsel;
int span;
int offset;
@@ -4626,19 +4865,18 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
if (((op->flag & OP_IS_INVOKE) || (op->flag & OP_IS_REPEAT_LAST) == 0) &&
RNA_property_is_set(op->ptr, prop_span)) {
span = RNA_property_int_get(op->ptr, prop_span);
- span = min_ii(span, (clamp / 2) - 1);
calc_span = false;
}
else {
- span = clamp / 4;
+ /* Will be overwritten if possible. */
+ span = 0;
calc_span = true;
}
offset = RNA_property_int_get(op->ptr, prop_offset);
- offset = clamp ? mod_i(offset, clamp) : 0;
/* in simple cases, move selection for tags, but also support more advanced cases */
- edbm_fill_grid_prepare(em->bm, offset, &span, calc_span);
+ use_prepare = edbm_fill_grid_prepare(em->bm, offset, &span, calc_span);
RNA_property_int_set(op->ptr, prop_span, span);
}
@@ -5240,7 +5478,7 @@ static int edbm_decimate_exec(bContext *C, wmOperator *op)
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
if (use_vertex_group) {
const MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset);
- weight = defvert_find_weight(dv, defbase_act);
+ weight = BKE_defvert_find_weight(dv, defbase_act);
if (invert_vertex_group) {
weight = 1.0f - weight;
}
@@ -6011,7 +6249,7 @@ static void sort_bmelem_flag(bContext *C,
const int flag,
const int action,
const int reverse,
- const unsigned int seed)
+ const uint seed)
{
BMEditMesh *em = BKE_editmesh_from_object(ob);
@@ -6024,7 +6262,7 @@ static void sort_bmelem_flag(bContext *C,
/* Just to mark protected elements. */
char *pblock[3] = {NULL, NULL, NULL}, *pb;
BMElemSort *sblock[3] = {NULL, NULL, NULL}, *sb;
- unsigned int *map[3] = {NULL, NULL, NULL}, *mp;
+ uint *map[3] = {NULL, NULL, NULL}, *mp;
int totelem[3] = {0, 0, 0};
int affected[3] = {0, 0, 0};
int i, j;
@@ -6201,7 +6439,7 @@ static void sort_bmelem_flag(bContext *C,
}
else if (action == SRT_SELECTED) {
- unsigned int *tbuf[3] = {NULL, NULL, NULL}, *tb;
+ uint *tbuf[3] = {NULL, NULL, NULL}, *tb;
if (totelem[0]) {
tb = tbuf[0] = MEM_callocN(sizeof(int) * totelem[0], "sort_bmelem vert tbuf");
@@ -6465,7 +6703,7 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op)
const int action = RNA_enum_get(op->ptr, "type");
PropertyRNA *prop_elem_types = RNA_struct_find_property(op->ptr, "elements");
const bool use_reverse = RNA_boolean_get(op->ptr, "reverse");
- unsigned int seed = RNA_int_get(op->ptr, "seed");
+ uint seed = RNA_int_get(op->ptr, "seed");
int elem_types = 0;
if (ELEM(action, SRT_VIEW_ZAXIS, SRT_VIEW_XAXIS)) {
@@ -6975,37 +7213,17 @@ void MESH_OT_wireframe(wmOperatorType *ot)
static int edbm_offset_edgeloop_exec(bContext *C, wmOperator *op)
{
- bool mode_change = false;
const bool use_cap_endpoint = RNA_boolean_get(op->ptr, "use_cap_endpoint");
- int ret = OPERATOR_CANCELLED;
-
- {
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->selectmode == SCE_SELECT_FACE) {
- EDBM_selectmode_to_scene(C);
- mode_change = true;
- }
- }
-
+ bool changed_multi = false;
+ Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
- view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &bases_len);
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- /** If in face-only select mode, switch to edge select mode so that
- * an edge-only selection is not inconsistent state.
- *
- * We need to run this for all objects, even when nothing is selected.
- * This way we keep them in sync. */
- if (mode_change) {
- em->selectmode = SCE_SELECT_EDGE;
- EDBM_selectmode_set(em);
- }
-
if (em->bm->totedgesel == 0) {
continue;
}
@@ -7025,16 +7243,26 @@ static int edbm_offset_edgeloop_exec(bContext *C, wmOperator *op)
BMO_slot_buffer_hflag_enable(
em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
- else {
+ if (EDBM_op_finish(em, &bmop, op, true)) {
EDBM_update_generic(obedit->data, true, true);
- ret = OPERATOR_FINISHED;
+ changed_multi = true;
}
}
- MEM_freeN(objects);
- return ret;
+
+ if (changed_multi) {
+ /** If in face-only select mode, switch to edge select mode so that
+ * an edge-only selection is not inconsistent state.
+ *
+ * We need to run this for all objects, even when nothing is selected.
+ * This way we keep them in sync. */
+ if (scene->toolsettings->selectmode == SCE_SELECT_FACE) {
+ EDBM_selectmode_disable_multi_ex(scene, bases, bases_len, SCE_SELECT_FACE, SCE_SELECT_EDGE);
+ }
+ }
+
+ MEM_freeN(bases);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void MESH_OT_offset_edge_loops(wmOperatorType *ot)
@@ -7685,14 +7913,14 @@ wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf)
};
static const char *keymap_name = "Custom Normals Modal Map";
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, keymap_name);
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, keymap_name);
/* We only need to add map once */
if (keymap && keymap->modal_items) {
return NULL;
}
- keymap = WM_modalkeymap_add(keyconf, keymap_name, modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, keymap_name, modal_items);
WM_modalkeymap_assign(keymap, "MESH_OT_point_normals");
@@ -7701,7 +7929,11 @@ wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf)
#define CLNORS_VALID_VEC_LEN (1e-4f)
-/********************** 'Point to' Loop Normals **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Loop Normals 'Point To' Operator
+ * \{ */
enum {
EDBM_CLNOR_POINTTO_MODE_COORDINATES = 1,
@@ -7719,7 +7951,7 @@ static EnumPropertyItem clnors_pointto_mode_items[] = {
};
/* Initialize loop normal data */
-static int point_normals_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static bool point_normals_init(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -7731,14 +7963,29 @@ static int point_normals_init(bContext *C, wmOperator *op, const wmEvent *UNUSED
op->customdata = lnors_ed_arr;
- return lnors_ed_arr->totloop;
+ return (lnors_ed_arr->totloop != 0);
}
-static void point_normals_free(bContext *C, wmOperator *op)
+static bool point_normals_ensure(bContext *C, wmOperator *op)
{
- BMLoopNorEditDataArray *lnors_ed_arr = op->customdata;
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- op->customdata = NULL;
+ if (op->customdata != NULL) {
+ return true;
+ }
+ return point_normals_init(C, op);
+}
+
+static void point_normals_free(wmOperator *op)
+{
+ if (op->customdata != NULL) {
+ BMLoopNorEditDataArray *lnors_ed_arr = op->customdata;
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ op->customdata = NULL;
+ }
+}
+
+static void point_normals_cancel(bContext *C, wmOperator *op)
+{
+ point_normals_free(op);
ED_area_status_text(CTX_wm_area(C), NULL);
}
@@ -7855,6 +8102,13 @@ static void point_normals_apply(bContext *C, wmOperator *op, float target[3], co
static int edbm_point_normals_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ /* As this operator passes events through, we can't be sure the user didn't exit edit-mode.
+ * or performed some other operation. */
+ if (!WM_operator_poll(C, op->type)) {
+ point_normals_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
@@ -8010,12 +8264,12 @@ static int edbm_point_normals_modal(bContext *C, wmOperator *op, const wmEvent *
/* Only handle mousemove event in case we are in mouse mode. */
if (event->type == MOUSEMOVE || force_mousemove) {
if (mode == EDBM_CLNOR_POINTTO_MODE_MOUSE) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float center[3];
bmesh_selected_verts_center_calc(bm, center);
- ED_view3d_win_to_3d_int(v3d, ar, center, event->mval, target);
+ ED_view3d_win_to_3d_int(v3d, region, center, event->mval, target);
ret = OPERATOR_RUNNING_MODAL;
}
@@ -8025,23 +8279,37 @@ static int edbm_point_normals_modal(bContext *C, wmOperator *op, const wmEvent *
if (!ELEM(ret, OPERATOR_CANCELLED, OPERATOR_FINISHED)) {
RNA_property_float_set_array(op->ptr, prop_target, target);
}
- point_normals_apply(C, op, target, do_reset);
- EDBM_update_generic(obedit->data, true, false); /* Recheck bools. */
- point_normals_update_header(C, op);
+ if (point_normals_ensure(C, op)) {
+ point_normals_apply(C, op, target, do_reset);
+ EDBM_update_generic(obedit->data, true, false); /* Recheck bools. */
+ point_normals_update_header(C, op);
+ }
+ else {
+ ret = OPERATOR_CANCELLED;
+ }
}
if (ELEM(ret, OPERATOR_CANCELLED, OPERATOR_FINISHED)) {
- point_normals_free(C, op);
+ point_normals_cancel(C, op);
}
+ /* If we allow other tools to run, we can't be sure if they will re-allocate
+ * the data this operator uses, see: T68159.
+ * Free the data here, then use #point_normals_ensure to add it back on demand. */
+ if (ret == OPERATOR_PASS_THROUGH) {
+ /* Don't free on mouse-move, causes creation/freeing of the loop data in an inefficient way. */
+ if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ point_normals_free(op);
+ }
+ }
return ret;
}
-static int edbm_point_normals_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int edbm_point_normals_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (!point_normals_init(C, op, event)) {
- point_normals_free(C, op);
+ if (!point_normals_init(C, op)) {
+ point_normals_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -8058,8 +8326,8 @@ static int edbm_point_normals_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
- if (!point_normals_init(C, op, NULL)) {
- point_normals_free(C, op);
+ if (!point_normals_init(C, op)) {
+ point_normals_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -8072,7 +8340,7 @@ static int edbm_point_normals_exec(bContext *C, wmOperator *op)
point_normals_apply(C, op, target, false);
EDBM_update_generic(obedit->data, true, false);
- point_normals_free(C, op);
+ point_normals_cancel(C, op);
return OPERATOR_FINISHED;
}
@@ -8117,7 +8385,7 @@ void MESH_OT_point_normals(struct wmOperatorType *ot)
ot->modal = edbm_point_normals_modal;
ot->poll = ED_operator_editmesh;
ot->ui = edbm_point_normals_ui;
- ot->cancel = point_normals_free;
+ ot->cancel = point_normals_cancel;
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -8162,7 +8430,7 @@ void MESH_OT_point_normals(struct wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Split/Merge Loop Normals
+/** \name Split/Merge Loop Normals Operator
* \{ */
static void normals_merge(BMesh *bm, BMLoopNorEditDataArray *lnors_ed_arr)
@@ -8176,6 +8444,8 @@ static void normals_merge(BMesh *bm, BMLoopNorEditDataArray *lnors_ed_arr)
BM_normals_loops_edges_tag(bm, false);
for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ BLI_assert(BLI_SMALLSTACK_IS_EMPTY(clnors));
+
if (BM_elem_flag_test(lnor_ed->loop, BM_ELEM_TAG)) {
continue;
}
@@ -8218,8 +8488,12 @@ static void normals_split(BMesh *bm)
BM_normals_loops_edges_tag(bm, true);
+ BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+
const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
+
l_curr = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) &&
@@ -8241,7 +8515,6 @@ static void normals_split(BMesh *bm)
lfan_pivot = l_curr;
e_next = lfan_pivot->e;
- BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
float avg_normal[3] = {0.0f};
while (true) {
@@ -8253,7 +8526,7 @@ static void normals_split(BMesh *bm)
e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
}
- BLI_SMALLSTACK_PUSH(loops, lfan_pivot);
+ BLI_SMALLSTACK_PUSH(loop_stack, lfan_pivot);
add_v3_v3(avg_normal, lfan_pivot->f->no);
if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
@@ -8265,7 +8538,7 @@ static void normals_split(BMesh *bm)
/* If avg normal is nearly 0, set clnor to default value. */
zero_v3(avg_normal);
}
- while ((l = BLI_SMALLSTACK_POP(loops))) {
+ while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
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(
@@ -8373,7 +8646,7 @@ void MESH_OT_split_normals(struct wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Average Loop Normals
+/** \name Average Loop Normals Operator
* \{ */
enum {
@@ -8407,7 +8680,13 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
const float absweight = (float)RNA_int_get(op->ptr, "weight");
const float threshold = RNA_float_get(op->ptr, "threshold");
+ HeapSimple *loop_weight = BLI_heapsimple_new();
+ BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
+ BLI_assert(BLI_heapsimple_is_empty(loop_weight));
+
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -8434,8 +8713,6 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
BM_normals_loops_edges_tag(bm, true);
- HeapSimple *loop_weight = BLI_heapsimple_new();
-
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
l_curr = l_first = BM_FACE_FIRST_LOOP(f);
do {
@@ -8485,7 +8762,6 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
lfan_pivot = lfan_pivot_next;
}
- BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
float wnor[3], avg_normal[3] = {0.0f}, count = 0;
float val = BLI_heapsimple_top_value(loop_weight);
@@ -8496,7 +8772,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
val = cur_val;
}
l = BLI_heapsimple_pop_min(loop_weight);
- BLI_SMALLSTACK_PUSH(loops, l);
+ BLI_SMALLSTACK_PUSH(loop_stack, l);
const float n_weight = pow(weight, count);
@@ -8517,7 +8793,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
/* If avg normal is nearly 0, set clnor to default value. */
zero_v3(avg_normal);
}
- while ((l = BLI_SMALLSTACK_POP(loops))) {
+ while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
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(
@@ -8528,10 +8804,11 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
} while ((l_curr = l_curr->next) != l_first);
}
- BLI_heapsimple_free(loop_weight, NULL);
EDBM_update_generic(obedit->data, true, false);
}
+ BLI_heapsimple_free(loop_weight, NULL);
+
MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8605,7 +8882,7 @@ void MESH_OT_average_normals(struct wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Custom Normal Interface Tools
+/** \name Custom Normal Interface Tools Operator
* \{ */
enum {
@@ -8841,6 +9118,12 @@ void MESH_OT_normals_tools(struct wmOperatorType *ot)
"Copy Absolute coordinates or Normal vector");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Normals from Faces Operator
+ * \{ */
+
static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -8948,7 +9231,13 @@ void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot)
RNA_def_boolean(ot->srna, "keep_sharp", 0, "Keep Sharp Edges", "Do not set sharp edges to face");
}
-static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Smooth Normal Vectors Operator
+ * \{ */
+
+static int edbm_smooth_normals_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
@@ -9001,7 +9290,7 @@ static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op)
float current_normal[3];
if (normalize_v3(smooth_normal[i]) < CLNORS_VALID_VEC_LEN) {
- /* Skip in case smoothen normal is invalid... */
+ /* Skip in case the smooth normal is invalid. */
continue;
}
@@ -9015,7 +9304,7 @@ static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op)
add_v3_v3(current_normal, smooth_normal[i]);
if (normalize_v3(current_normal) < CLNORS_VALID_VEC_LEN) {
- /* Skip in case smoothen normal is invalid... */
+ /* Skip in case the smoothed normal is invalid. */
continue;
}
@@ -9033,15 +9322,15 @@ static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void MESH_OT_smoothen_normals(struct wmOperatorType *ot)
+void MESH_OT_smooth_normals(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "Smooth Normals Vectors";
- ot->description = "Smoothen custom normals based on adjacent vertex normals";
- ot->idname = "MESH_OT_smoothen_normals";
+ ot->description = "Smooth custom normals based on adjacent vertex normals";
+ ot->idname = "MESH_OT_smooth_normals";
/* api callbacks */
- ot->exec = edbm_smoothen_normals_exec;
+ ot->exec = edbm_smooth_normals_exec;
ot->poll = ED_operator_editmesh;
/* flags */
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index faa80341b0f..e4ecfa9c680 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -22,32 +22,32 @@
#include "CLG_log.h"
+#include "DNA_key_types.h"
+#include "DNA_layer_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "DNA_key_types.h"
-#include "DNA_layer_types.h"
-#include "BLI_listbase.h"
#include "BLI_array_utils.h"
+#include "BLI_listbase.h"
#include "BKE_context.h"
+#include "BKE_editmesh.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
-#include "BKE_editmesh.h"
#include "BKE_undo_system.h"
#include "DEG_depsgraph.h"
-#include "ED_object.h"
#include "ED_mesh.h"
-#include "ED_util.h"
+#include "ED_object.h"
#include "ED_undo.h"
+#include "ED_util.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#define USE_ARRAY_STORE
@@ -397,9 +397,7 @@ struct UMArrayData {
UndoMesh *um;
const UndoMesh *um_ref; /* can be NULL */
};
-static void um_arraystore_compact_cb(TaskPool *__restrict UNUSED(pool),
- void *taskdata,
- int UNUSED(threadid))
+static void um_arraystore_compact_cb(TaskPool *__restrict UNUSED(pool), void *taskdata)
{
struct UMArrayData *um_data = taskdata;
um_arraystore_compact_with_info(um_data->um, um_data->um_ref);
@@ -541,16 +539,14 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key)
# ifdef USE_ARRAY_STORE_THREAD
if (um_arraystore.task_pool == NULL) {
- TaskScheduler *scheduler = BLI_task_scheduler_get();
- um_arraystore.task_pool = BLI_task_pool_create_background(scheduler, NULL);
+ um_arraystore.task_pool = BLI_task_pool_create_background(NULL, TASK_PRIORITY_LOW);
}
struct UMArrayData *um_data = MEM_mallocN(sizeof(*um_data), __func__);
um_data->um = um;
um_data->um_ref = um_ref;
- BLI_task_pool_push(
- um_arraystore.task_pool, um_arraystore_compact_cb, um_data, true, TASK_PRIORITY_LOW);
+ BLI_task_pool_push(um_arraystore.task_pool, um_arraystore_compact_cb, um_data, true, NULL);
# else
um_arraystore_compact_with_info(um, um_ref);
# endif
@@ -672,7 +668,8 @@ static void undomesh_free_data(UndoMesh *um)
static Object *editmesh_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
if (obedit && obedit->type == OB_MESH) {
Mesh *me = obedit->data;
if (me->edit_mesh != NULL) {
@@ -715,8 +712,7 @@ static bool mesh_undosys_step_encode(struct bContext *C, struct Main *bmain, Und
* outside of this list will be moved out of edit-mode when reading back undo steps. */
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, NULL, &objects_len);
+ Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
us->elems_len = objects_len;
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index f7092a8c6ab..a26003d78ed 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -23,25 +23,25 @@
#include "MEM_guardedalloc.h"
+#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
-#include "DNA_key_types.h"
-#include "BLI_math.h"
#include "BLI_alloca.h"
#include "BLI_buffer.h"
#include "BLI_kdtree.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_bvh.h"
+#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_report.h"
-#include "BKE_editmesh.h"
-#include "BKE_editmesh_bvh.h"
-#include "BKE_global.h"
#include "DEG_depsgraph.h"
@@ -52,6 +52,7 @@
#include "ED_mesh.h"
#include "ED_screen.h"
+#include "ED_transform_snap_object_context.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
@@ -370,8 +371,7 @@ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data)
* cycles.
*/
#if 0
- for (Object *other_object = bmain->objects.first; other_object != NULL;
- other_object = other_object->id.next) {
+ for (Object *other_object = bmain->objects.first; other_object != NULL; other_object = other_object->id.next) {
if (other_object->data == ob->data) {
BKE_object_free_derived_caches(other_object);
}
@@ -406,10 +406,10 @@ void EDBM_mesh_load(Main *bmain, Object *ob)
void EDBM_mesh_free(BMEditMesh *em)
{
/* These tables aren't used yet, so it's not strictly necessary
- * to 'end' them (with 'e' param) but if someone tries to start
- * using them, having these in place will save a lot of pain */
- ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
- ED_mesh_mirror_topo_table(NULL, NULL, 'e');
+ * to 'end' them but if someone tries to start using them,
+ * having these in place will save a lot of pain. */
+ ED_mesh_mirror_spatial_table_end(NULL);
+ ED_mesh_mirror_topo_table_end(NULL);
BKE_editmesh_free(em);
}
@@ -539,7 +539,7 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm,
UvVertMap *vmap;
UvMapVert *buf;
MLoopUV *luv;
- unsigned int a;
+ uint a;
int totverts, i, totuv, totfaces;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
bool *winding = NULL;
@@ -669,7 +669,7 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm,
return vmap;
}
-UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, unsigned int v)
+UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, uint v)
{
return vmap->vert[v];
}
@@ -832,7 +832,7 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
}
if (do_islands) {
- unsigned int *map;
+ uint *map;
BMFace **stack;
int stacksize = 0;
UvElement *islandbuf;
@@ -1079,7 +1079,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
BMVert *v;
int cd_vmirr_offset = 0;
int i;
- const float maxdist_sq = SQUARE(maxdist);
+ const float maxdist_sq = square_f(maxdist);
/* one or the other is used depending if topo is enabled */
KDTree_3d *tree = NULL;
@@ -1224,7 +1224,7 @@ BMFace *EDBM_verts_mirror_get_face(BMEditMesh *em, BMFace *f)
BMVert **v_mirr_arr = BLI_array_alloca(v_mirr_arr, f->len);
BMLoop *l_iter, *l_first;
- unsigned int i = 0;
+ uint i = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
@@ -1577,7 +1577,7 @@ static void scale_point(float c1[3], const float p[3], const float s)
bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
BMEdge *e,
struct Depsgraph *depsgraph,
- ARegion *ar,
+ ARegion *region,
View3D *v3d,
Object *obedit)
{
@@ -1587,11 +1587,11 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
float epsilon = 0.01f;
float end[3];
const float mval_f[2] = {
- ar->winx / 2.0f,
- ar->winy / 2.0f,
+ region->winx / 2.0f,
+ region->winy / 2.0f,
};
- ED_view3d_win_to_segment_clipped(depsgraph, ar, v3d, mval_f, origin, end, false);
+ ED_view3d_win_to_segment_clipped(depsgraph, region, v3d, mval_f, origin, end, false);
invert_m4_m4(invmat, obedit->obmat);
mul_m4_v3(invmat, origin);
@@ -1639,3 +1639,48 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name BMesh Vertex Projection API
+ * \{ */
+
+void EDBM_project_snap_verts(
+ bContext *C, Depsgraph *depsgraph, ARegion *region, Object *obedit, BMEditMesh *em)
+{
+ Main *bmain = CTX_data_main(C);
+ BMIter iter;
+ BMVert *eve;
+
+ ED_view3d_init_mats_rv3d(obedit, region->regiondata);
+
+ struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
+ bmain, CTX_data_scene(C), 0, region, CTX_wm_view3d(C));
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ float mval[2], co_proj[3];
+ if (ED_view3d_project_float_object(region, eve->co, mval, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK) {
+ if (ED_transform_snap_object_project_view3d(snap_context,
+ depsgraph,
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_NOT_ACTIVE,
+ .use_object_edit_cage = false,
+ .use_occlusion_test = true,
+ },
+ mval,
+ NULL,
+ NULL,
+ co_proj,
+ NULL)) {
+ mul_v3_m4v3(eve->co, obedit->imat, co_proj);
+ }
+ }
+ }
+ }
+
+ ED_transform_snap_object_context_destroy(snap_context);
+}
+
+/** \} */
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 7007ff29401..51b699acd63 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -29,9 +29,9 @@
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
-#include "BLI_utildefines.h"
#include "BLI_alloca.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 9125925c5d3..c9f841a059f 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -248,7 +248,7 @@ void MESH_OT_split_normals(struct wmOperatorType *ot);
void MESH_OT_normals_tools(struct wmOperatorType *ot);
void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot);
void MESH_OT_average_normals(struct wmOperatorType *ot);
-void MESH_OT_smoothen_normals(struct wmOperatorType *ot);
+void MESH_OT_smooth_normals(struct wmOperatorType *ot);
void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot);
/* *** editmesh_mask_extract.c *** */
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
index 628c8273bc5..0bbc8b0df76 100644
--- a/source/blender/editors/mesh/mesh_mirror.c
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -29,8 +29,8 @@
#include "DNA_object_types.h"
#include "BKE_editmesh.h"
-#include "BLI_kdtree.h"
#include "BKE_mesh.h"
+#include "BLI_kdtree.h"
#include "ED_mesh.h"
@@ -44,73 +44,71 @@ static struct {
void *tree;
} MirrKdStore = {NULL};
-/* mode is 's' start, or 'e' end, or 'u' use */
-/* if end, ob can be NULL */
-int ED_mesh_mirror_spatial_table(
- Object *ob, BMEditMesh *em, Mesh *me_eval, const float co[3], char mode)
+void ED_mesh_mirror_spatial_table_begin(Object *ob, BMEditMesh *em, Mesh *me_eval)
{
- if (mode == 'u') { /* use table */
- if (MirrKdStore.tree == NULL) {
- ED_mesh_mirror_spatial_table(ob, em, me_eval, NULL, 's');
- }
-
- if (MirrKdStore.tree) {
- KDTreeNearest_3d nearest;
- const int i = BLI_kdtree_3d_find_nearest(MirrKdStore.tree, co, &nearest);
+ Mesh *me = ob->data;
+ const bool use_em = (!me_eval && em && me->edit_mesh == em);
+ const int totvert = use_em ? em->bm->totvert : me_eval ? me_eval->totvert : me->totvert;
- if (i != -1) {
- if (nearest.dist < KD_THRESH) {
- return i;
- }
- }
- }
- return -1;
+ if (MirrKdStore.tree) { /* happens when entering this call without ending it */
+ ED_mesh_mirror_spatial_table_end(ob);
}
- else if (mode == 's') { /* start table */
- Mesh *me = ob->data;
- const bool use_em = (!me_eval && em && me->edit_mesh == em);
- const int totvert = use_em ? em->bm->totvert : me_eval ? me_eval->totvert : me->totvert;
- if (MirrKdStore.tree) { /* happens when entering this call without ending it */
- ED_mesh_mirror_spatial_table(ob, em, me_eval, co, 'e');
- }
-
- MirrKdStore.tree = BLI_kdtree_3d_new(totvert);
+ MirrKdStore.tree = BLI_kdtree_3d_new(totvert);
- if (use_em) {
- BMVert *eve;
- BMIter iter;
- int i;
+ if (use_em) {
+ BMVert *eve;
+ BMIter iter;
+ int i;
- /* this needs to be valid for index lookups later (callers need) */
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ /* this needs to be valid for index lookups later (callers need) */
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- BLI_kdtree_3d_insert(MirrKdStore.tree, i, eve->co);
- }
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ BLI_kdtree_3d_insert(MirrKdStore.tree, i, eve->co);
}
- else {
- MVert *mvert = me_eval ? me_eval->mvert : me->mvert;
- int i;
+ }
+ else {
+ MVert *mvert = me_eval ? me_eval->mvert : me->mvert;
+ int i;
- for (i = 0; i < totvert; i++, mvert++) {
- BLI_kdtree_3d_insert(MirrKdStore.tree, i, mvert->co);
- }
+ for (i = 0; i < totvert; i++, mvert++) {
+ BLI_kdtree_3d_insert(MirrKdStore.tree, i, mvert->co);
}
+ }
+
+ BLI_kdtree_3d_balance(MirrKdStore.tree);
+}
- BLI_kdtree_3d_balance(MirrKdStore.tree);
+int ED_mesh_mirror_spatial_table_lookup(Object *ob,
+ BMEditMesh *em,
+ Mesh *me_eval,
+ const float co[3])
+{
+ if (MirrKdStore.tree == NULL) {
+ ED_mesh_mirror_spatial_table_begin(ob, em, me_eval);
}
- else if (mode == 'e') { /* end table */
- if (MirrKdStore.tree) {
- BLI_kdtree_3d_free(MirrKdStore.tree);
- MirrKdStore.tree = NULL;
+
+ if (MirrKdStore.tree) {
+ KDTreeNearest_3d nearest;
+ const int i = BLI_kdtree_3d_find_nearest(MirrKdStore.tree, co, &nearest);
+
+ if (i != -1) {
+ if (nearest.dist < KD_THRESH) {
+ return i;
+ }
}
}
- else {
- BLI_assert(0);
- }
+ return -1;
+}
- return 0;
+void ED_mesh_mirror_spatial_table_end(Object *UNUSED(ob))
+{
+ /* TODO: store this in object/object-data (keep unused argument for now). */
+ if (MirrKdStore.tree) {
+ BLI_kdtree_3d_free(MirrKdStore.tree);
+ MirrKdStore.tree = NULL;
+ }
}
/** \} */
@@ -119,7 +117,7 @@ int ED_mesh_mirror_spatial_table(
/** \name Mesh Topology Mirror API
* \{ */
-typedef unsigned int MirrTopoHash_t;
+typedef uint MirrTopoHash_t;
typedef struct MirrTopoVert_t {
MirrTopoHash_t hash;
@@ -231,7 +229,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
medge = me->medge;
for (a = 0, med = medge; a < totedge; a++, med++) {
- const unsigned int i1 = med->v1, i2 = med->v2;
+ const uint i1 = med->v1, i2 = med->v2;
topo_hash[i1]++;
topo_hash[i2]++;
}
@@ -257,7 +255,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
}
else {
for (a = 0, med = medge; a < totedge; a++, med++) {
- const unsigned int i1 = med->v1, i2 = med->v2;
+ const uint i1 = med->v1, i2 = med->v2;
topo_hash[i1] += topo_hash_prev[i2] * topo_pass;
topo_hash[i2] += topo_hash_prev[i1] * topo_pass;
tot_unique_edges += (topo_hash[i1] != topo_hash[i2]);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 4c585b35335..adaf146d5b9 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -21,16 +21,16 @@
* \ingroup edmesh
*/
-#include "DNA_scene_types.h"
#include "DNA_modifier_types.h"
+#include "DNA_scene_types.h"
#include "RNA_access.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
@@ -203,7 +203,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_normals_tools);
WM_operatortype_append(MESH_OT_set_normals_from_faces);
WM_operatortype_append(MESH_OT_average_normals);
- WM_operatortype_append(MESH_OT_smoothen_normals);
+ WM_operatortype_append(MESH_OT_smooth_normals);
WM_operatortype_append(MESH_OT_mod_weighted_strength);
}
@@ -277,6 +277,18 @@ void ED_operatormacros_mesh(void)
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
RNA_boolean_set(otmacro->ptr, "mirror", false);
+ ot = WM_operatortype_append_macro(
+ "MESH_OT_extrude_region_dissolve_move_intersect",
+ "Extrude, Dissolve, Move and Intersect",
+ "Extrude, dissolves edges whose faces form a flat surface and intersect new edges",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
+ RNA_boolean_set(otmacro->ptr, "use_dissolve_ortho_edges", true);
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+ RNA_boolean_set(otmacro->ptr, "use_automerge_and_split", true);
+
ot = WM_operatortype_append_macro("MESH_OT_extrude_context_move",
"Extrude Region and Move",
"Extrude region together along the average normal",
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 380d9100ed4..917bbe61e3d 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -37,15 +37,15 @@
#include "DNA_view3d_types.h"
#include "DNA_workspace_types.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_key.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -161,7 +161,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
*/
if (key) {
/* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
- for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
+ LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
/* get pointer to where to write data for this mesh in shapekey's data array */
float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
@@ -191,7 +191,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
* - otherwise, copy across plain coordinates (no need to transform coordinates)
*/
if (key) {
- for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
+ LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
/* get pointer to where to write data for this mesh in shapekey's data array */
float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
@@ -250,7 +250,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
if (matmap) {
/* make mapping for materials */
for (a = 1; a <= ob_src->totcol; a++) {
- Material *ma = give_current_material(ob_src, a);
+ Material *ma = BKE_object_material_get(ob_src, a);
for (b = 0; b < totcol; b++) {
if (ma == matar[b]) {
@@ -314,7 +314,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
int a, b, totcol, totmat = 0, totedge = 0, totvert = 0;
int totloop = 0, totpoly = 0, vertofs, *matmap = NULL;
int i, haskey = 0, edgeofs, loopofs, polyofs;
- bool ok = false;
+ bool ok = false, join_parent = false;
bDeformGroup *dg, *odg;
CustomData vdata, edata, fdata, ldata, pdata;
@@ -346,6 +346,10 @@ int join_mesh_exec(bContext *C, wmOperator *op)
ok = true;
}
+ if ((ob->parent != NULL) && (ob_iter == ob->parent)) {
+ join_parent = true;
+ }
+
/* check for shapekeys */
if (me->key) {
haskey++;
@@ -354,6 +358,13 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ /* Apply parent transform if the active object's parent was joined to it.
+ * Note: This doesn't apply recursive parenting. */
+ if (join_parent) {
+ ob->parent = NULL;
+ BKE_object_apply_mat4_ex(ob, ob->obmat, ob->parent, ob->parentinv, false);
+ }
+
/* that way the active object is always selected */
if (ok == false) {
BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh");
@@ -391,7 +402,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* obact materials in new main array, is nicer start! */
for (a = 0; a < ob->totcol; a++) {
- matar[a] = give_current_material(ob, a + 1);
+ matar[a] = BKE_object_material_get(ob, a + 1);
id_us_plus((ID *)matar[a]);
/* increase id->us : will be lowered later */
}
@@ -429,8 +440,8 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* Join this object's vertex groups to the base one's */
for (dg = ob_iter->defbase.first; dg; dg = dg->next) {
/* See if this group exists in the object (if it doesn't, add it to the end) */
- if (!defgroup_find_name(ob, dg->name)) {
- odg = MEM_callocN(sizeof(bDeformGroup), "join deformGroup");
+ if (!BKE_object_defgroup_find_name(ob, dg->name)) {
+ odg = MEM_mallocN(sizeof(bDeformGroup), "join deformGroup");
memcpy(odg, dg, sizeof(bDeformGroup));
BLI_addtail(&ob->defbase, odg);
}
@@ -440,10 +451,10 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
/* Join this object's face maps to the base one's. */
- for (bFaceMap *fmap = ob_iter->fmaps.first; fmap; fmap = fmap->next) {
+ LISTBASE_FOREACH (bFaceMap *, fmap, &ob_iter->fmaps) {
/* See if this group exists in the object (if it doesn't, add it to the end) */
if (BKE_object_facemap_find_name(ob, fmap->name) == NULL) {
- bFaceMap *fmap_new = MEM_callocN(sizeof(bFaceMap), "join faceMap");
+ bFaceMap *fmap_new = MEM_mallocN(sizeof(bFaceMap), "join faceMap");
memcpy(fmap_new, fmap, sizeof(bFaceMap));
BLI_addtail(&ob->fmaps, fmap_new);
}
@@ -457,7 +468,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
* (but only if limits not exceeded yet) */
if (totcol < MAXMAT) {
for (a = 1; a <= ob_iter->totcol; a++) {
- ma = give_current_material(ob_iter, a);
+ ma = BKE_object_material_get(ob_iter, a);
for (b = 0; b < totcol; b++) {
if (ma == matar[b]) {
@@ -669,7 +680,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
ob->totcol = me->totcol = totcol;
/* other mesh users */
- test_all_objects_materials(bmain, (ID *)me);
+ BKE_objects_materials_test_all(bmain, (ID *)me);
/* free temp copy of destination shapekeys (if applicable) */
if (nkey) {
@@ -786,62 +797,73 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
}
/* -------------------------------------------------------------------- */
-/* Mesh Mirror (Topology) */
-
/** \name Mesh Topology Mirror API
* \{ */
static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
+BLI_INLINE void mesh_mirror_topo_table_get_meshes(Object *ob,
+ Mesh *me_eval,
+ Mesh **r_me_mirror,
+ BMEditMesh **r_em_mirror)
+{
+ Mesh *me_mirror = NULL;
+ BMEditMesh *em_mirror = NULL;
+
+ Mesh *me = ob->data;
+ if (me_eval != NULL) {
+ me_mirror = me_eval;
+ }
+ else if (me->edit_mesh != NULL) {
+ em_mirror = me->edit_mesh;
+ }
+ else {
+ me_mirror = me;
+ }
+
+ *r_me_mirror = me_mirror;
+ *r_em_mirror = em_mirror;
+}
+
/**
* Mode is 's' start, or 'e' end, or 'u' use
* if end, ob can be NULL.
* \note This is supposed return -1 on error,
* which callers are currently checking for, but is not used so far.
*/
-int ED_mesh_mirror_topo_table(Object *ob, Mesh *me_eval, char mode)
+void ED_mesh_mirror_topo_table_begin(Object *ob, Mesh *me_eval)
{
+ Mesh *me_mirror;
+ BMEditMesh *em_mirror;
+ mesh_mirror_topo_table_get_meshes(ob, me_eval, &me_mirror, &em_mirror);
- Mesh *me_mirror = NULL;
- BMEditMesh *em_mirror = NULL;
+ ED_mesh_mirrtopo_init(em_mirror, me_mirror, &mesh_topo_store, false);
+}
- if (mode != 'e') {
- Mesh *me = ob->data;
- if (me_eval != NULL) {
- me_mirror = me_eval;
- }
- else if (me->edit_mesh != NULL) {
- em_mirror = me->edit_mesh;
- }
- else {
- me_mirror = me;
- }
- }
+void ED_mesh_mirror_topo_table_end(Object *UNUSED(ob))
+{
+ /* TODO: store this in object/object-data (keep unused argument for now). */
+ ED_mesh_mirrtopo_free(&mesh_topo_store);
+}
- if (mode == 'u') { /* use table */
- if (ED_mesh_mirrtopo_recalc_check(em_mirror, me_mirror, &mesh_topo_store)) {
- ED_mesh_mirror_topo_table(ob, me_eval, 's');
- }
- }
- else if (mode == 's') { /* start table */
- ED_mesh_mirrtopo_init(em_mirror, me_mirror, &mesh_topo_store, false);
- }
- else if (mode == 'e') { /* end table */
- ED_mesh_mirrtopo_free(&mesh_topo_store);
- }
- else {
- BLI_assert(0);
- }
+static int ed_mesh_mirror_topo_table_update(Object *ob, Mesh *me_eval)
+{
+ Mesh *me_mirror;
+ BMEditMesh *em_mirror;
+ mesh_mirror_topo_table_get_meshes(ob, me_eval, &me_mirror, &em_mirror);
+ if (ED_mesh_mirrtopo_recalc_check(em_mirror, me_mirror, &mesh_topo_store)) {
+ ED_mesh_mirror_topo_table_begin(ob, me_eval);
+ }
return 0;
}
/** \} */
-static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *mesh, int index)
+static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *me_eval, int index)
{
Mesh *me = ob->data;
- MVert *mvert = mesh ? mesh->mvert : me->mvert;
+ MVert *mvert = me_eval ? me_eval->mvert : me->mvert;
float vec[3];
mvert = &mvert[index];
@@ -849,12 +871,12 @@ static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *mesh, int index)
vec[1] = mvert->co[1];
vec[2] = mvert->co[2];
- return ED_mesh_mirror_spatial_table(ob, NULL, mesh, vec, 'u');
+ return ED_mesh_mirror_spatial_table_lookup(ob, NULL, me_eval, vec);
}
static int mesh_get_x_mirror_vert_topo(Object *ob, Mesh *mesh, int index)
{
- if (ED_mesh_mirror_topo_table(ob, mesh, 'u') == -1) {
+ if (ed_mesh_mirror_topo_table_update(ob, mesh) == -1) {
return -1;
}
@@ -885,7 +907,7 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
vec[1] = co[1];
vec[2] = co[2];
- i = ED_mesh_mirror_spatial_table(ob, em, NULL, vec, 'u');
+ i = ED_mesh_mirror_spatial_table_lookup(ob, em, NULL, vec);
if (i != -1) {
return BM_vert_at_index(em->bm, i);
}
@@ -898,7 +920,7 @@ static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob,
int index)
{
intptr_t poinval;
- if (ED_mesh_mirror_topo_table(ob, NULL, 'u') == -1) {
+ if (ed_mesh_mirror_topo_table_update(ob, NULL) == -1) {
return NULL;
}
@@ -943,7 +965,7 @@ BMVert *editbmesh_get_x_mirror_vert(Object *ob,
}
/**
- * Wrapper for objectmode/editmode.
+ * Wrapper for object-mode/edit-mode.
*
* call #BM_mesh_elem_table_ensure first for editmesh.
*/
@@ -1023,10 +1045,10 @@ static float *editmesh_get_mirror_uv(
#endif
-static unsigned int mirror_facehash(const void *ptr)
+static uint mirror_facehash(const void *ptr)
{
const MFace *mf = ptr;
- unsigned int v0, v1;
+ uint v0, v1;
if (mf->v4) {
v0 = MIN4(mf->v1, mf->v2, mf->v3, mf->v4);
@@ -1098,13 +1120,13 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
mvert = me_eval ? me_eval->mvert : me->mvert;
mface = me_eval ? me_eval->mface : me->mface;
- ED_mesh_mirror_spatial_table(ob, em, me_eval, NULL, 's');
+ ED_mesh_mirror_spatial_table_begin(ob, em, me_eval);
for (a = 0, mv = mvert; a < totvert; a++, mv++) {
mirrorverts[a] = mesh_get_x_mirror_vert(ob, me_eval, a, use_topology);
}
- ED_mesh_mirror_spatial_table(ob, em, me_eval, NULL, 'e');
+ ED_mesh_mirror_spatial_table_end(ob);
fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
for (a = 0, mf = mface; a < totface; a++, mf++) {
@@ -1119,8 +1141,8 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
/* make sure v4 is not 0 if a quad */
if (mf->v4 && mirrormf.v4 == 0) {
- SWAP(unsigned int, mirrormf.v1, mirrormf.v3);
- SWAP(unsigned int, mirrormf.v2, mirrormf.v4);
+ SWAP(uint, mirrormf.v1, mirrormf.v3);
+ SWAP(uint, mirrormf.v2, mirrormf.v4);
}
hashmf = BLI_ghash_lookup(fhash, &mirrormf);
@@ -1167,14 +1189,14 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px,
/* sample rect to increase chances of selecting, so that when clicking
* on an edge in the backbuf, we can still select a face */
*r_index = DRW_select_buffer_find_nearest_to_point(
- vc.depsgraph, vc.ar, vc.v3d, mval, 1, me->totpoly + 1, &dist_px);
+ vc.depsgraph, vc.region, vc.v3d, mval, 1, me->totpoly + 1, &dist_px);
}
else {
/* sample only on the exact position */
- *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.ar, vc.v3d, mval);
+ *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.region, vc.v3d, mval);
}
- if ((*r_index) == 0 || (*r_index) > (unsigned int)me->totpoly) {
+ if ((*r_index) == 0 || (*r_index) > (uint)me->totpoly) {
return false;
}
@@ -1185,7 +1207,7 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px,
static void ed_mesh_pick_face_vert__mpoly_find(
/* context */
- struct ARegion *ar,
+ struct ARegion *region,
const float mval[2],
/* mesh data (evaluated) */
const MPoly *mp,
@@ -1201,7 +1223,7 @@ static void ed_mesh_pick_face_vert__mpoly_find(
float sco[2];
const int v_idx = ml->v;
const float *co = mvert[v_idx].co;
- if (ED_view3d_project_float_object(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(region, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
const float len_test = len_manhattan_v2v2(mval, sco);
if (len_test < *r_len_best) {
*r_len_best = len_test;
@@ -1218,7 +1240,7 @@ bool ED_mesh_pick_face_vert(
bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- unsigned int poly_index;
+ uint poly_index;
Mesh *me = ob->data;
BLI_assert(me && GS(me->id.name) == ID_ME);
@@ -1226,7 +1248,7 @@ bool ED_mesh_pick_face_vert(
if (ED_mesh_pick_face(C, ob, mval, dist_px, &poly_index)) {
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- struct ARegion *ar = CTX_wm_region(C);
+ struct ARegion *region = CTX_wm_region(C);
/* derived mesh to find deformed locations */
Mesh *me_eval = mesh_get_eval_final(
@@ -1241,7 +1263,7 @@ bool ED_mesh_pick_face_vert(
MPoly *me_eval_mpoly;
MLoop *me_eval_mloop;
MVert *me_eval_mvert;
- unsigned int me_eval_mpoly_len;
+ uint me_eval_mpoly_len;
const int *index_mp_to_orig;
me_eval_mpoly = me_eval->mpoly;
@@ -1254,18 +1276,23 @@ bool ED_mesh_pick_face_vert(
/* tag all verts using this face */
if (index_mp_to_orig) {
- unsigned int i;
+ uint i;
for (i = 0; i < me_eval_mpoly_len; i++) {
if (index_mp_to_orig[i] == poly_index) {
- ed_mesh_pick_face_vert__mpoly_find(
- ar, mval_f, &me_eval_mpoly[i], me_eval_mvert, me_eval_mloop, &len_best, &v_idx_best);
+ ed_mesh_pick_face_vert__mpoly_find(region,
+ mval_f,
+ &me_eval_mpoly[i],
+ me_eval_mvert,
+ me_eval_mloop,
+ &len_best,
+ &v_idx_best);
}
}
}
else {
if (poly_index < me_eval_mpoly_len) {
- ed_mesh_pick_face_vert__mpoly_find(ar,
+ ed_mesh_pick_face_vert__mpoly_find(region,
mval_f,
&me_eval_mpoly[poly_index],
me_eval_mvert,
@@ -1302,7 +1329,7 @@ bool ED_mesh_pick_face_vert(
typedef struct VertPickData {
const MVert *mvert;
const float *mval_f; /* [2] */
- ARegion *ar;
+ ARegion *region;
/* runtime */
float len_best;
@@ -1319,7 +1346,7 @@ static void ed_mesh_pick_vert__mapFunc(void *userData,
if ((data->mvert[index].flag & ME_HIDE) == 0) {
float sco[2];
- if (ED_view3d_project_float_object(data->ar, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) ==
+ if (ED_view3d_project_float_object(data->region, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) ==
V3D_PROJ_RET_OK) {
const float len = len_manhattan_v2v2(data->mval_f, sco);
if (len < data->len_best) {
@@ -1350,11 +1377,11 @@ bool ED_mesh_pick_vert(
/* sample rect to increase chances of selecting, so that when clicking
* on an face in the backbuf, we can still select a vert */
*r_index = DRW_select_buffer_find_nearest_to_point(
- vc.depsgraph, vc.ar, vc.v3d, mval, 1, me->totvert + 1, &dist_px);
+ vc.depsgraph, vc.region, vc.v3d, mval, 1, me->totvert + 1, &dist_px);
}
else {
/* sample only on the exact position */
- *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.ar, vc.v3d, mval);
+ *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.region, vc.v3d, mval);
}
if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) {
@@ -1369,8 +1396,8 @@ bool ED_mesh_pick_vert(
/* derived mesh to find deformed locations */
Mesh *me_eval = mesh_get_eval_final(vc.depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
- ARegion *ar = vc.ar;
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = vc.region;
+ RegionView3D *rv3d = region->regiondata;
/* find the vert closest to 'mval' */
const float mval_f[2] = {(float)mval[0], (float)mval[1]};
@@ -1385,7 +1412,7 @@ bool ED_mesh_pick_vert(
/* setup data */
data.mvert = me->mvert;
- data.ar = ar;
+ data.region = region;
data.mval_f = mval_f;
data.len_best = FLT_MAX;
data.v_idx_best = -1;
diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c
index e8700e94e91..552e459acb1 100644
--- a/source/blender/editors/metaball/editmball_undo.c
+++ b/source/blender/editors/metaball/editmball_undo.c
@@ -25,9 +25,9 @@
#include "CLG_log.h"
-#include "BLI_utildefines.h"
-#include "BLI_listbase.h"
#include "BLI_array_utils.h"
+#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "DNA_defs.h"
#include "DNA_meta_types.h"
@@ -40,13 +40,13 @@
#include "DEG_depsgraph.h"
-#include "ED_object.h"
#include "ED_mball.h"
+#include "ED_object.h"
#include "ED_undo.h"
#include "ED_util.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
/** We only need this locally. */
static CLG_LogRef LOG = {"ed.undo.mball"};
@@ -120,7 +120,8 @@ static void undomball_free_data(UndoMBall *umb)
static Object *editmball_object_from_context(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
if (obedit && obedit->type == OB_MBALL) {
MetaBall *mb = obedit->data;
if (mb->editelems != NULL) {
@@ -162,8 +163,7 @@ static bool mball_undosys_step_encode(struct bContext *C, struct Main *bmain, Un
* outside of this list will be moved out of edit-mode when reading back undo steps. */
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, NULL, &objects_len);
+ Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
us->elems_len = objects_len;
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 64ae75a0ee8..9386c466f95 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -27,22 +27,22 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_kdtree.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "BLI_kdtree.h"
#include "DNA_defs.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "BKE_context.h"
-#include "BKE_mball.h"
#include "BKE_layer.h"
+#include "BKE_mball.h"
#include "BKE_object.h"
#include "DEG_depsgraph.h"
@@ -456,7 +456,7 @@ static int select_random_metaelems_exec(bContext *C, wmOperator *op)
RNG *rng = BLI_rng_new_srandom(seed_iter);
- for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
+ LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
if (BLI_rng_get_float(rng) < randfac) {
if (select) {
ml->flag |= SELECT;
@@ -656,7 +656,7 @@ static int reveal_metaelems_exec(bContext *C, wmOperator *op)
const bool select = RNA_boolean_get(op->ptr, "select");
bool changed = false;
- for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
+ LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
if (ml->flag & MB_HIDE) {
SET_FLAG_FROM_TEST(ml->flag, select, SELECT);
ml->flag &= ~MB_HIDE;
@@ -697,7 +697,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
static MetaElem *startelem = NULL;
ViewContext vc;
int a, hits;
- unsigned int buffer[MAXPICKBUF];
+ uint buffer[MAXPICKBUF];
rcti rect;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c
index c203ca56d74..100ca4691ca 100644
--- a/source/blender/editors/metaball/mball_ops.c
+++ b/source/blender/editors/metaball/mball_ops.c
@@ -29,9 +29,9 @@
#include "WM_types.h"
#include "ED_mball.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "ED_object.h"
#include "mball_intern.h"
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 69abe475fed..fb273cf49a8 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -17,6 +17,7 @@
set(INC
../include
+ ../../blenfont
../../blenkernel
../../blenlib
../../blentranslation
@@ -33,6 +34,7 @@ set(INC
../../shader_fx
../../render/extern/include
../../windowmanager
+ ../../../../intern/clog
../../../../intern/glew-mx
../../../../intern/guardedalloc
)
@@ -65,6 +67,7 @@ set(SRC
object_transform.c
object_utils.c
object_vgroup.c
+ object_volume.c
object_warp.c
object_intern.h
@@ -88,4 +91,8 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_NEW_OBJECT_TYPES)
+ add_definitions(-DWITH_NEW_OBJECT_TYPES)
+endif()
+
blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index f55a4c7f5f9..74fba4d0cf9 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -21,9 +21,9 @@
* \ingroup edobj
*/
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
#include "MEM_guardedalloc.h"
@@ -31,47 +31,48 @@
#include "DNA_camera_types.h"
#include "DNA_collection_types.h"
#include "DNA_curve_types.h"
-#include "DNA_light_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_key_types.h"
+#include "DNA_light_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_fluidsim_types.h"
#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
-#include "DNA_lightprobe_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
-#include "DNA_gpencil_types.h"
-#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BKE_action.h"
-#include "BKE_anim.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_armature.h"
#include "BKE_camera.h"
#include "BKE_collection.h"
-#include "BKE_context.h"
#include "BKE_constraint.h"
+#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
+#include "BKE_duplilist.h"
#include "BKE_effect.h"
#include "BKE_font.h"
-#include "BKE_gpencil.h"
+#include "BKE_gpencil_curve.h"
+#include "BKE_hair.h"
#include "BKE_key.h"
-#include "BKE_light.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
+#include "BKE_light.h"
#include "BKE_lightprobe.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -81,9 +82,11 @@
#include "BKE_nla.h"
#include "BKE_object.h"
#include "BKE_particle.h"
+#include "BKE_pointcloud.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_speaker.h"
+#include "BKE_volume.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -143,7 +146,7 @@ static const EnumPropertyItem field_type_items[] = {
{PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""},
{PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""},
{PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""},
- {PFIELD_SMOKEFLOW, "SMOKE", ICON_FORCE_SMOKEFLOW, "Smoke Flow", ""},
+ {PFIELD_FLUIDFLOW, "FLUID", ICON_FORCE_FLUIDFLOW, "Fluid Flow", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -410,45 +413,54 @@ bool ED_object_add_generic_get_opts(bContext *C,
rot = _rot;
}
- prop = RNA_struct_find_property(op->ptr, "align");
- int alignment = RNA_property_enum_get(op->ptr, prop);
- bool alignment_set = RNA_property_is_set(op->ptr, prop);
-
if (RNA_struct_property_is_set(op->ptr, "rotation")) {
+ /* If rotation is set, always use it. Alignment (and corresponding user preference)
+ * can be ignored since this is in world space anyways.
+ * To not confuse (e.g. on redo), dont set it to ALIGN_WORLD in the op UI though. */
*is_view_aligned = false;
- RNA_property_enum_set(op->ptr, prop, ALIGN_WORLD);
- alignment = ALIGN_WORLD;
- }
- else if (alignment_set) {
- *is_view_aligned = alignment == ALIGN_VIEW;
+ RNA_float_get_array(op->ptr, "rotation", rot);
}
else {
- *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
- if (*is_view_aligned) {
- RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW);
- alignment = ALIGN_VIEW;
+ int alignment = ALIGN_WORLD;
+ prop = RNA_struct_find_property(op->ptr, "align");
+
+ if (RNA_property_is_set(op->ptr, prop)) {
+ /* If alignment is set, always use it. */
+ *is_view_aligned = alignment == ALIGN_VIEW;
+ alignment = RNA_property_enum_get(op->ptr, prop);
}
- else if (U.flag & USER_ADD_CURSORALIGNED) {
- RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR);
- alignment = ALIGN_CURSOR;
+ else {
+ /* If alignment is not set, use User Preferences. */
+ *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
+ if (*is_view_aligned) {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW);
+ alignment = ALIGN_VIEW;
+ }
+ else if ((U.flag & USER_ADD_CURSORALIGNED) != 0) {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR);
+ alignment = ALIGN_CURSOR;
+ }
+ else {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_WORLD);
+ alignment = ALIGN_WORLD;
+ }
}
- }
-
- switch (alignment) {
- case ALIGN_WORLD:
- RNA_float_get_array(op->ptr, "rotation", rot);
- break;
- case ALIGN_VIEW:
- ED_object_rotation_from_view(C, rot, view_align_axis);
- RNA_float_set_array(op->ptr, "rotation", rot);
- break;
- case ALIGN_CURSOR: {
- const Scene *scene = CTX_data_scene(C);
- float tmat[3][3];
- BKE_scene_cursor_rot_to_mat3(&scene->cursor, tmat);
- mat3_normalized_to_eul(rot, tmat);
- RNA_float_set_array(op->ptr, "rotation", rot);
- break;
+ switch (alignment) {
+ case ALIGN_WORLD:
+ RNA_float_get_array(op->ptr, "rotation", rot);
+ break;
+ case ALIGN_VIEW:
+ ED_object_rotation_from_view(C, rot, view_align_axis);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ break;
+ case ALIGN_CURSOR: {
+ const Scene *scene = CTX_data_scene(C);
+ float tmat[3][3];
+ BKE_scene_cursor_rot_to_mat3(&scene->cursor, tmat);
+ mat3_normalized_to_eul(rot, tmat);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ break;
+ }
}
}
}
@@ -1318,15 +1330,15 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op)
if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
const wmEvent *event = CTX_wm_window(C)->eventstate;
- ARegion *ar = CTX_wm_region(C);
- const int mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+ ARegion *region = CTX_wm_region(C);
+ const int mval[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin};
ED_object_location_from_view(C, loc);
ED_view3d_cursor3d_position(C, mval, false, loc);
RNA_float_set_array(op->ptr, "location", loc);
}
}
else {
- collection = BLI_findlink(&CTX_data_main(C)->collections, RNA_enum_get(op->ptr, "collection"));
+ collection = BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection"));
}
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
@@ -1345,6 +1357,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_add_type(
C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits);
ob->instance_collection = collection;
+ ob->empty_drawsize = U.collection_instance_empty_size;
ob->transflag |= OB_DUPLICOLLECTION;
id_us_plus(&collection->id);
@@ -1450,9 +1463,82 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Delete Object Operator
+/** \name Add Hair Operator
+ * \{ */
+
+static int object_hair_add_exec(bContext *C, wmOperator *op)
+{
+ ushort local_view_bits;
+ float loc[3], rot[3];
+
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ Object *object = ED_object_add_type(C, OB_HAIR, NULL, loc, rot, false, local_view_bits);
+ object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_hair_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Hair";
+ ot->description = "Add a hair object to the scene";
+ ot->idname = "OBJECT_OT_hair_add";
+
+ /* api callbacks */
+ ot->exec = object_hair_add_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, false);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Point Cloud Operator
* \{ */
+static int object_pointcloud_add_exec(bContext *C, wmOperator *op)
+{
+ ushort local_view_bits;
+ float loc[3], rot[3];
+
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ Object *object = ED_object_add_type(C, OB_POINTCLOUD, NULL, loc, rot, false, local_view_bits);
+ object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_pointcloud_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Point Cloud";
+ ot->description = "Add a point cloud object to the scene";
+ ot->idname = "OBJECT_OT_pointcloud_add";
+
+ /* api callbacks */
+ ot->exec = object_pointcloud_add_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, false);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Object Operator
+ * \{ */
/* remove base from a specific scene */
/* note: now unlinks constraints as well */
void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
@@ -1528,7 +1614,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
* Will also remove parent from grease pencil from other scenes,
* even when use_global is false... */
for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->parent != NULL) {
if (gpl->parent == ob) {
gpl->parent = NULL;
@@ -1653,10 +1739,10 @@ static void copy_object_set_idnew(bContext *C)
* 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_hash(const void *ptr)
+static uint dupliobject_hash(const void *ptr)
{
const DupliObject *dob = ptr;
- unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
+ uint hash = BLI_ghashutil_ptrhash(dob->ob);
if (dob->type == OB_DUPLICOLLECTION) {
for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
@@ -1675,10 +1761,10 @@ static unsigned int dupliobject_hash(const void *ptr)
* 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_instancer_hash(const void *ptr)
+static uint dupliobject_instancer_hash(const void *ptr)
{
const DupliObject *dob = ptr;
- unsigned int hash = BLI_ghashutil_inthash(dob->persistent_id[0]);
+ uint 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);
}
@@ -1963,6 +2049,7 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE, scene);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ ED_outliner_select_sync_from_object_tag(C);
return OPERATOR_FINISHED;
}
@@ -2170,7 +2257,7 @@ static int convert_exec(bContext *C, wmOperator *op)
* needed since re-evaluating single modifiers causes bugs if they depend
* on other objects data masks too, see: T50950. */
{
- for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ LISTBASE_FOREACH (CollectionPointerLink *, link, &selected_editable_bases) {
Base *base = link->ptr.data;
Object *ob = base->object;
@@ -2197,7 +2284,7 @@ static int convert_exec(bContext *C, wmOperator *op)
scene->customdata_mask = customdata_mask_prev;
}
- for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ LISTBASE_FOREACH (CollectionPointerLink *, link, &selected_editable_bases) {
Object *newob = NULL;
Base *base = link->ptr.data;
Object *ob = base->object;
@@ -2295,13 +2382,8 @@ static int convert_exec(bContext *C, wmOperator *op)
cu = newob->data;
- /* TODO(sergey): Ideally DAG will create nurbs list for a curve data
- * datablock, but for until we've got granular update
- * lets take care by selves.
- */
- /* XXX This may fail/crash, since BKE_vfont_to_curve()
- * accesses evaluated data in some cases (bastien). */
- BKE_vfont_to_curve(newob, FO_EDIT);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_vfont_to_curve_ex(ob_eval, ob_eval->data, FO_EDIT, &cu->nurb, NULL, NULL, NULL, NULL);
newob->type = OB_CURVE;
cu->type = OB_CURVE;
@@ -2378,15 +2460,14 @@ static int convert_exec(bContext *C, wmOperator *op)
else if (target == OB_GPENCIL) {
if (ob->type != OB_CURVE) {
ob->flag &= ~OB_DONE;
- BKE_report(
- op->reports, RPT_ERROR, "Convert Surfaces to Grease Pencil is not supported.");
+ BKE_report(op->reports, RPT_ERROR, "Convert Surfaces to Grease Pencil is not supported");
}
else {
/* Create a new grease pencil object and copy transformations.
* Nurbs Surface are not supported.
*/
ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
- gpencil_ob = ED_gpencil_add_object(C, scene, ob->loc, local_view_bits);
+ gpencil_ob = ED_gpencil_add_object(C, ob->loc, local_view_bits);
copy_v3_v3(gpencil_ob->rot, ob->rot);
copy_v3_v3(gpencil_ob->scale, ob->scale);
BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, false, false, true);
@@ -2443,7 +2524,7 @@ static int convert_exec(bContext *C, wmOperator *op)
/* Ensure new object has consistent material data with its new obdata. */
if (newob) {
- test_object_materials(bmain, newob, newob->data);
+ BKE_object_materials_test(bmain, newob, newob->data);
}
/* tag obdata if it was been changed */
@@ -2459,7 +2540,12 @@ static int convert_exec(bContext *C, wmOperator *op)
}
if (!keep_original && (ob->flag & OB_DONE)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ /* NOTE: Tag transform for update because object parenting to curve with path is handled
+ * differently from all other cases. Converting curve to mesh and mesh to curve will likely
+ * affect the way children are evaluated.
+ * It is not enough to tag only geometry and rely on the curve parenting relations because
+ * this relation is lost when curve is converted to mesh. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */
}
}
@@ -2754,8 +2840,8 @@ static int add_named_exec(bContext *C, wmOperator *op)
basen->object->restrictflag &= ~OB_RESTRICT_VIEWPORT;
if (event) {
- ARegion *ar = CTX_wm_region(C);
- const int mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+ ARegion *region = CTX_wm_region(C);
+ const int mval[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin};
ED_object_location_from_view(C, basen->object->loc);
ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
}
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index bc79521ee9b..baa24ab2f4e 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -25,40 +25,40 @@
#include "MEM_guardedalloc.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_world_types.h"
-#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_blender.h"
+#include "BKE_cdderivedmesh.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_report.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_modifier.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_mesh.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
+#include "RE_multires_bake.h"
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
-#include "RE_multires_bake.h"
#include "PIL_time.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "GPU_draw.h" /* GPU_free_image */
@@ -156,7 +156,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op)
ok = mmd->totlvl > 0;
for (md = (ModifierData *)mmd->modifier.next; md && ok; md = md->next) {
- if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
+ if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) {
ok = false;
}
}
@@ -596,7 +596,7 @@ static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const
/* running render */
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_PASS_THROUGH;
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index acecbc47c28..c31de7f371c 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -23,23 +23,23 @@
#include "MEM_guardedalloc.h"
-#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "BLI_listbase.h"
#include "BLI_fileops.h"
+#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -57,9 +57,9 @@
#include "RE_engine.h"
#include "RE_pipeline.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -116,7 +116,7 @@ typedef struct BakeAPIRender {
short *do_update;
/* for redrawing */
- ScrArea *sa;
+ ScrArea *area;
} BakeAPIRender;
/* callbacks */
@@ -143,7 +143,7 @@ static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
/* running render */
switch (event->type) {
- case ESCKEY: {
+ case EVT_ESCKEY: {
G.is_break = true;
return OPERATOR_RUNNING_MODAL;
}
@@ -161,10 +161,10 @@ static int bake_break(void *UNUSED(rjv))
return 0;
}
-static void bake_update_image(ScrArea *sa, Image *image)
+static void bake_update_image(ScrArea *area, Image *image)
{
- if (sa && sa->spacetype == SPACE_IMAGE) { /* in case the user changed while baking */
- SpaceImage *sima = sa->spacedata.first;
+ if (area && area->spacetype == SPACE_IMAGE) { /* in case the user changed while baking */
+ SpaceImage *sima = area->spacedata.first;
if (sima) {
sima->image = image;
}
@@ -234,7 +234,7 @@ static bool write_internal_bake_pixels(Image *image,
ibuf->x);
}
else {
- IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
+ IMB_buffer_byte_from_float((uchar *)ibuf->rect,
buffer,
ibuf->channels,
ibuf->dither,
@@ -259,7 +259,7 @@ static bool write_internal_bake_pixels(Image *image,
mask_buffer);
}
else {
- IMB_buffer_byte_from_float_mask((unsigned char *)ibuf->rect,
+ IMB_buffer_byte_from_float_mask((uchar *)ibuf->rect,
buffer,
ibuf->channels,
ibuf->dither,
@@ -359,7 +359,7 @@ static bool write_external_bake_pixels(const char *filepath,
buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
}
- IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
+ IMB_buffer_byte_from_float((uchar *)ibuf->rect,
buffer,
ibuf->channels,
ibuf->dither,
@@ -446,7 +446,8 @@ static bool bake_object_check(ViewLayer *view_layer, Object *ob, ReportList *rep
for (i = 0; i < ob->totcol; i++) {
bNodeTree *ntree = NULL;
bNode *node = NULL;
- ED_object_get_active_image(ob, i + 1, &image, NULL, &node, &ntree);
+ const int mat_nr = i + 1;
+ ED_object_get_active_image(ob, mat_nr, &image, NULL, &node, &ntree);
if (image) {
ImBuf *ibuf;
@@ -481,7 +482,7 @@ static bool bake_object_check(ViewLayer *view_layer, Object *ob, ReportList *rep
}
}
else {
- Material *mat = give_current_material(ob, i);
+ Material *mat = BKE_object_material_get(ob, mat_nr);
if (mat != NULL) {
BKE_reportf(reports,
RPT_INFO,
@@ -743,7 +744,7 @@ static int bake(Render *re,
const int width,
const int height,
const char *identifier,
- ScrArea *sa,
+ ScrArea *area,
const char *uv_layer)
{
/* We build a depsgraph for the baking,
@@ -894,7 +895,7 @@ static int bake(Render *re,
/* for multires bake, use linear UV subdivision to match low res UVs */
if (pass_type == SCE_PASS_NORMAL && normal_space == R_BAKE_SPACE_TANGENT &&
!is_selected_to_active) {
- mmd_low = (MultiresModifierData *)modifiers_findByType(ob_low, eModifierType_Multires);
+ mmd_low = (MultiresModifierData *)BKE_modifiers_findby_type(ob_low, eModifierType_Multires);
if (mmd_low) {
mmd_flags_low = mmd_low->flags;
mmd_low->uv_smooth = SUBSURF_UV_SMOOTH_NONE;
@@ -944,7 +945,7 @@ static int bake(Render *re,
if (md->type == eModifierType_EdgeSplit) {
BLI_remlink(&ob_low_eval->modifiers, md);
- modifier_free(md);
+ BKE_modifier_free(md);
is_changed = true;
}
md = md_next;
@@ -1023,7 +1024,7 @@ static int bake(Render *re,
highpoly[i].ob,
i,
pixel_array_high,
- num_pixels,
+ &bake_images,
depth,
pass_type,
pass_filter,
@@ -1045,7 +1046,7 @@ static int bake(Render *re,
ob_low_eval,
0,
pixel_array_low,
- num_pixels,
+ &bake_images,
depth,
pass_type,
pass_filter,
@@ -1095,7 +1096,7 @@ static int bake(Render *re,
int mode;
BKE_object_eval_reset(ob_low_eval);
- md = modifiers_findByType(ob_low_eval, eModifierType_Multires);
+ md = BKE_modifiers_findby_type(ob_low_eval, eModifierType_Multires);
if (md) {
mode = md->mode;
@@ -1146,7 +1147,7 @@ static int bake(Render *re,
is_noncolor);
/* might be read by UI to set active image for display */
- bake_update_image(sa, bk_image->image);
+ bake_update_image(area, bk_image->image);
if (!ok) {
BKE_reportf(reports,
@@ -1283,13 +1284,13 @@ cleanup:
static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
{
bool is_save_internal;
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
bkr->ob = CTX_data_active_object(C);
bkr->main = CTX_data_main(C);
bkr->view_layer = CTX_data_view_layer(C);
bkr->scene = CTX_data_scene(C);
- bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL;
+ bkr->area = screen ? BKE_screen_find_big_area(screen, SPACE_IMAGE, 10) : NULL;
bkr->pass_type = RNA_enum_get(op->ptr, "type");
bkr->pass_filter = RNA_enum_get(op->ptr, "pass_filter");
@@ -1400,7 +1401,7 @@ static int bake_exec(bContext *C, wmOperator *op)
bkr.width,
bkr.height,
bkr.identifier,
- bkr.sa,
+ bkr.area,
bkr.uv_layer);
}
else {
@@ -1432,7 +1433,7 @@ static int bake_exec(bContext *C, wmOperator *op)
bkr.width,
bkr.height,
bkr.identifier,
- bkr.sa,
+ bkr.area,
bkr.uv_layer);
}
}
@@ -1501,7 +1502,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
bkr->width,
bkr->height,
bkr->identifier,
- bkr->sa,
+ bkr->area,
bkr->uv_layer);
}
else {
@@ -1533,7 +1534,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
bkr->width,
bkr->height,
bkr->identifier,
- bkr->sa,
+ bkr->area,
bkr->uv_layer);
if (bkr->result == OPERATOR_CANCELLED) {
diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c
index a00e5e7b198..7a83d582299 100644
--- a/source/blender/editors/object/object_collection.c
+++ b/source/blender/editors/object/object_collection.c
@@ -32,7 +32,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -40,8 +40,8 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#include "ED_screen.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -302,8 +302,8 @@ static int collection_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op
void COLLECTION_OT_objects_remove_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove from All Unlinked Collections";
- ot->description = "Remove selected objects from all collections not used in a scene";
+ ot->name = "Remove from All Collections";
+ ot->description = "Remove selected objects from all collections";
ot->idname = "COLLECTION_OT_objects_remove_all";
/* api callbacks */
@@ -481,9 +481,21 @@ static int collection_link_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+ /* Currently this should not be allowed (might be supported in the future though...). */
+ if (ID_IS_OVERRIDE_LIBRARY(&collection->id)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not add the collection because it is overridden.");
+ return OPERATOR_CANCELLED;
+ }
+ /* Linked collections are already checked for by using RNA_collection_local_itemf
+ * but operator can be called without invoke */
+ if (ID_IS_LINKED(&collection->id)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not add the collection because it is linked.");
+ return OPERATOR_CANCELLED;
+ }
+
/* Adding object to collection which is used as dupli-collection for self is bad idea.
*
- * It is also bad idea to add object to collection which is in collection which
+ * It is also bad idea to add object to collection which is in collection which
* contains our current object.
*/
if (BKE_collection_object_cyclic_check(bmain, ob, collection)) {
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 8981221cb9c..ba641fb2a39 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -27,8 +27,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLI_dynstr.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -37,10 +37,11 @@
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_text_types.h"
-#include "DNA_object_types.h"
+#include "BIK_api.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
@@ -50,7 +51,6 @@
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_tracking.h"
-#include "BIK_api.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -67,8 +67,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "ED_object.h"
#include "ED_keyframing.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -76,7 +76,9 @@
#include "object_intern.h"
-/* -------------- Get Active Constraint Data ---------------------- */
+/* ------------------------------------------------------------------- */
+/** \name Constraint Data Accessors
+ * \{ */
/* if object in posemode, active bone constraints, else object constraints */
ListBase *get_active_constraints(Object *ob)
@@ -146,9 +148,13 @@ bConstraint *get_active_constraint(Object *ob)
return BKE_constraints_active_get(get_active_constraints(ob));
}
-/* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name PyConstraints (Unused)
+ * \{ */
+
#ifdef WITH_PYTHON
-/* ------------- PyConstraints ------------------ */
/* this callback sets the text-file to be used for selected menu item */
static void validate_pyconstraint_cb(Main *bmain, void *arg1, void *arg2)
@@ -231,6 +237,12 @@ static void update_pyconstraint_cb(void *arg1, void *arg2)
}
#endif // UNUSED
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Add Constraint Utilities
+ * \{ */
+
/* helper function for add_constriant - sets the last target for the active constraint */
static void set_constraint_nth_target(bConstraint *con,
Object *target,
@@ -272,7 +284,11 @@ static void set_constraint_nth_target(bConstraint *con,
}
}
-/* ------------- Constraint Sanity Testing ------------------- */
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Constraint Sanity Testing
+ * \{ */
static void test_constraint(
Main *bmain, Object *owner, bPoseChannel *pchan, bConstraint *con, int type)
@@ -626,7 +642,11 @@ static void object_test_constraint(Main *bmain, Object *owner, bConstraint *con)
}
}
-/*** generic functions for operators using constraint names and data context *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Generic Functions for Operators Using Constraint Names and Data Context
+ * \{ */
#define EDIT_CONSTRAINT_OWNER_OBJECT 0
#define EDIT_CONSTRAINT_OWNER_BONE 1
@@ -766,10 +786,13 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
return con;
}
-/* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */
+/** \} */
-/* ---------- Distance-Dependent Constraints ---------- */
-/* StretchTo, Limit Distance */
+/* ------------------------------------------------------------------- */
+/** \name Stretch-To/Limit-Distance Constraint (Reset Original Length Operator)
+ *
+ * For Stretch-To & Limit-Distance constraints.
+ * \{ */
static int stretchto_reset_exec(bContext *C, wmOperator *op)
{
@@ -820,6 +843,14 @@ void CONSTRAINT_OT_stretchto_reset(wmOperatorType *ot)
edit_constraint_properties(ot);
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Distance Constraint (Reset Operator)
+ *
+ * For Limit-Distance constraint.
+ * \{ */
+
static int limitdistance_reset_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -869,120 +900,37 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
edit_constraint_properties(ot);
}
-/* ------------- Child-Of Constraint ------------------ */
+/** \} */
-static void child_get_inverse_matrix_owner_bone(
- Depsgraph *depsgraph, 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.
- */
- 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);
+/* ------------------------------------------------------------------- */
+/** \name Child-Of Constraint (Set Inverse Operator)
+ * \{ */
- bPoseChannel *pchan_eval = BKE_pose_channel_active(ob_eval);
-
- /* 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;
-
- /* 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];
-
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&pchan_eval->constraints, con_eval) != -1);
-
- /* 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);
-
- /* 2. knock out constraints starting from this one */
- con_last = pchan_eval->constraints.last;
- pchan_eval->constraints.last = con_eval->prev;
-
- 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;
- }
-
- /* 3. solve pose without disabled constraints */
- BKE_pose_where_is(depsgraph, scene, ob_eval);
-
- /* 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;
-
- 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); */
- }
-}
-
-static void child_get_inverse_matrix_owner_object(
- Depsgraph *depsgraph, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4])
+/* Force evaluation so that the 'set inverse' flag is handled.
+ * No-op when the constraint is enabled, as in such cases the evaluation will happen anyway.
+ */
+static void force_evaluation_if_constraint_disabled(bContext *C, Object *ob, bConstraint *con)
{
+ if ((con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) == 0) {
+ return;
+ }
- /* 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);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
- /* 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);
- }
+ short flag_backup = con->flag;
+ con->flag &= ~(CONSTRAINT_DISABLE | CONSTRAINT_OFF);
+ BKE_object_eval_constraints(depsgraph, scene, ob);
+ con->flag = flag_backup;
}
/* ChildOf Constraint - set inverse callback */
static int childof_set_inverse_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
- const int owner = RNA_enum_get(op->ptr, "owner");
/* despite 3 layers of checks, we may still not be able to find a constraint */
if (data == NULL) {
@@ -991,12 +939,11 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat);
- }
- else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat);
- }
+ /* Set a flag to request recalculation on next update. */
+ data->flag |= CHILDOF_SET_INVERSE;
+
+ /* Force constraint to run, it will perform the recalculation. */
+ force_evaluation_if_constraint_disabled(C, ob, con);
ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
@@ -1084,7 +1031,11 @@ void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot)
edit_constraint_properties(ot);
}
-/* --------------- Follow Path Constraint ------------------ */
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Follow Path Constraint (Auto Animate Path Operator)
+ * \{ */
static int followpath_path_animate_exec(bContext *C, wmOperator *op)
{
@@ -1112,8 +1063,8 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op)
if (ELEM(NULL, cu->adt, cu->adt->action) ||
(list_find_fcurve(&cu->adt->action->curves, "eval_time", 0) == NULL)) {
/* create F-Curve for path animation */
- act = verify_adt_action(bmain, &cu->id, 1);
- fcu = verify_fcurve(bmain, act, NULL, NULL, "eval_time", 0, 1);
+ act = ED_id_action_ensure(bmain, &cu->id);
+ fcu = ED_action_fcurve_ensure(bmain, act, NULL, NULL, "eval_time", 0);
/* standard vertical range - 1:1 = 100 frames */
standardRange = 100.0f;
@@ -1137,8 +1088,8 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op)
path = RNA_path_from_ID_to_property(&ptr, prop);
/* create F-Curve for constraint */
- act = verify_adt_action(bmain, &ob->id, 1);
- fcu = verify_fcurve(bmain, act, NULL, NULL, path, 0, 1);
+ act = ED_id_action_ensure(bmain, &ob->id);
+ fcu = ED_action_fcurve_ensure(bmain, act, NULL, NULL, path, 0);
/* standard vertical range - 0.0 to 1.0 */
standardRange = 1.0f;
@@ -1226,31 +1177,32 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
MAXFRAME);
}
-/* ------------- Object Solver Constraint ------------------ */
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Object Solver Constraint (Set Inverse Operator)
+ * \{ */
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(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);
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
- const int owner = RNA_enum_get(op->ptr, "owner");
/* despite 3 layers of checks, we may still not be able to find a constraint */
if (data == NULL) {
- printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
- BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse");
+ printf("DEBUG: ObjectSolver Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
+ BKE_report(
+ op->reports, RPT_ERROR, "Could not find constraint data for ObjectSolver Set Inverse");
return OPERATOR_CANCELLED;
}
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat);
- }
- else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat);
- }
+ /* Set a flag to request recalculation on next update. */
+ data->flag |= OBJECTSOLVER_SET_INVERSE;
+
+ /* Force constraint to run, it will perform the recalculation. */
+ force_evaluation_if_constraint_disabled(C, ob, con);
ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
@@ -1289,8 +1241,15 @@ void CONSTRAINT_OT_objectsolver_set_inverse(wmOperatorType *ot)
edit_constraint_properties(ot);
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Object Solver Constraint (Clear Inverse Operator)
+ * \{ */
+
static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
@@ -1303,6 +1262,7 @@ static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
/* simply clear the matrix */
unit_m4(data->invmat);
+ ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
return OPERATOR_FINISHED;
@@ -1339,7 +1299,11 @@ void CONSTRAINT_OT_objectsolver_clear_inverse(wmOperatorType *ot)
edit_constraint_properties(ot);
}
-/***************************** BUTTONS ****************************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Constraint Management Utilities
+ * \{ */
void ED_object_constraint_set_active(Object *ob, bConstraint *con)
{
@@ -1433,6 +1397,12 @@ static bool constraint_poll(bContext *C)
return (ptr.owner_id && ptr.data);
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Delete Constraint Operator
+ * \{ */
+
static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
@@ -1477,6 +1447,12 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Move Down Constraint Operator
+ * \{ */
+
static int constraint_move_down_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C);
@@ -1527,6 +1503,12 @@ void CONSTRAINT_OT_move_down(wmOperatorType *ot)
edit_constraint_properties(ot);
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Move Up Constraint Operator
+ * \{ */
+
static int constraint_move_up_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C);
@@ -1575,9 +1557,11 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot)
edit_constraint_properties(ot);
}
-/***************************** OPERATORS ****************************/
+/** \} */
-/************************ remove constraint operators *********************/
+/* ------------------------------------------------------------------- */
+/** \name Clear Pose Constraints Operator
+ * \{ */
static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1638,6 +1622,12 @@ static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Clear Object Constraints Operator
+ * \{ */
+
void OBJECT_OT_constraints_clear(wmOperatorType *ot)
{
/* identifiers */
@@ -1650,7 +1640,11 @@ void OBJECT_OT_constraints_clear(wmOperatorType *ot)
ot->poll = ED_operator_object_active_editable;
}
-/************************ copy all constraints operators *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Copy Pose Constraints Operator
+ * \{ */
static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
{
@@ -1705,6 +1699,12 @@ void POSE_OT_constraints_copy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Copy Object Constraints Operator
+ * \{ */
+
static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
@@ -1744,7 +1744,11 @@ void OBJECT_OT_constraints_copy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/************************ add constraint operators *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Add Constraints Operator
+ * \{ */
/* get the Object and/or PoseChannel to use as target */
static bool get_new_constraint_target(
@@ -2102,6 +2106,12 @@ void OBJECT_OT_constraint_add(wmOperatorType *ot)
ot->prop = prop;
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Add Constraints With Targets Operator
+ * \{ */
+
void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -2167,8 +2177,14 @@ void POSE_OT_constraint_add_with_targets(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
-/************************ IK Constraint operators *********************/
-/* NOTE: only for Pose-Channels */
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Add IK to Bone Operator
+ *
+ * \note Only for pose-channels.
+ * \{ */
+
// TODO: should these be here, or back in editors/armature/poseobject.c again?
/* present menu with options + validation for targets to use */
@@ -2267,9 +2283,14 @@ void POSE_OT_ik_add(wmOperatorType *ot)
"Assign IK Constraint with targets derived from the select bones/objects");
}
-/* ------------------ */
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Clear IK from Bone Operator
+ *
+ * Remove IK constraints from selected bones.
+ * \{ */
-/* remove IK constraints from selected bones */
static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *prev_ob = NULL;
@@ -2317,3 +2338,5 @@ void POSE_OT_ik_clear(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/** \} */
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 0a5db782892..1e2b7702dc5 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -26,8 +26,8 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c
index b6f125c6f71..54fd1fe6671 100644
--- a/source/blender/editors/object/object_data_transform.c
+++ b/source/blender/editors/object/object_data_transform.c
@@ -32,23 +32,23 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_collection_types.h"
+#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_collection_types.h"
-#include "DNA_lattice_types.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_editmesh.h"
+#include "BKE_lattice.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
-#include "BKE_armature.h"
-#include "BKE_lattice.h"
#include "BKE_scene.h"
#include "bmesh.h"
@@ -58,9 +58,9 @@
#include "WM_types.h"
-#include "ED_object.h"
-#include "ED_mesh.h"
#include "ED_armature.h"
+#include "ED_mesh.h"
+#include "ED_object.h"
#include "MEM_guardedalloc.h"
@@ -92,7 +92,7 @@ static struct ElemData_Armature *armature_coords_and_quats_get_recurse(
const ListBase *bone_base, struct ElemData_Armature *elem_array)
{
struct ElemData_Armature *elem = elem_array;
- for (const Bone *bone = bone_base->first; bone; bone = bone->next) {
+ LISTBASE_FOREACH (const Bone *, bone, bone_base) {
#define COPY_PTR(member) memcpy(elem->member, bone->member, sizeof(bone->member))
#define COPY_VAL(member) memcpy(&elem->member, &bone->member, sizeof(bone->member))
@@ -125,7 +125,7 @@ static const struct ElemData_Armature *armature_coords_and_quats_apply_with_mat4
ListBase *bone_base, const struct ElemData_Armature *elem_array, const float mat[4][4])
{
const struct ElemData_Armature *elem = elem_array;
- for (Bone *bone = bone_base->first; bone; bone = bone->next) {
+ LISTBASE_FOREACH (Bone *, bone, bone_base) {
#define COPY_PTR(member) memcpy(bone->member, elem->member, sizeof(bone->member))
#define COPY_VAL(member) memcpy(&bone->member, &elem->member, sizeof(bone->member))
@@ -580,100 +580,3 @@ void ED_object_data_xform_tag_update(struct XFormObjectData *xod_base)
}
/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Object Data Transform Container
- *
- * Use to implement 'Affect Only Origins' feature.
- *
- * \{ */
-
-struct XFormObjectData_Container {
- GHash *obdata_in_obmode_map;
-};
-
-struct XFormObjectData_Extra {
- Object *ob;
- float obmat_orig[4][4];
- struct XFormObjectData *xod;
-};
-
-void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container *xds, Object *ob)
-{
- if (xds->obdata_in_obmode_map == NULL) {
- xds->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
- }
-
- void **xf_p;
- if (!BLI_ghash_ensure_p(xds->obdata_in_obmode_map, ob->data, &xf_p)) {
- struct XFormObjectData_Extra *xf = MEM_mallocN(sizeof(*xf), __func__);
- copy_m4_m4(xf->obmat_orig, ob->obmat);
- xf->ob = ob;
- /* Result may be NULL, that's OK. */
- xf->xod = ED_object_data_xform_create(ob->data);
- *xf_p = xf;
- }
-}
-
-/**
- * This may be called multiple times with the same data.
- * Each time, the original transformations are re-applied, instead of accumulating the changes.
- */
-void ED_object_data_xform_container_update_all(struct XFormObjectData_Container *xds,
- struct Main *bmain,
- Depsgraph *depsgraph)
-{
- if (xds->obdata_in_obmode_map == NULL) {
- return;
- }
- BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
-
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, xds->obdata_in_obmode_map) {
- ID *id = BLI_ghashIterator_getKey(&gh_iter);
- struct XFormObjectData_Extra *xf = BLI_ghashIterator_getValue(&gh_iter);
- if (xf->xod == NULL) {
- continue;
- }
-
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, xf->ob);
- float imat[4][4], dmat[4][4];
- invert_m4_m4(imat, xf->obmat_orig);
- mul_m4_m4m4(dmat, imat, ob_eval->obmat);
- invert_m4(dmat);
-
- ED_object_data_xform_by_mat4(xf->xod, dmat);
- if (xf->ob->type == OB_ARMATURE) {
- /* TODO: none of the current flags properly update armatures, needs investigation. */
- DEG_id_tag_update(id, 0);
- }
- else {
- DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
- }
- }
-}
-
-/** Callback for #GHash free. */
-static void trans_obdata_in_obmode_free_elem(void *xf_p)
-{
- struct XFormObjectData_Extra *xf = xf_p;
- if (xf->xod) {
- ED_object_data_xform_destroy(xf->xod);
- }
- MEM_freeN(xf);
-}
-
-struct XFormObjectData_Container *ED_object_data_xform_container_create(void)
-{
- struct XFormObjectData_Container *xds = MEM_callocN(sizeof(*xds), __func__);
- xds->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
- return xds;
-}
-
-void ED_object_data_xform_container_destroy(struct XFormObjectData_Container *xds)
-{
- BLI_ghash_free(xds->obdata_in_obmode_map, NULL, trans_obdata_in_obmode_free_elem);
- MEM_freeN(xds);
-}
-
-/** \} */
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 34e1b3b2b4b..690c63a2cbf 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -21,19 +21,19 @@
* \ingroup edobj
*/
+#include <ctype.h>
+#include <float.h>
+#include <math.h>
+#include <stddef.h> //for offsetof
#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include <time.h>
-#include <float.h>
-#include <ctype.h>
-#include <stddef.h> //for offsetof
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -41,25 +41,26 @@
#include "DNA_collection_types.h"
#include "DNA_curve_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_lattice_types.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_object_force_types.h"
-#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_lattice_types.h"
#include "DNA_workspace_types.h"
#include "IMB_imbuf_types.h"
-#include "BKE_anim.h"
+#include "BKE_anim_visualization.h"
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_editlattice.h"
+#include "BKE_editmesh.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -74,10 +75,9 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "BKE_softbody.h"
-#include "BKE_editmesh.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_softbody.h"
#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
@@ -86,47 +86,45 @@
#include "ED_anim_api.h"
#include "ED_armature.h"
#include "ED_curve.h"
-#include "ED_mesh.h"
-#include "ED_mball.h"
+#include "ED_gpencil.h"
+#include "ED_image.h"
#include "ED_lattice.h"
+#include "ED_mball.h"
+#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_undo.h"
-#include "ED_image.h"
-#include "ED_gpencil.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "CLG_log.h"
+
/* for menu/popup icons etc etc*/
#include "UI_interface.h"
#include "UI_resources.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "object_intern.h" // own include
+static CLG_LogRef LOG = {"ed.object.edit"};
+
/* prototypes */
typedef struct MoveToCollectionData MoveToCollectionData;
static void move_to_collection_menus_items(struct uiLayout *layout,
struct MoveToCollectionData *menu);
static ListBase selected_objects_get(bContext *C);
-/* ************* XXX **************** */
-static void error(const char *UNUSED(arg))
-{
-}
-
-/* port over here */
-static void error_libdata(void)
-{
-}
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
Object *ED_object_context(bContext *C)
{
@@ -147,7 +145,11 @@ Object *ED_object_active_context(bContext *C)
return ob;
}
-/* ********************** object hiding *************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hide Operator
+ * \{ */
static bool object_hide_poll(bContext *C)
{
@@ -166,7 +168,7 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *op)
const bool select = RNA_boolean_get(op->ptr, "select");
bool changed = false;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->flag & BASE_HIDDEN) {
base->flag &= ~BASE_HIDDEN;
changed = true;
@@ -217,7 +219,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op)
bool changed = false;
/* Hide selected or unselected objects. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (!(base->flag & BASE_VISIBLE_VIEWLAYER)) {
continue;
}
@@ -321,7 +323,7 @@ void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout)
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
- for (LayerCollection *lc = lc_scene->layer_collections.first; lc; lc = lc->next) {
+ LISTBASE_FOREACH (LayerCollection *, lc, &lc_scene->layer_collections) {
int index = BKE_layer_collection_findindex(view_layer, lc);
uiLayout *row = uiLayoutRow(layout, false);
@@ -401,7 +403,11 @@ void OBJECT_OT_hide_collection(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
-/* ******************* toggle editmode operator ***************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Edit-Mode Operator
+ * \{ */
static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
{
@@ -414,7 +420,7 @@ static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
return true;
}
if (ob->data == me) {
- for (const ModifierData *md = ob->modifiers.first; md; md = md->next) {
+ LISTBASE_FOREACH (const ModifierData *, md, &ob->modifiers) {
if (md->type == eModifierType_Hook) {
return true;
}
@@ -441,7 +447,11 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
}
if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) {
- error("Too many vertices");
+ /* This used to be warned int the UI, we could warn again although it's quite rare. */
+ CLOG_WARN(&LOG,
+ "Too many vertices for mesh '%s' (%d)",
+ me->id.name + 2,
+ me->edit_mesh->bm->totvert);
return false;
}
@@ -454,8 +464,8 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
}
/* will be recalculated as needed. */
{
- ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
- ED_mesh_mirror_topo_table(NULL, NULL, 'e');
+ ED_mesh_mirror_spatial_table_end(obedit);
+ ED_mesh_mirror_topo_table_end(obedit);
}
}
else if (obedit->type == OB_ARMATURE) {
@@ -543,6 +553,8 @@ bool ED_object_editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int f
* is flagged for editmode, without 'obedit' being set [#35489] */
if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
obedit->mode &= ~OB_MODE_EDIT;
+ /* Also happens when mesh is shared across multiple objects. [#T69834] */
+ DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
return true;
}
@@ -598,7 +610,8 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag
}
if (BKE_object_obdata_is_libdata(ob)) {
- error_libdata();
+ /* Ideally the caller should check this. */
+ CLOG_WARN(&LOG, "Unable to enter edit-mode on library data for object '%s'", ob->id.name + 2);
return false;
}
@@ -627,7 +640,7 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag
bArmature *arm = ob->data;
ok = 1;
ED_armature_to_edit(arm);
- /* to ensure all goes in restposition and without striding */
+ /* To ensure all goes in rest-position and without striding. */
arm->needs_flush_to_id = 0;
@@ -775,7 +788,11 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* *************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Pose-Mode Operator
+ * \{ */
static int posemode_exec(bContext *C, wmOperator *op)
{
@@ -859,12 +876,16 @@ void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************* force field toggle operator ***************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Force Field Toggle Operator
+ * \{ */
void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object)
{
PartDeflect *pd = object->pd;
- ModifierData *md = modifiers_findByType(object, eModifierType_Surface);
+ ModifierData *md = BKE_modifiers_findby_type(object, eModifierType_Surface);
/* add/remove modifier as needed */
if (!md) {
@@ -922,8 +943,11 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************************************** */
-/* Motion Paths */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Calculate Motion Paths Operator
+ * \{ */
static eAnimvizCalcRange object_path_convert_range(eObjectPathCalcRange range)
{
@@ -1017,8 +1041,8 @@ static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEv
}
/* show popup dialog to allow editing of range... */
- /* FIXME: hardcoded dimensions here are just arbitrary */
- return WM_operator_props_dialog_popup(C, op, 200, 200);
+ /* FIXME: hard-coded dimensions here are just arbitrary. */
+ return WM_operator_props_dialog_popup(C, op, 200);
}
/* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */
@@ -1086,7 +1110,11 @@ void OBJECT_OT_paths_calculate(wmOperatorType *ot)
MAXFRAME / 2.0);
}
-/* --------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Update Motion Paths Operator
+ * \{ */
static bool object_update_paths_poll(bContext *C)
{
@@ -1130,7 +1158,11 @@ void OBJECT_OT_paths_update(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* --------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Motion Paths Operator
+ * \{ */
/* Helper for ED_objects_clear_paths() */
static void object_clear_mpath(Object *ob)
@@ -1149,14 +1181,14 @@ static void object_clear_mpath(Object *ob)
void ED_objects_clear_paths(bContext *C, bool only_selected)
{
if (only_selected) {
- /* loop over all selected + sedtiable objects in scene */
+ /* Loop over all selected + editable objects in scene. */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
object_clear_mpath(ob);
}
CTX_DATA_END;
}
else {
- /* loop over all edtiable objects in scene */
+ /* Loop over all editable objects in scene. */
CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
object_clear_mpath(ob);
}
@@ -1208,13 +1240,17 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot)
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
-/* --------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Update Motion Paths Range from Scene Operator
+ * \{ */
static int object_update_paths_range_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- /* loop over all edtiable objects in scene */
+ /* Loop over all editable objects in scene. */
CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
/* use Preview Range or Full Frame Range - whichever is in use */
ob->avs.path_sf = PSFRA;
@@ -1244,63 +1280,99 @@ void OBJECT_OT_paths_range_update(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/********************** Smooth/Flat *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Shade Smooth/Flat Operator
+ * \{ */
static int shade_smooth_exec(bContext *C, wmOperator *op)
{
- ID *data;
- Curve *cu;
- Nurb *nu;
- int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat"));
- bool done = false, linked_data = false;
+ const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth");
+ bool changed_multi = false;
+ bool has_linked_data = false;
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
- data = ob->data;
+ ListBase ctx_objects = {NULL, NULL};
+ CollectionPointerLink ctx_ob_single_active = {NULL};
+
+ /* For modes that only use an active object, don't handle the whole selection. */
+ {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = OBACT(view_layer);
+ if (obact && ((obact->mode & OB_MODE_ALL_PAINT))) {
+ ctx_ob_single_active.ptr.data = obact;
+ BLI_addtail(&ctx_objects, &ctx_ob_single_active);
+ }
+ }
+
+ if (ctx_objects.first != &ctx_ob_single_active) {
+ CTX_data_selected_editable_objects(C, &ctx_objects);
+ }
+
+ for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+ ID *data = ob->data;
+ if (data != NULL) {
+ data->tag |= LIB_TAG_DOIT;
+ }
+ }
+
+ for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ /* Always un-tag all object data-blocks irrespective of our ability to operate on them. */
+ Object *ob = ctx_ob->ptr.data;
+ ID *data = ob->data;
+ if ((data == NULL) || ((data->tag & LIB_TAG_DOIT) == 0)) {
+ continue;
+ }
+ data->tag &= ~LIB_TAG_DOIT;
+ /* Finished un-tagging, continue with regular logic. */
if (data && ID_IS_LINKED(data)) {
- linked_data = true;
+ has_linked_data = true;
continue;
}
+ bool changed = false;
if (ob->type == OB_MESH) {
- BKE_mesh_smooth_flag_set(ob->data, !clear);
-
+ BKE_mesh_smooth_flag_set(ob->data, use_smooth);
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- done = true;
+ changed = true;
}
else if (ELEM(ob->type, OB_SURF, OB_CURVE)) {
- cu = ob->data;
+ BKE_curve_smooth_flag_set(ob->data, use_smooth);
+ changed = true;
+ }
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (!clear) {
- nu->flag |= ME_SMOOTH;
- }
- else {
- nu->flag &= ~ME_SMOOTH;
- }
- }
+ if (changed) {
+ changed_multi = true;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- done = true;
}
}
- CTX_DATA_END;
- if (linked_data) {
+ if (ctx_objects.first != &ctx_ob_single_active) {
+ BLI_freelistN(&ctx_objects);
+ }
+
+ if (has_linked_data) {
BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data");
}
- return (done) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static bool shade_poll(bContext *C)
{
- return (CTX_data_edit_object(C) == NULL);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = OBACT(view_layer);
+ if (obact != NULL) {
+ /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */
+ if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT)) {
+ return false;
+ }
+ }
+ return true;
}
void OBJECT_OT_shade_flat(wmOperatorType *ot)
@@ -1333,7 +1405,11 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Mode Set Operator
+ * \{ */
static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
PointerRNA *UNUSED(ptr),
@@ -1353,7 +1429,8 @@ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
if (ob) {
const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) ||
(ob->soft != NULL) ||
- (modifiers_findByType(ob, eModifierType_Cloth) != NULL);
+ (BKE_modifiers_findby_type(ob, eModifierType_Cloth) !=
+ NULL);
while (input->identifier) {
if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
(input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
@@ -1368,7 +1445,8 @@ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
OB_MODE_EDIT_GPENCIL,
OB_MODE_PAINT_GPENCIL,
OB_MODE_SCULPT_GPENCIL,
- OB_MODE_WEIGHT_GPENCIL) &&
+ OB_MODE_WEIGHT_GPENCIL,
+ OB_MODE_VERTEX_GPENCIL) &&
(ob->type == OB_GPENCIL)) ||
(input->value == OB_MODE_OBJECT)) {
RNA_enum_item_add(&item, &totitem, input);
@@ -1388,66 +1466,57 @@ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
return item;
}
-static bool object_mode_set_poll(bContext *C)
-{
- /* Since Grease Pencil editmode is also handled here,
- * we have a special exception for allowing this operator
- * to still work in that case when there's no active object
- * so that users can exit editmode this way as per normal.
- */
- if (ED_operator_object_active_editable(C)) {
- return true;
- }
- else {
- return (CTX_data_gpencil_data(C) != NULL);
- }
-}
-
static int object_mode_set_exec(bContext *C, wmOperator *op)
{
bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode");
Object *ob = CTX_data_active_object(C);
eObjectMode mode = RNA_enum_get(op->ptr, "mode");
- eObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT;
+ eObjectMode restore_mode = ob->mode;
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
/* by default the operator assume is a mesh, but if gp object change mode */
- if ((ob != NULL) && (ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) {
+ if ((ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) {
mode = OB_MODE_EDIT_GPENCIL;
}
- if (!ob || !ED_object_mode_compat_test(ob, mode)) {
+ if (!ED_object_mode_compat_test(ob, mode)) {
return OPERATOR_PASS_THROUGH;
}
- if (ob->mode != mode) {
- /* we should be able to remove this call, each operator calls */
- ED_object_mode_compat_set(C, ob, mode, op->reports);
- }
-
- /* Exit current mode if it's not the mode we're setting */
- if (mode != OB_MODE_OBJECT && (ob->mode != mode || toggle)) {
- /* Enter new mode */
- ED_object_mode_toggle(C, mode);
+ if (toggle == false) {
+ if (ob->mode != mode) {
+ if (mode != OB_MODE_OBJECT) {
+ /* Enter new mode. */
+ ED_object_mode_toggle(C, mode);
+ }
+ else {
+ ED_object_mode_compat_set(C, ob, mode, op->reports);
+ }
+ }
}
+ else {
+ /* Exit current mode if it's not the mode we're setting */
+ if (mode != OB_MODE_OBJECT) {
+ /* Enter new mode. */
+ ED_object_mode_toggle(C, mode);
+ }
- if (toggle) {
/* Special case for Object mode! */
- if (mode == OB_MODE_OBJECT && restore_mode == OB_MODE_OBJECT &&
- ob->restore_mode != OB_MODE_OBJECT) {
+ if ((mode == OB_MODE_OBJECT) && (restore_mode == OB_MODE_OBJECT) &&
+ (ob->restore_mode != OB_MODE_OBJECT)) {
ED_object_mode_toggle(C, ob->restore_mode);
}
else if (ob->mode == mode) {
/* For toggling, store old mode so we know what to go back to */
ob->restore_mode = restore_mode;
}
- else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
+ else if ((ob->restore_mode != OB_MODE_OBJECT) && (ob->restore_mode != mode)) {
ED_object_mode_toggle(C, ob->restore_mode);
}
}
/* if type is OB_GPENCIL, set cursor mode */
- if ((ob) && (ob->type == OB_GPENCIL)) {
+ if (ob->type == OB_GPENCIL) {
if (ob->data) {
bGPdata *gpd = (bGPdata *)ob->data;
ED_gpencil_setup_modes(C, gpd, ob->mode);
@@ -1482,8 +1551,7 @@ void OBJECT_OT_mode_set(wmOperatorType *ot)
/* api callbacks */
ot->exec = object_mode_set_exec;
-
- ot->poll = object_mode_set_poll; // ED_operator_object_active_editable;
+ ot->poll = ED_operator_object_active_editable;
/* flags */
ot->flag = 0; /* no register/undo here, leave it to operators being called */
@@ -1513,6 +1581,12 @@ void OBJECT_OT_mode_set_with_submode(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Link/Move to Collection Operator
+ * \{ */
+
static ListBase selected_objects_get(bContext *C)
{
ListBase objects = {NULL};
@@ -1590,7 +1664,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- for (LinkData *link = objects.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &objects) {
Object *ob = link->data;
if (!is_link) {
@@ -1737,7 +1811,7 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
BKE_collection_new_name_get(collection, name);
RNA_property_string_set(op->ptr, prop, name);
- return WM_operator_props_dialog_popup(C, op, 200, 100);
+ return WM_operator_props_dialog_popup(C, op, 200);
}
}
return move_to_collection_exec(C, op);
@@ -1853,3 +1927,5 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
ot->prop = prop;
}
+
+/** \} */
diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c
index 0081e18f33c..147bd3d7871 100644
--- a/source/blender/editors/object/object_facemap_ops.c
+++ b/source/blender/editors/object/object_facemap_ops.c
@@ -25,27 +25,27 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
-#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
#include "DNA_workspace_types.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_object.h"
-#include "BKE_object_facemap.h"
#include "BKE_object_deform.h"
+#include "BKE_object_facemap.h"
#include "DEG_depsgraph.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "ED_mesh.h"
#include "ED_object.h"
diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c
index 9138e65dd2f..6d0f53cfa1e 100644
--- a/source/blender/editors/object/object_gpencil_modifier.c
+++ b/source/blender/editors/object/object_gpencil_modifier.c
@@ -27,8 +27,8 @@
#include "MEM_guardedalloc.h"
-#include "DNA_gpencil_types.h"
#include "DNA_gpencil_modifier_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -37,11 +37,11 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_main.h"
+#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
-#include "BKE_report.h"
+#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_gpencil.h"
+#include "BKE_report.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -65,7 +65,7 @@ GpencilModifierData *ED_object_gpencil_modifier_add(
ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
{
GpencilModifierData *new_md = NULL;
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type);
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(type);
if (ob->type != OB_GPENCIL) {
BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
@@ -73,7 +73,7 @@ GpencilModifierData *ED_object_gpencil_modifier_add(
}
if (mti->flags & eGpencilModifierTypeFlag_Single) {
- if (BKE_gpencil_modifiers_findByType(ob, type)) {
+ if (BKE_gpencil_modifiers_findby_type(ob, type)) {
BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
return NULL;
}
@@ -91,6 +91,11 @@ GpencilModifierData *ED_object_gpencil_modifier_add(
/* make sure modifier data has unique name */
BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, new_md);
+ /* Enable edit mode visible by default. */
+ if (mti->flags & eGpencilModifierTypeFlag_SupportsEditmode) {
+ new_md->mode |= eGpencilModifierMode_Editmode;
+ }
+
bGPdata *gpd = ob->data;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -209,7 +214,7 @@ int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports),
static int gpencil_modifier_apply_obdata(
ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md)
{
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
if (mti->isDisabled && mti->isDisabled(md, 0)) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
@@ -276,18 +281,18 @@ int ED_object_gpencil_modifier_apply(Main *bmain,
int ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModifierData *md)
{
GpencilModifierData *nmd;
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
GpencilModifierType type = md->type;
if (mti->flags & eGpencilModifierTypeFlag_Single) {
- if (BKE_gpencil_modifiers_findByType(ob, type)) {
+ if (BKE_gpencil_modifiers_findby_type(ob, type)) {
BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
return 0;
}
}
nmd = BKE_gpencil_modifier_new(md->type);
- BKE_gpencil_modifier_copyData(md, nmd);
+ BKE_gpencil_modifier_copydata(md, nmd);
BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd);
BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd);
@@ -330,7 +335,7 @@ static const EnumPropertyItem *gpencil_modifier_add_itemf(bContext *C,
for (a = 0; rna_enum_object_greasepencil_modifier_type_items[a].identifier; a++) {
md_item = &rna_enum_object_greasepencil_modifier_type_items[a];
if (md_item->identifier[0]) {
- mti = BKE_gpencil_modifierType_getInfo(md_item->value);
+ mti = BKE_gpencil_modifier_get_info(md_item->value);
if (mti->flags & eGpencilModifierTypeFlag_NoUserAdd) {
continue;
@@ -362,7 +367,7 @@ void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "Add Grease Pencil Modifier";
+ ot->name = "Add Modifier";
ot->description = "Add a procedural operation/effect to the active grease pencil object";
ot->idname = "OBJECT_OT_gpencil_modifier_add";
@@ -450,7 +455,7 @@ static GpencilModifierData *gpencil_edit_modifier_property_get(wmOperator *op,
GpencilModifierData *md;
RNA_string_get(op->ptr, "modifier", modifier_name);
- md = BKE_gpencil_modifiers_findByName(ob, modifier_name);
+ md = BKE_gpencil_modifiers_findby_name(ob, modifier_name);
if (md && type != 0 && md->type != type) {
md = NULL;
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index bcbf7ddf9a6..9d2e5e74352 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -26,8 +26,8 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -41,29 +41,29 @@
#include "BKE_action.h"
#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_editmesh.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "BKE_deform.h"
-#include "BKE_editmesh.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "ED_curve.h"
#include "ED_mesh.h"
#include "ED_screen.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "UI_resources.h"
@@ -123,7 +123,7 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name,
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- if (defvert_find_weight(dvert, defgrp_index) > 0.0f) {
+ if (BKE_defvert_find_weight(dvert, defgrp_index) > 0.0f) {
add_v3_v3(r_cent, eve->co);
totvert++;
}
@@ -552,14 +552,14 @@ static int add_hook_object(const bContext *C,
}
md = obedit->modifiers.first;
- while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) {
+ while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) {
md = md->next;
}
- hmd = (HookModifierData *)modifier_new(eModifierType_Hook);
+ hmd = (HookModifierData *)BKE_modifier_new(eModifierType_Hook);
BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name + 2);
- modifier_unique_name(&obedit->modifiers, (ModifierData *)hmd);
+ BKE_modifier_unique_name(&obedit->modifiers, (ModifierData *)hmd);
hmd->object = ob;
hmd->indexar = indexar;
@@ -725,7 +725,7 @@ static int object_hook_remove_exec(bContext *C, wmOperator *op)
/* remove functionality */
BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
- modifier_free((ModifierData *)hmd);
+ BKE_modifier_free((ModifierData *)hmd);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 352ba744d92..d7a7b4ca110 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -24,6 +24,10 @@
#ifndef __OBJECT_INTERN_H__
#define __OBJECT_INTERN_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Object;
struct StructRNA;
struct bContext;
@@ -111,6 +115,8 @@ void OBJECT_OT_light_add(struct wmOperatorType *ot);
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
void OBJECT_OT_camera_add(struct wmOperatorType *ot);
void OBJECT_OT_speaker_add(struct wmOperatorType *ot);
+void OBJECT_OT_hair_add(struct wmOperatorType *ot);
+void OBJECT_OT_pointcloud_add(struct wmOperatorType *ot);
void OBJECT_OT_collection_instance_add(struct wmOperatorType *ot);
void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot);
@@ -120,6 +126,10 @@ void OBJECT_OT_join(struct wmOperatorType *ot);
void OBJECT_OT_join_shapes(struct wmOperatorType *ot);
void OBJECT_OT_convert(struct wmOperatorType *ot);
+/* object_volume.c */
+void OBJECT_OT_volume_add(struct wmOperatorType *ot);
+void OBJECT_OT_volume_import(struct wmOperatorType *ot);
+
/* object_hook.c */
void OBJECT_OT_hook_add_selob(struct wmOperatorType *ot);
void OBJECT_OT_hook_add_newob(struct wmOperatorType *ot);
@@ -159,6 +169,8 @@ void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot);
void OBJECT_OT_multires_reshape(struct wmOperatorType *ot);
void OBJECT_OT_multires_higher_levels_delete(struct wmOperatorType *ot);
void OBJECT_OT_multires_base_apply(struct wmOperatorType *ot);
+void OBJECT_OT_multires_unsubdivide(struct wmOperatorType *ot);
+void OBJECT_OT_multires_rebuild_subdiv(struct wmOperatorType *ot);
void OBJECT_OT_multires_external_save(struct wmOperatorType *ot);
void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot);
void OBJECT_OT_correctivesmooth_bind(struct wmOperatorType *ot);
@@ -281,10 +293,15 @@ void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot);
/* object_remesh.c */
void OBJECT_OT_voxel_remesh(struct wmOperatorType *ot);
+void OBJECT_OT_voxel_size_edit(struct wmOperatorType *ot);
void OBJECT_OT_quadriflow_remesh(struct wmOperatorType *ot);
/* object_transfer_data.c */
void OBJECT_OT_data_transfer(struct wmOperatorType *ot);
void OBJECT_OT_datalayout_transfer(struct wmOperatorType *ot);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __OBJECT_INTERN_H__ */
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index 80e7e6312aa..f06b6a4db2a 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -88,6 +88,9 @@ static const char *object_mode_op_string(eObjectMode mode)
if (mode == OB_MODE_WEIGHT_GPENCIL) {
return "GPENCIL_OT_weightmode_toggle";
}
+ if (mode == OB_MODE_VERTEX_GPENCIL) {
+ return "GPENCIL_OT_vertexmode_toggle";
+ }
return NULL;
}
@@ -129,7 +132,7 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
break;
case OB_GPENCIL:
if (mode & (OB_MODE_EDIT | OB_MODE_EDIT_GPENCIL | OB_MODE_PAINT_GPENCIL |
- OB_MODE_SCULPT_GPENCIL | OB_MODE_WEIGHT_GPENCIL)) {
+ OB_MODE_SCULPT_GPENCIL | OB_MODE_WEIGHT_GPENCIL | OB_MODE_VERTEX_GPENCIL)) {
return true;
}
break;
@@ -279,7 +282,9 @@ static bool ed_object_mode_generic_exit_ex(struct Main *bmain,
ED_object_posemode_exit_ex(bmain, ob);
}
}
- else if ((ob->type == OB_GPENCIL) && ((ob->mode & OB_MODE_OBJECT) == 0)) {
+ else if (ob->type == OB_GPENCIL) {
+ /* Accounted for above. */
+ BLI_assert((ob->mode & OB_MODE_OBJECT) == 0);
if (only_test) {
return true;
}
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index db946b63323..5cb4714dabf 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -37,25 +37,26 @@
#include "DNA_scene_types.h"
#include "BLI_bitmap.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
-#include "BLI_path_util.h"
#include "BLI_utildefines.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_animsys.h"
-#include "BKE_curve.h"
#include "BKE_context.h"
-#include "BKE_DerivedMesh.h"
+#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_gpencil_modifier.h"
+#include "BKE_hair.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
@@ -67,9 +68,11 @@
#include "BKE_ocean.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
+#include "BKE_pointcloud.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_softbody.h"
+#include "BKE_volume.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -80,9 +83,10 @@
#include "RNA_enum_types.h"
#include "ED_armature.h"
+#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
-#include "ED_mesh.h"
+#include "ED_sculpt.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -91,7 +95,9 @@
static void modifier_skin_customdata_delete(struct Object *ob);
-/******************************** API ****************************/
+/* ------------------------------------------------------------------- */
+/** \name Public Api
+ * \{ */
static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *ob)
{
@@ -114,29 +120,39 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *
else if (ob->type == OB_GPENCIL) {
BKE_gpencil_modifiers_calc(depsgraph, scene_eval, ob_eval);
}
+ else if (ob->type == OB_HAIR) {
+ BKE_hair_data_update(depsgraph, scene_eval, ob);
+ }
+ else if (ob->type == OB_POINTCLOUD) {
+ BKE_pointcloud_data_update(depsgraph, scene_eval, ob);
+ }
+ else if (ob->type == OB_VOLUME) {
+ BKE_volume_data_update(depsgraph, scene_eval, ob);
+ }
}
static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph,
Object *object,
ModifierData *md)
{
- ModifierData *md_eval = (ModifierData *)modifier_get_evaluated(depsgraph, object, md);
+ ModifierData *md_eval = (ModifierData *)BKE_modifier_get_evaluated(depsgraph, object, md);
const int mode = md_eval->mode;
md_eval->mode |= eModifierMode_Realtime;
object_force_modifier_update_for_bind(depsgraph, object);
md_eval->mode = mode;
}
-/** Add a modifier to given object, including relevant extra processing needed by some physics
- * types (particles, simulations...).
+/**
+ * Add a modifier to given object, including relevant extra processing needed by some physics types
+ * (particles, simulations...).
*
- * \param scene is only used to set current frame in some cases, and may be NULL.
+ * \param scene: is only used to set current frame in some cases, and may be NULL.
*/
ModifierData *ED_object_modifier_add(
ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
{
ModifierData *md = NULL, *new_md = NULL;
- const ModifierTypeInfo *mti = modifierType_getInfo(type);
+ const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
/* Check compatibility of modifier [T25291, T50373]. */
if (!BKE_object_support_modifier_type_check(ob, type)) {
@@ -145,7 +161,7 @@ ModifierData *ED_object_modifier_add(
}
if (mti->flags & eModifierTypeFlag_Single) {
- if (modifiers_findByType(ob, type)) {
+ if (BKE_modifiers_findby_type(ob, type)) {
BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
return NULL;
}
@@ -159,12 +175,12 @@ ModifierData *ED_object_modifier_add(
}
else {
/* get new modifier data to add */
- new_md = modifier_new(type);
+ new_md = BKE_modifier_new(type);
if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
md = ob->modifiers.first;
- while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) {
+ while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) {
md = md->next;
}
@@ -180,7 +196,7 @@ ModifierData *ED_object_modifier_add(
/* make sure modifier data has unique name */
- modifier_unique_name(&ob->modifiers, new_md);
+ BKE_modifier_unique_name(&ob->modifiers, new_md);
/* special cases */
if (type == eModifierType_Softbody) {
@@ -367,7 +383,7 @@ static bool object_modifier_remove(Main *bmain,
}
BLI_remlink(&ob->modifiers, md);
- modifier_free(md);
+ BKE_modifier_free(md);
BKE_object_free_derived_caches(ob);
return 1;
@@ -417,10 +433,10 @@ void ED_object_modifier_clear(Main *bmain, Object *ob)
int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
{
if (md->prev) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
if (mti->type != eModifierTypeType_OnlyDeform) {
- const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
+ const ModifierTypeInfo *nmti = BKE_modifier_get_info(md->prev->type);
if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) {
BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
@@ -438,10 +454,10 @@ int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md
int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
{
if (md->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
- const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
+ const ModifierTypeInfo *nmti = BKE_modifier_get_info(md->next->type);
if (nmti->type != eModifierTypeType_OnlyDeform) {
BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
@@ -604,7 +620,7 @@ static int modifier_apply_shape(Main *bmain,
Object *ob,
ModifierData *md_eval)
{
- const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type);
+ const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type);
if (mti->isDisabled && mti->isDisabled(scene, md_eval, 0)) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
@@ -628,7 +644,7 @@ static int modifier_apply_shape(Main *bmain,
Key *key = me->key;
KeyBlock *kb;
- if (!modifier_isSameTopology(md_eval) || mti->type == eModifierTypeType_NonGeometrical) {
+ if (!BKE_modifier_is_same_topology(md_eval) || mti->type == eModifierTypeType_NonGeometrical) {
BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes");
return 0;
}
@@ -654,6 +670,7 @@ static int modifier_apply_shape(Main *bmain,
BKE_id_free(NULL, mesh_applied);
}
else {
+ /* TODO: implement for hair, pointclouds and volumes. */
BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
return 0;
}
@@ -663,7 +680,7 @@ static int modifier_apply_shape(Main *bmain,
static int modifier_apply_obdata(
ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md_eval)
{
- const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type);
+ const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type);
if (mti->isDisabled && mti->isDisabled(scene, md_eval, 0)) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
@@ -686,7 +703,7 @@ static int modifier_apply_obdata(
}
if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
- if (!multiresModifier_reshapeFromDeformModifier(depsgraph, mmd, ob, md_eval)) {
+ if (!multiresModifier_reshapeFromDeformModifier(depsgraph, ob, mmd, md_eval)) {
BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
return 0;
}
@@ -732,6 +749,7 @@ static int modifier_apply_obdata(
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
else {
+ /* TODO: implement for hair, pointclouds and volumes. */
BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
return 0;
}
@@ -754,30 +772,30 @@ static int modifier_apply_obdata(
return 1;
}
-int ED_object_modifier_apply(Main *bmain,
- ReportList *reports,
- Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- ModifierData *md,
- int mode)
+bool ED_object_modifier_apply(Main *bmain,
+ ReportList *reports,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ ModifierData *md,
+ int mode)
{
int prev_mode;
if (BKE_object_is_in_editmode(ob)) {
BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode");
- return 0;
+ return false;
}
- else if (((ID *)ob->data)->us > 1) {
+ else if (ID_REAL_USERS(ob->data) > 1) {
BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
- return 0;
+ return false;
}
else if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) &&
- (modifier_isSameTopology(md) == false)) {
+ (BKE_modifier_is_same_topology(md) == false)) {
BKE_report(reports,
RPT_ERROR,
"Constructive modifier cannot be applied to multi-res data in sculpt mode");
- return 0;
+ return false;
}
if (md != ob->modifiers.first) {
@@ -787,7 +805,7 @@ int ED_object_modifier_apply(Main *bmain,
/* Get evaluated modifier, so object links pointer to evaluated data,
* but still use original object it is applied to the original mesh. */
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- ModifierData *md_eval = (ob_eval) ? modifiers_findByName(ob_eval, md->name) : md;
+ ModifierData *md_eval = (ob_eval) ? BKE_modifiers_findny_name(ob_eval, md->name) : md;
/* allow apply of a not-realtime modifier, by first re-enabling realtime. */
prev_mode = md_eval->mode;
@@ -796,38 +814,42 @@ int ED_object_modifier_apply(Main *bmain,
if (mode == MODIFIER_APPLY_SHAPE) {
if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md_eval)) {
md_eval->mode = prev_mode;
- return 0;
+ return false;
}
}
else {
if (!modifier_apply_obdata(reports, depsgraph, scene, ob, md_eval)) {
md_eval->mode = prev_mode;
- return 0;
+ return false;
}
}
md_eval->mode = prev_mode;
BLI_remlink(&ob->modifiers, md);
- modifier_free(md);
+ BKE_modifier_free(md);
BKE_object_free_derived_caches(ob);
- return 1;
+ return true;
}
int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
{
ModifierData *nmd;
- nmd = modifier_new(md->type);
- modifier_copyData(md, nmd);
+ nmd = BKE_modifier_new(md->type);
+ BKE_modifier_copydata(md, nmd);
BLI_insertlinkafter(&ob->modifiers, md, nmd);
- modifier_unique_name(&ob->modifiers, nmd);
+ BKE_modifier_unique_name(&ob->modifiers, nmd);
return 1;
}
-/************************ add modifier operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Add Modifier Operator
+ * \{ */
static int modifier_add_exec(bContext *C, wmOperator *op)
{
@@ -864,7 +886,7 @@ static const EnumPropertyItem *modifier_add_itemf(bContext *C,
md_item = &rna_enum_object_modifier_type_items[a];
if (md_item->identifier[0]) {
- mti = modifierType_getInfo(md_item->value);
+ mti = BKE_modifier_get_info(md_item->value);
if (mti->flags & eModifierTypeFlag_NoUserAdd) {
continue;
@@ -919,7 +941,13 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot)
ot->prop = prop;
}
-/********** generic functions for operators using mod names and data context *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Generic Functions For Operators
+ *
+ * Using modifier names and data context.
+ * \{ */
bool edit_modifier_poll_generic(bContext *C,
StructRNA *rna_type,
@@ -931,28 +959,28 @@ bool edit_modifier_poll_generic(bContext *C,
ModifierData *mod = ptr.data; /* May be NULL. */
if (!ob || ID_IS_LINKED(ob)) {
- return 0;
+ return false;
}
if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
- return 0;
+ return false;
}
if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) {
- return 0;
+ return false;
}
if (ID_IS_OVERRIDE_LIBRARY(ob)) {
if ((mod != NULL) && (mod->flag & eModifierFlag_OverrideLibrary_Local) == 0) {
CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override");
- return 0;
+ return false;
}
}
if (!is_editmode_allowed && CTX_data_edit_object(C) != NULL) {
CTX_wm_operator_poll_msg_set(C, "This modifier operation is not allowed from Edit mode");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
bool edit_modifier_poll(bContext *C)
@@ -992,7 +1020,7 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
ModifierData *md;
RNA_string_get(op->ptr, "modifier", modifier_name);
- md = modifiers_findByName(ob, modifier_name);
+ md = BKE_modifiers_findny_name(ob, modifier_name);
if (md && type != 0 && md->type != type) {
md = NULL;
@@ -1001,7 +1029,11 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
return md;
}
-/************************ remove modifier operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Remove Modifier Operator
+ * \{ */
static int modifier_remove_exec(bContext *C, wmOperator *op)
{
@@ -1053,7 +1085,11 @@ void OBJECT_OT_modifier_remove(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/************************ move up modifier operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Move Up Modifier Operator
+ * \{ */
static int modifier_move_up_exec(bContext *C, wmOperator *op)
{
@@ -1095,7 +1131,11 @@ void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/************************ move down modifier operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Move Down Modifier Operator
+ * \{ */
static int modifier_move_down_exec(bContext *C, wmOperator *op)
{
@@ -1137,7 +1177,37 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/************************ apply modifier operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Apply Modifier Operator
+ * \{ */
+
+static bool modifier_apply_poll(bContext *C)
+{
+ if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false)) {
+ return false;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
+ Object *ob = (ptr.owner_id != NULL) ? (Object *)ptr.owner_id : ED_object_active_context(C);
+ ModifierData *md = ptr.data; /* May be NULL. */
+
+ if ((ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) {
+ CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied to multi-user data");
+ return false;
+ }
+ else if (md != NULL) {
+ if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) &&
+ (BKE_modifier_is_same_topology(md) == false)) {
+ CTX_wm_operator_poll_msg_set(
+ C, "Constructive modifier cannot be applied to multi-res data in sculpt mode");
+ return false;
+ }
+ }
+ return true;
+}
static int modifier_apply_exec(bContext *C, wmOperator *op)
{
@@ -1187,7 +1257,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
ot->invoke = modifier_apply_invoke;
ot->exec = modifier_apply_exec;
- ot->poll = edit_modifier_poll;
+ ot->poll = modifier_apply_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -1201,7 +1271,11 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/************************ convert modifier operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Convert Modifier Operator
+ * \{ */
static int modifier_convert_exec(bContext *C, wmOperator *op)
{
@@ -1248,7 +1322,11 @@ void OBJECT_OT_modifier_convert(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/************************ copy modifier operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Copy Modifier Operator
+ * \{ */
static int modifier_copy_exec(bContext *C, wmOperator *op)
{
@@ -1290,7 +1368,11 @@ void OBJECT_OT_modifier_copy(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/************* multires delete higher levels operator ****************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Multires Delete Higher Levels Operator
+ * \{ */
static bool multires_poll(bContext *C)
{
@@ -1345,30 +1427,54 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/****************** multires subdivide operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Multires Subdivide Operator
+ * \{ */
+
+static EnumPropertyItem prop_multires_subdivide_mode_type[] = {
+ {MULTIRES_SUBDIVIDE_CATMULL_CLARK,
+ "CATMULL_CLARK",
+ 0,
+ "Catmull-Clark",
+ "Create a new level using Catmull-Clark subdivisions"},
+ {MULTIRES_SUBDIVIDE_SIMPLE,
+ "SIMPLE",
+ 0,
+ "Simple",
+ "Create a new level using simple subdivisions"},
+ {MULTIRES_SUBDIVIDE_LINEAR,
+ "LINEAR",
+ 0,
+ "Linear",
+ "Create a new level using linear interpolation of the sculpted displacement"},
+ {0, NULL, 0, NULL, NULL},
+};
static int multires_subdivide_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
+ Object *object = ED_object_active_context(C);
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
- op, ob, eModifierType_Multires);
+ op, object, eModifierType_Multires);
if (!mmd) {
return OPERATOR_CANCELLED;
}
- multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple);
+ const eMultiresSubdivideModeType subdivide_mode = (eMultiresSubdivideModeType)(
+ RNA_enum_get(op->ptr, "mode"));
+ multiresModifier_subdivide(object, mmd, subdivide_mode);
ED_object_iter_other(
- CTX_data_main(C), ob, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
+ CTX_data_main(C), object, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object);
- if (ob->mode & OB_MODE_SCULPT) {
+ if (object->mode & OB_MODE_SCULPT) {
/* ensure that grid paint mask layer is created */
- BKE_sculpt_mask_layers_ensure(ob, mmd);
+ BKE_sculpt_mask_layers_ensure(object, mmd);
}
return OPERATOR_FINISHED;
@@ -1397,9 +1503,19 @@ void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
+ RNA_def_enum(ot->srna,
+ "mode",
+ prop_multires_subdivide_mode_type,
+ MULTIRES_SUBDIVIDE_CATMULL_CLARK,
+ "Subdivision Mode",
+ "How the mesh is going to be subdivided to create a new level");
}
-/****************** multires reshape operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Multires Reshape Operator
+ * \{ */
static int multires_reshape_exec(bContext *C, wmOperator *op)
{
@@ -1466,7 +1582,11 @@ void OBJECT_OT_multires_reshape(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/****************** multires save external operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Multires Save External Operator
+ * \{ */
static int multires_external_save_exec(bContext *C, wmOperator *op)
{
@@ -1555,7 +1675,11 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/****************** multires pack operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Multires Pack Operator
+ * \{ */
static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1585,22 +1709,31 @@ void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/********************* multires apply base ***********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Multires Apply Base
+ * \{ */
+
static int multires_base_apply_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Object *object = ED_object_active_context(C);
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
- op, ob, eModifierType_Multires);
+ op, object, eModifierType_Multires);
if (!mmd) {
return OPERATOR_CANCELLED;
}
- multiresModifier_base_apply(mmd, scene, ob);
+ ED_sculpt_undo_push_multires_mesh_begin(C, op->type->name);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ multiresModifier_base_apply(depsgraph, object, mmd);
+
+ ED_sculpt_undo_push_multires_mesh_end(C, op->type->name);
+
+ DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object);
return OPERATOR_FINISHED;
}
@@ -1626,11 +1759,128 @@ void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
ot->exec = multires_base_apply_exec;
/* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
+}
+
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Multires Unsubdivide
+ * \{ */
+
+static int multires_unsubdivide_exec(bContext *C, wmOperator *op)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Object *object = ED_object_active_context(C);
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, object, eModifierType_Multires);
+
+ if (!mmd) {
+ return OPERATOR_CANCELLED;
+ }
+
+ int new_levels = multiresModifier_rebuild_subdiv(depsgraph, object, mmd, 1, true);
+ if (new_levels == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Not valid subdivisions found to rebuild a lower level");
+ return OPERATOR_CANCELLED;
+ }
+
+ DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object);
+
+ return OPERATOR_FINISHED;
+}
+
+static int multires_unsubdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (edit_modifier_invoke_properties(C, op)) {
+ return multires_unsubdivide_exec(C, op);
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void OBJECT_OT_multires_unsubdivide(wmOperatorType *ot)
+{
+ ot->name = "Unsubdivide";
+ ot->description = "Rebuild a lower subdivision level of the current base mesh";
+ ot->idname = "OBJECT_OT_multires_unsubdivide";
+
+ ot->poll = multires_poll;
+ ot->invoke = multires_unsubdivide_invoke;
+ ot->exec = multires_unsubdivide_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
+}
+
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Multires Rebuild Subdivisions
+ * \{ */
+
+static int multires_rebuild_subdiv_exec(bContext *C, wmOperator *op)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Object *object = ED_object_active_context(C);
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, object, eModifierType_Multires);
+
+ if (!mmd) {
+ return OPERATOR_CANCELLED;
+ }
+
+ int new_levels = multiresModifier_rebuild_subdiv(depsgraph, object, mmd, INT_MAX, false);
+ if (new_levels == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Not valid subdivisions found to rebuild lower levels");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_reportf(op->reports, RPT_INFO, "%d new levels rebuilt", new_levels);
+
+ DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object);
+
+ return OPERATOR_FINISHED;
+}
+
+static int multires_rebuild_subdiv_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
+{
+ if (edit_modifier_invoke_properties(C, op)) {
+ return multires_rebuild_subdiv_exec(C, op);
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void OBJECT_OT_multires_rebuild_subdiv(wmOperatorType *ot)
+{
+ ot->name = "Rebuild Lower Subdivisions";
+ ot->description =
+ "Rebuilds all possible subdivisions levels to generate a lower resolution base mesh";
+ ot->idname = "OBJECT_OT_multires_rebuild_subdiv";
+
+ ot->poll = multires_poll;
+ ot->invoke = multires_rebuild_subdiv_invoke;
+ ot->exec = multires_rebuild_subdiv_exec;
+
+ /* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
-/************************** skin modifier ***********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Skin Modifier
+ * \{ */
static void modifier_skin_customdata_delete(Object *ob)
{
@@ -1962,7 +2212,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
arm_ob = modifier_skin_armature_create(depsgraph, bmain, scene, ob);
/* add a modifier to connect the new armature to the mesh */
- arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature);
+ arm_md = (ArmatureModifierData *)BKE_modifier_new(eModifierType_Armature);
if (arm_md) {
skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin);
BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md);
@@ -2002,7 +2252,11 @@ void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
-/************************ delta mush bind operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Delta Mesh Bind Operator
+ * \{ */
static bool correctivesmooth_poll(bContext *C)
{
@@ -2022,7 +2276,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) {
+ if (!BKE_modifier_is_enabled(scene, &csmd->modifier, eModifierMode_Realtime)) {
BKE_report(op->reports, RPT_ERROR, "Modifier is disabled");
return OPERATOR_CANCELLED;
}
@@ -2039,8 +2293,8 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
else {
/* Signal to modifier to recalculate. */
CorrectiveSmoothModifierData *csmd_eval = (CorrectiveSmoothModifierData *)
- modifier_get_evaluated(depsgraph, ob, &csmd->modifier);
- csmd_eval->bind_coords_num = (unsigned int)-1;
+ BKE_modifier_get_evaluated(depsgraph, ob, &csmd->modifier);
+ csmd_eval->bind_coords_num = (uint)-1;
/* Force modifier to run, it will call binding routine
* (this has to happen outside of depsgraph evaluation). */
@@ -2080,7 +2334,11 @@ void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/************************ mdef bind operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Mesh Deform Bind Operator
+ * \{ */
static bool meshdeform_poll(bContext *C)
{
@@ -2114,7 +2372,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
else {
/* Force modifier to run, it will call binding routine
* (this has to happen outside of depsgraph evaluation). */
- MeshDeformModifierData *mmd_eval = (MeshDeformModifierData *)modifier_get_evaluated(
+ MeshDeformModifierData *mmd_eval = (MeshDeformModifierData *)BKE_modifier_get_evaluated(
depsgraph, ob, &mmd->modifier);
mmd_eval->bindfunc = ED_mesh_deform_bind_callback;
object_force_modifier_bind_simple_options(depsgraph, ob, &mmd->modifier);
@@ -2153,7 +2411,11 @@ void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/****************** explode refresh operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Explode Refresh Operator
+ * \{ */
static bool explode_poll(bContext *C)
{
@@ -2203,7 +2465,11 @@ void OBJECT_OT_explode_refresh(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/****************** ocean bake operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Ocean Bake Operator
+ * \{ */
static bool ocean_bake_poll(bContext *C)
{
@@ -2311,7 +2577,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
}
och = BKE_ocean_init_cache(omd->cachepath,
- modifier_path_relbase(bmain, ob),
+ BKE_modifier_path_relbase(bmain, ob),
omd->bakestart,
omd->bakeend,
omd->wave_scale,
@@ -2330,7 +2596,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
* No drivers or other modifier parameters. */
/* TODO(sergey): This operates on an original data, so no flush is needed. However, baking
* usually should happen on an evaluated objects, so this seems to be deeper issue here. */
- BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false);
+ BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false);
och->time[i] = omd->time;
i++;
@@ -2405,7 +2671,11 @@ void OBJECT_OT_ocean_bake(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it");
}
-/************************ LaplacianDeform bind operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Laplaciandeform Bind Operator
+ * \{ */
static bool laplaciandeform_poll(bContext *C)
{
@@ -2430,8 +2700,8 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
lmd->flag |= MOD_LAPLACIANDEFORM_BIND;
}
- LaplacianDeformModifierData *lmd_eval = (LaplacianDeformModifierData *)modifier_get_evaluated(
- depsgraph, ob, &lmd->modifier);
+ LaplacianDeformModifierData *lmd_eval = (LaplacianDeformModifierData *)
+ BKE_modifier_get_evaluated(depsgraph, ob, &lmd->modifier);
lmd_eval->flag = lmd->flag;
/* Force modifier to run, it will call binding routine
@@ -2480,7 +2750,11 @@ void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/************************ sdef bind operator *********************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Surface Deform Bind Operator
+ * \{ */
static bool surfacedeform_bind_poll(bContext *C)
{
@@ -2505,7 +2779,7 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
smd->flags |= MOD_SDEF_BIND;
}
- SurfaceDeformModifierData *smd_eval = (SurfaceDeformModifierData *)modifier_get_evaluated(
+ SurfaceDeformModifierData *smd_eval = (SurfaceDeformModifierData *)BKE_modifier_get_evaluated(
depsgraph, ob, &smd->modifier);
smd_eval->flags = smd->flags;
@@ -2544,3 +2818,5 @@ void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
+
+/** \} */
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index f6b08b953a4..819b6c18a44 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -21,8 +21,8 @@
* \ingroup edobj
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -37,9 +37,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "ED_object.h"
#include "DEG_depsgraph.h"
@@ -109,6 +109,12 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_light_add);
WM_operatortype_append(OBJECT_OT_camera_add);
WM_operatortype_append(OBJECT_OT_speaker_add);
+#ifdef WITH_NEW_OBJECT_TYPES
+ WM_operatortype_append(OBJECT_OT_hair_add);
+ WM_operatortype_append(OBJECT_OT_pointcloud_add);
+#endif
+ WM_operatortype_append(OBJECT_OT_volume_add);
+ WM_operatortype_append(OBJECT_OT_volume_import);
WM_operatortype_append(OBJECT_OT_add);
WM_operatortype_append(OBJECT_OT_add_named);
WM_operatortype_append(OBJECT_OT_effector_add);
@@ -131,6 +137,8 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_multires_reshape);
WM_operatortype_append(OBJECT_OT_multires_higher_levels_delete);
WM_operatortype_append(OBJECT_OT_multires_base_apply);
+ WM_operatortype_append(OBJECT_OT_multires_unsubdivide);
+ WM_operatortype_append(OBJECT_OT_multires_rebuild_subdiv);
WM_operatortype_append(OBJECT_OT_multires_external_save);
WM_operatortype_append(OBJECT_OT_multires_external_pack);
WM_operatortype_append(OBJECT_OT_skin_root_mark);
@@ -259,6 +267,8 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_hide_collection);
WM_operatortype_append(OBJECT_OT_voxel_remesh);
+ WM_operatortype_append(OBJECT_OT_voxel_size_edit);
+
WM_operatortype_append(OBJECT_OT_quadriflow_remesh);
}
diff --git a/source/blender/editors/object/object_random.c b/source/blender/editors/object/object_random.c
index 43aaecb887b..a6958c798f1 100644
--- a/source/blender/editors/object/object_random.c
+++ b/source/blender/editors/object/object_random.c
@@ -50,7 +50,7 @@ static bool object_rand_transverts(TransVertStore *tvs,
const float offset,
const float uniform,
const float normal_factor,
- const unsigned int seed)
+ const uint seed)
{
bool use_normal = (normal_factor != 0.0f);
struct RNG *rng;
@@ -100,7 +100,7 @@ static int object_rand_verts_exec(bContext *C, wmOperator *op)
const float offset = RNA_float_get(op->ptr, "offset");
const float uniform = RNA_float_get(op->ptr, "uniform");
const float normal_factor = RNA_float_get(op->ptr, "normal");
- const unsigned int seed = RNA_int_get(op->ptr, "seed");
+ const uint seed = RNA_int_get(op->ptr, "seed");
bool changed_multi = false;
uint objects_len = 0;
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index f9e2a2b8a1a..bfceaef4644 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -33,8 +33,8 @@
#include "DNA_collection_types.h"
#include "DNA_constraint_types.h"
#include "DNA_gpencil_types.h"
-#include "DNA_light_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_light_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
@@ -44,36 +44,37 @@
#include "DNA_vfont_types.h"
#include "DNA_world_types.h"
-#include "BLI_math.h"
-#include "BLI_listbase.h"
+#include "BLI_kdtree.h"
#include "BLI_linklist.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_string.h"
-#include "BLI_kdtree.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_action.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_armature.h"
#include "BKE_camera.h"
#include "BKE_collection.h"
-#include "BKE_context.h"
#include "BKE_constraint.h"
+#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
-#include "BKE_gpencil.h"
#include "BKE_fcurve.h"
+#include "BKE_gpencil.h"
+#include "BKE_hair.h"
#include "BKE_idprop.h"
-#include "BKE_light.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
+#include "BKE_light.h"
#include "BKE_lightprobe.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -82,10 +83,12 @@
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_pointcloud.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_speaker.h"
#include "BKE_texture.h"
+#include "BKE_volume.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -105,14 +108,16 @@
#include "ED_curve.h"
#include "ED_gpencil.h"
#include "ED_keyframing.h"
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "object_intern.h"
-/*********************** Make Vertex Parent Operator ************************/
+/* ------------------------------------------------------------------- */
+/** \name Make Vertex Parent Operator
+ * \{ */
static bool vertex_parent_set_poll(bContext *C)
{
@@ -328,7 +333,11 @@ void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/********************** Make Proxy Operator *************************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Make Proxy Operator
+ * \{ */
/* set the object to proxify */
static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -408,7 +417,12 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
* TODO(sergey): We really need to get rid of this bi-directional links
* in proxies with something like library overrides.
*/
- newob->proxy->proxy_from = newob;
+ if (newob->proxy != NULL) {
+ newob->proxy->proxy_from = newob;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Unable to assign proxy");
+ }
/* depsgraph flushes are needed for the new data */
DEG_relations_tag_update(bmain);
@@ -482,13 +496,11 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot)
ot->prop = prop;
}
-/********************** Clear Parent Operator ******************* */
+/** \} */
-typedef enum eObClearParentTypes {
- CLEAR_PARENT_ALL = 0,
- CLEAR_PARENT_KEEP_TRANSFORM,
- CLEAR_PARENT_INVERSE,
-} eObClearParentTypes;
+/* ------------------------------------------------------------------- */
+/** \name Clear Parent Operator
+ * \{ */
EnumPropertyItem prop_clear_parent_types[] = {
{CLEAR_PARENT_ALL,
@@ -545,7 +557,7 @@ static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
/* free modifier if match */
if (free) {
BLI_remlink(&ob->modifiers, md);
- modifier_free(md);
+ BKE_modifier_free(md);
}
}
}
@@ -616,15 +628,17 @@ void OBJECT_OT_parent_clear(wmOperatorType *ot)
ot->invoke = WM_menu_invoke;
ot->exec = parent_clear_exec;
- ot->poll = ED_operator_object_active_editable;
-
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", "");
}
-/* ******************** Make Parent Operator *********************** */
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Make Parent Operator
+ * \{ */
void ED_object_parent(Object *ob, Object *par, const int type, const char *substr)
{
@@ -709,8 +723,8 @@ bool ED_object_parent_set(ReportList *reports,
/* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */
if (partype == PAR_FOLLOW) {
/* get or create F-Curve */
- bAction *act = verify_adt_action(bmain, &cu->id, 1);
- FCurve *fcu = verify_fcurve(bmain, act, NULL, NULL, "eval_time", 0, 1);
+ bAction *act = ED_id_action_ensure(bmain, &cu->id);
+ FCurve *fcu = ED_action_fcurve_ensure(bmain, act, NULL, NULL, "eval_time", 0);
/* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
@@ -789,7 +803,7 @@ bool ED_object_parent_set(ReportList *reports,
switch (partype) {
case PAR_CURVE: /* curve deform */
- if (modifiers_isDeformedByCurve(ob) != par) {
+ if (BKE_modifiers_is_deformed_by_curve(ob) != par) {
md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve);
if (md) {
((CurveModifierData *)md)->object = par;
@@ -800,7 +814,7 @@ bool ED_object_parent_set(ReportList *reports,
}
break;
case PAR_LATTICE: /* lattice deform */
- if (modifiers_isDeformedByLattice(ob) != par) {
+ if (BKE_modifiers_is_deformed_by_lattice(ob) != par) {
md = ED_object_modifier_add(
reports, bmain, scene, ob, NULL, eModifierType_Lattice);
if (md) {
@@ -809,7 +823,7 @@ bool ED_object_parent_set(ReportList *reports,
}
break;
default: /* armature deform */
- if (modifiers_isDeformedByArmature(ob) != par) {
+ if (BKE_modifiers_is_deformed_by_armature(ob) != par) {
md = ED_object_modifier_add(
reports, bmain, scene, ob, NULL, eModifierType_Armature);
if (md) {
@@ -885,7 +899,10 @@ bool ED_object_parent_set(ReportList *reports,
invert_m4_m4(ob->parentinv, workob.obmat);
}
else if (pararm && (ob->type == OB_GPENCIL) && (par->type == OB_ARMATURE)) {
- if (partype == PAR_ARMATURE_NAME) {
+ if (partype == PAR_ARMATURE) {
+ ED_gpencil_add_armature(C, reports, ob, par);
+ }
+ else if (partype == PAR_ARMATURE_NAME) {
ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_NAME);
}
else if ((partype == PAR_ARMATURE_AUTO) || (partype == PAR_ARMATURE_ENVELOPE)) {
@@ -1056,7 +1073,9 @@ static int parent_set_invoke_menu(bContext *C, wmOperatorType *ot)
if (parent->type == OB_ARMATURE) {
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE);
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_NAME);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_ENVELOPE);
+ if (!has_children_of_type.gpencil) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_ENVELOPE);
+ }
if (has_children_of_type.mesh || has_children_of_type.gpencil) {
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_AUTO);
}
@@ -1141,7 +1160,11 @@ void OBJECT_OT_parent_set(wmOperatorType *ot)
"Apply transformation before parenting");
}
-/* ************ Make Parent Without Inverse Operator ******************* */
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Make Parent Without Inverse Operator
+ * \{ */
static int parent_noinv_set_exec(bContext *C, wmOperator *op)
{
@@ -1194,7 +1217,11 @@ void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************** Clear Track Operator ******************* */
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Clear Track Operator
+ * \{ */
enum {
CLEAR_TRACK = 1,
@@ -1270,7 +1297,11 @@ void OBJECT_OT_track_clear(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
}
-/************************** Make Track Operator *****************************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Make Track Operator
+ * \{ */
enum {
CREATE_TRACK_DAMPTRACK = 1,
@@ -1389,10 +1420,14 @@ void OBJECT_OT_track_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
}
-/************************** Link to Scene Operator *****************************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Link to Scene Operator
+ * \{ */
#if 0
-static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
+static void link_to_scene(Main *UNUSED(bmain), ushort UNUSED(nr))
{
Scene *sce = (Scene *)BLI_findlink(&bmain->scene, G.curscreen->scenenr - 1);
Base *base, *nbase;
@@ -1534,16 +1569,16 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
ob_dst->data = obdata_id;
/* if amount of material indices changed: */
- test_object_materials(bmain, ob_dst, ob_dst->data);
+ BKE_object_materials_test(bmain, ob_dst, ob_dst->data);
DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
break;
case MAKE_LINKS_MATERIALS:
/* new approach, using functions from kernel */
for (a = 0; a < ob_src->totcol; a++) {
- Material *ma = give_current_material(ob_src, a + 1);
+ Material *ma = BKE_object_material_get(ob_src, a + 1);
/* also works with `ma == NULL` */
- assign_material(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF);
+ BKE_object_material_assign(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF);
}
DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
break;
@@ -1586,7 +1621,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob_dst->id, ID_RECALC_COPY_ON_WRITE);
break;
case MAKE_LINKS_MODIFIERS:
- BKE_object_link_modifiers(scene, ob_dst, ob_src);
+ BKE_object_link_modifiers(ob_dst, ob_src);
DEG_id_tag_update(&ob_dst->id,
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
break;
@@ -1705,7 +1740,11 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", "");
}
-/**************************** Make Single User ********************************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Make Single User Operator
+ * \{ */
static void libblock_relink_collection(Collection *collection, const bool do_collection)
{
@@ -1717,7 +1756,7 @@ static void libblock_relink_collection(Collection *collection, const bool do_col
BKE_libblock_relink_to_newid(&cob->ob->id);
}
- for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
libblock_relink_collection(child->collection, true);
}
}
@@ -1736,7 +1775,7 @@ static Collection *single_object_users_collection(Main *bmain,
}
/* We do not remap to new objects here, this is done in separate step. */
- for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
Object *ob = cob->ob;
/* an object may be in more than one collection */
if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
@@ -1900,6 +1939,15 @@ static void single_obdata_users(
case OB_GPENCIL:
ob->data = ID_NEW_SET(ob->data, BKE_gpencil_copy(bmain, ob->data));
break;
+ case OB_HAIR:
+ ob->data = ID_NEW_SET(ob->data, BKE_hair_copy(bmain, ob->data));
+ break;
+ case OB_POINTCLOUD:
+ ob->data = ID_NEW_SET(ob->data, BKE_pointcloud_copy(bmain, ob->data));
+ break;
+ case OB_VOLUME:
+ ob->data = ID_NEW_SET(ob->data, BKE_volume_copy(bmain, ob->data));
+ break;
default:
printf("ERROR %s: can't copy %s\n", __func__, id->name);
BLI_assert(!"This should never happen.");
@@ -1950,7 +1998,7 @@ static void single_mat_users(
FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
if (!ID_IS_LINKED(ob)) {
for (a = 1; a <= ob->totcol; a++) {
- ma = give_current_material(ob, a);
+ ma = BKE_object_material_get(ob, a);
if (ma) {
/* do not test for LIB_TAG_NEW or use newid:
* this functions guaranteed delivers single_users! */
@@ -1960,7 +2008,7 @@ static void single_mat_users(
BKE_animdata_copy_id_action(bmain, &man->id, false);
man->id.us = 0;
- assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
+ BKE_object_material_assign(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
}
}
}
@@ -2061,7 +2109,7 @@ void ED_object_single_users(Main *bmain,
if (scene->nodetree) {
IDP_RelinkProperty(scene->nodetree->id.properties);
- for (bNode *node = scene->nodetree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &scene->nodetree->nodes) {
IDP_RelinkProperty(node->prop);
}
}
@@ -2078,7 +2126,11 @@ void ED_object_single_users(Main *bmain,
DEG_relations_tag_update(bmain);
}
-/******************************* Make Local ***********************************/
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Make Local Operator
+ * \{ */
enum {
MAKE_LOCAL_SELECT_OB = 1,
@@ -2087,11 +2139,9 @@ enum {
MAKE_LOCAL_ALL = 4,
};
-static int tag_localizable_looper(void *UNUSED(user_data),
- ID *UNUSED(self_id),
- ID **id_pointer,
- const int UNUSED(cb_flag))
+static int tag_localizable_looper(LibraryIDLinkCallbackData *cb_data)
{
+ ID **id_pointer = cb_data->id_pointer;
if (*id_pointer) {
(*id_pointer)->tag &= ~LIB_TAG_DOIT;
}
@@ -2198,7 +2248,7 @@ static void make_local_animdata_tag(AnimData *adt)
/* TODO: need to handle the ID-targets too? */
/* NLA Data */
- for (NlaTrack *nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
make_local_animdata_tag_strips(&nlt->strips);
}
}
@@ -2262,7 +2312,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
}
}
- matarar = (Material ***)give_matarar(ob);
+ matarar = BKE_object_material_array_p(ob);
if (matarar) {
for (a = 0; a < ob->totcol; a++) {
ma = (*matarar)[a];
@@ -2320,6 +2370,12 @@ void OBJECT_OT_make_local(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Make Library Override Operator
+ * \{ */
+
static void make_override_library_tag_object(Object *obact, Object *ob)
{
if (ob == obact) {
@@ -2453,7 +2509,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- success = BKE_override_library_create_from_tag(bmain);
+ success = BKE_lib_override_library_create_from_tag(bmain);
/* Instantiate our newly overridden objects in scene, if not yet done. */
Scene *scene = CTX_data_scene(C);
@@ -2472,7 +2528,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
/* Disabled for now, according to some artist this is probably not really useful anyway.
* And it breaks things like objects parented to bones
* (most likely due to missing proper setting of inverse parent matrix?)... */
- /* Note: we might even actually want to get rid of that instanciating empty... */
+ /* Note: we might even actually want to get rid of that instantiating empty... */
if (0 && new_ob->parent == NULL) {
new_ob->parent = obcollection;
}
@@ -2485,7 +2541,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
new_ob->id.override_library->flag &= ~OVERRIDE_LIBRARY_AUTO;
}
/* We still want to store all objects' current override status (i.e. change of parent). */
- BKE_override_library_operations_create(bmain, &new_ob->id, true);
+ BKE_lib_override_library_operations_create(bmain, &new_ob->id, true);
}
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
@@ -2520,7 +2576,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
make_override_library_tag_object(obact, ob);
}
- success = BKE_override_library_create_from_tag(bmain);
+ success = BKE_lib_override_library_create_from_tag(bmain);
/* Also, we'd likely want to lock by default things like
* transformations of implicitly overridden objects? */
@@ -2533,7 +2589,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
else {
/* For now, remapp all local usages of linked ID to local override one here. */
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true);
- success = (BKE_override_library_create_from_id(bmain, &obact->id, true) != NULL);
+ success = (BKE_lib_override_library_create_from_id(bmain, &obact->id, true) != NULL);
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
}
@@ -2547,7 +2603,7 @@ static bool make_override_library_poll(bContext *C)
Object *obact = CTX_data_active_object(C);
/* Object must be directly linked to be overridable. */
- return (BKE_override_library_is_enabled() && ED_operator_objectmode(C) && obact != NULL &&
+ return (BKE_lib_override_library_is_enabled() && ED_operator_objectmode(C) && obact != NULL &&
((ID_IS_LINKED(obact) && obact->id.tag & LIB_TAG_EXTERN) ||
(!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
ID_IS_LINKED(obact->instance_collection))));
@@ -2581,6 +2637,12 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot)
ot->prop = prop;
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Make Single User Operator
+ * \{ */
+
enum {
MAKE_SINGLE_USER_ALL = 1,
MAKE_SINGLE_USER_SELECTED = 2,
@@ -2611,6 +2673,9 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
if (RNA_boolean_get(op->ptr, "obdata")) {
single_obdata_users(bmain, scene, view_layer, v3d, flag);
+
+ /* Needed since some IDs were remapped? (incl. me->texcomesh, see T73797). */
+ update_deps = true;
}
if (RNA_boolean_get(op->ptr, "material")) {
@@ -2645,8 +2710,11 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
ot->description = "Make linked data local to each object";
ot->idname = "OBJECT_OT_make_single_user";
+ /* Note that the invoke callback is only used from operator search,
+ * otherwise this does nothing by default. */
+
/* api callbacks */
- ot->invoke = WM_menu_invoke;
+ ot->invoke = WM_operator_props_popup_confirm;
ot->exec = make_single_user_exec;
ot->poll = ED_operator_objectmode;
@@ -2663,6 +2731,12 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object");
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Drop Named Material on Object Operator
+ * \{ */
+
static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
@@ -2676,7 +2750,7 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_CANCELLED;
}
- assign_material(CTX_data_main(C), base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
+ BKE_object_material_assign(CTX_data_main(C), base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
DEG_id_tag_update(&base->object->id, ID_RECALC_TRANSFORM);
@@ -2706,6 +2780,12 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign");
}
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Unlink Object Operator
+ * \{ */
+
static int object_unlink_data_exec(bContext *C, wmOperator *op)
{
ID *id;
@@ -2756,3 +2836,5 @@ void OBJECT_OT_unlink_data(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_INTERNAL;
}
+
+/** \} */
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index 73fd45693a2..22869748b22 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -21,11 +21,11 @@
* \ingroup edobj
*/
+#include <ctype.h>
+#include <float.h>
+#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
-#include <float.h>
-#include <ctype.h>
#include "MEM_guardedalloc.h"
@@ -33,26 +33,29 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLT_translation.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
-#include "BKE_mesh_runtime.h"
#include "BKE_mesh_mirror.h"
+#include "BKE_mesh_remesh_voxel.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_shrinkwrap.h"
-#include "BKE_customdata.h"
-#include "BKE_mesh_remesh_voxel.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -61,19 +64,38 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
+#include "ED_space_api.h"
#include "ED_undo.h"
+#include "ED_view3d.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+
+#include "BLF_api.h"
#include "object_intern.h" // own include
+/* TODO(sebpa): unstable, can lead to unrecoverable errors. */
+// #define USE_MESH_CURVATURE
+
+/* -------------------------------------------------------------------- */
+/** \name Voxel Remesh Operator
+ * \{ */
+
static bool object_remesh_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
@@ -83,18 +105,18 @@ static bool object_remesh_poll(bContext *C)
}
if (BKE_object_is_in_editmode(ob)) {
- CTX_wm_operator_poll_msg_set(C, "The remesher cannot run from edit mode.");
+ CTX_wm_operator_poll_msg_set(C, "The remesher cannot run from edit mode");
return false;
}
if (ob->mode == OB_MODE_SCULPT && ob->sculpt->bm) {
- CTX_wm_operator_poll_msg_set(C, "The remesher cannot run with dyntopo activated.");
+ CTX_wm_operator_poll_msg_set(C, "The remesher cannot run with dyntopo activated");
return false;
}
- if (modifiers_usesMultires(ob)) {
+ if (BKE_modifiers_uses_multires(ob)) {
CTX_wm_operator_poll_msg_set(
- C, "The remesher cannot run with a Multires modifier in the modifier stack.");
+ C, "The remesher cannot run with a Multires modifier in the modifier stack");
return false;
}
@@ -109,7 +131,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
Mesh *new_mesh;
if (mesh->remesh_voxel_size <= 0.0f) {
- BKE_report(op->reports, RPT_ERROR, "Voxel remesher cannot run with a voxel size of 0.0.");
+ BKE_report(op->reports, RPT_ERROR, "Voxel remesher cannot run with a voxel size of 0.0");
return OPERATOR_CANCELLED;
}
@@ -122,7 +144,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
mesh, mesh->remesh_voxel_size, mesh->remesh_voxel_adaptivity, isovalue);
if (!new_mesh) {
- BKE_report(op->reports, RPT_ERROR, "Voxel remesher failed to create mesh.");
+ BKE_report(op->reports, RPT_ERROR, "Voxel remesher failed to create mesh");
return OPERATOR_CANCELLED;
}
@@ -135,16 +157,23 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
BKE_mesh_calc_normals(new_mesh);
}
- if (mesh->flag & ME_REMESH_REPROJECT_VOLUME) {
+ if (mesh->flag & ME_REMESH_REPROJECT_VOLUME || mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK ||
+ mesh->flag & ME_REMESH_REPROJECT_SCULPT_FACE_SETS) {
BKE_mesh_runtime_clear_geometry(mesh);
+ }
+
+ if (mesh->flag & ME_REMESH_REPROJECT_VOLUME) {
BKE_shrinkwrap_remesh_target_project(new_mesh, mesh, ob);
}
if (mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK) {
- BKE_mesh_runtime_clear_geometry(mesh);
BKE_mesh_remesh_reproject_paint_mask(new_mesh, mesh);
}
+ if (mesh->flag & ME_REMESH_REPROJECT_SCULPT_FACE_SETS) {
+ BKE_remesh_reproject_sculpt_face_sets(new_mesh, mesh);
+ }
+
BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true);
if (mesh->flag & ME_REMESH_SMOOTH_NORMALS) {
@@ -178,16 +207,413 @@ void OBJECT_OT_voxel_remesh(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Voxel Size Operator
+ * \{ */
+
+#define VOXEL_SIZE_EDIT_MAX_GRIDS_LINES 500
+#define VOXEL_SIZE_EDIT_MAX_STR_LEN 20
+
+typedef struct VoxelSizeEditCustomData {
+ void *draw_handle;
+ Object *active_object;
+
+ float init_mval[2];
+ float slow_mval[2];
+
+ bool slow_mode;
+
+ float init_voxel_size;
+ float slow_voxel_size;
+ float voxel_size;
+
+ float preview_plane[4][3];
+
+ float text_mat[4][4];
+} VoxelSizeEditCustomData;
+
+static void voxel_size_parallel_lines_draw(uint pos3d,
+ const float initial_co[3],
+ const float end_co[3],
+ const float length_co[3],
+ const float spacing)
+{
+ const float total_len = len_v3v3(initial_co, end_co);
+ const int tot_lines = (int)(total_len / spacing);
+ const int tot_lines_half = (tot_lines / 2) + 1;
+ float spacing_dir[3], lines_start[3];
+ float line_dir[3];
+ sub_v3_v3v3(spacing_dir, end_co, initial_co);
+ normalize_v3(spacing_dir);
+
+ sub_v3_v3v3(line_dir, length_co, initial_co);
+
+ if (tot_lines > VOXEL_SIZE_EDIT_MAX_GRIDS_LINES || tot_lines <= 1) {
+ return;
+ }
+
+ mid_v3_v3v3(lines_start, initial_co, end_co);
+
+ immBegin(GPU_PRIM_LINES, (uint)tot_lines_half * 2);
+ for (int i = 0; i < tot_lines_half; i++) {
+ float line_start[3];
+ float line_end[3];
+ madd_v3_v3v3fl(line_start, lines_start, spacing_dir, spacing * i);
+ add_v3_v3v3(line_end, line_start, line_dir);
+ immVertex3fv(pos3d, line_start);
+ immVertex3fv(pos3d, line_end);
+ }
+ immEnd();
+
+ mul_v3_fl(spacing_dir, -1.0f);
+
+ immBegin(GPU_PRIM_LINES, (uint)(tot_lines_half - 1) * 2);
+ for (int i = 1; i < tot_lines_half; i++) {
+ float line_start[3];
+ float line_end[3];
+ madd_v3_v3v3fl(line_start, lines_start, spacing_dir, spacing * i);
+ add_v3_v3v3(line_end, line_start, line_dir);
+ immVertex3fv(pos3d, line_start);
+ immVertex3fv(pos3d, line_end);
+ }
+ immEnd();
+}
+
+static void voxel_size_edit_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+{
+ VoxelSizeEditCustomData *cd = arg;
+
+ GPU_blend(true);
+ GPU_line_smooth(true);
+
+ uint pos3d = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ GPU_matrix_push();
+ GPU_matrix_mul(cd->active_object->obmat);
+
+ /* Draw Rect */
+ immUniformColor4f(0.9f, 0.9f, 0.9f, 0.8f);
+ GPU_line_width(3.0f);
+
+ immBegin(GPU_PRIM_LINES, 8);
+ immVertex3fv(pos3d, cd->preview_plane[0]);
+ immVertex3fv(pos3d, cd->preview_plane[1]);
+
+ immVertex3fv(pos3d, cd->preview_plane[1]);
+ immVertex3fv(pos3d, cd->preview_plane[2]);
+
+ immVertex3fv(pos3d, cd->preview_plane[2]);
+ immVertex3fv(pos3d, cd->preview_plane[3]);
+
+ immVertex3fv(pos3d, cd->preview_plane[3]);
+ immVertex3fv(pos3d, cd->preview_plane[0]);
+ immEnd();
+
+ /* Draw Grid */
+ GPU_line_width(1.0f);
+
+ const float total_len = len_v3v3(cd->preview_plane[0], cd->preview_plane[1]);
+ const int tot_lines = (int)(total_len / cd->voxel_size);
+
+ /* Smoothstep to reduce the alpha of the grid as the line number increases. */
+ const float a = VOXEL_SIZE_EDIT_MAX_GRIDS_LINES * 0.1f;
+ const float b = VOXEL_SIZE_EDIT_MAX_GRIDS_LINES;
+ const float x = clamp_f((tot_lines - a) / (b - a), 0.0f, 1.0);
+ const float alpha_factor = 1.0f - (x * x * (3.0f - 2.0f * x));
+
+ immUniformColor4f(0.9f, 0.9f, 0.9f, 0.75f * alpha_factor);
+ voxel_size_parallel_lines_draw(
+ pos3d, cd->preview_plane[0], cd->preview_plane[1], cd->preview_plane[3], cd->voxel_size);
+ voxel_size_parallel_lines_draw(
+ pos3d, cd->preview_plane[1], cd->preview_plane[2], cd->preview_plane[0], cd->voxel_size);
+
+ /* Draw text */
+ const uiStyle *style = UI_style_get();
+ const uiFontStyle *fstyle = &style->widget;
+ const int fontid = fstyle->uifont_id;
+ float strwidth, strheight;
+ short fstyle_points = fstyle->points;
+ char str[VOXEL_SIZE_EDIT_MAX_STR_LEN];
+ short strdrawlen = 0;
+
+ BLI_snprintf(str, VOXEL_SIZE_EDIT_MAX_STR_LEN, "%3.4f%%", cd->voxel_size);
+ strdrawlen = BLI_strlen_utf8(str);
+
+ immUnbindProgram();
+
+ GPU_matrix_push();
+ GPU_matrix_mul(cd->text_mat);
+ BLF_size(fontid, 10.0f * fstyle_points, U.dpi);
+ BLF_color3f(fontid, 1.0f, 1.0f, 1.0f);
+ BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight);
+ BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f);
+ BLF_draw(fontid, str, strdrawlen);
+ GPU_matrix_pop();
+
+ GPU_matrix_pop();
+
+ GPU_blend(false);
+ GPU_line_smooth(false);
+}
+
+static void voxel_size_edit_cancel(bContext *C, wmOperator *op)
+{
+ ARegion *ar = CTX_wm_region(C);
+ VoxelSizeEditCustomData *cd = op->customdata;
+
+ ED_region_draw_cb_exit(ar->type, cd->draw_handle);
+
+ MEM_freeN(op->customdata);
+
+ ED_workspace_status_text(C, NULL);
+}
+
+static int voxel_size_edit_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ VoxelSizeEditCustomData *cd = op->customdata;
+ Object *active_object = cd->active_object;
+ Mesh *mesh = (Mesh *)active_object->data;
+
+ /* Cancel modal operator */
+ if ((event->type == EVT_ESCKEY && event->val == KM_PRESS) ||
+ (event->type == RIGHTMOUSE && event->val == KM_PRESS)) {
+ voxel_size_edit_cancel(C, op);
+ ED_region_tag_redraw(ar);
+ return OPERATOR_FINISHED;
+ }
+
+ /* Finish modal operator */
+ if ((event->type == LEFTMOUSE && event->val == KM_RELEASE) ||
+ (event->type == EVT_RETKEY && event->val == KM_PRESS) ||
+ (event->type == EVT_PADENTER && event->val == KM_PRESS)) {
+ ED_region_draw_cb_exit(ar->type, cd->draw_handle);
+ mesh->remesh_voxel_size = cd->voxel_size;
+ MEM_freeN(op->customdata);
+ ED_region_tag_redraw(ar);
+ return OPERATOR_FINISHED;
+ }
+
+ float mval[2] = {event->mval[0], event->mval[1]};
+
+ float d = cd->init_mval[0] - mval[0];
+
+ if (cd->slow_mode) {
+ d = cd->slow_mval[0] - mval[0];
+ }
+
+ if (event->ctrl) {
+ /* Linear mode, enables jumping to any voxel size. */
+ d = d * 0.0005f;
+ }
+ else {
+ /* Multiply d by the initial voxel size to prevent uncontrollable speeds when using low voxel
+ * sizes. */
+ /* When the voxel size is slower, it needs more precision. */
+ d = d * min_ff(pow2f(cd->init_voxel_size), 0.1f) * 0.05f;
+ }
+ if (cd->slow_mode) {
+ cd->voxel_size = cd->slow_voxel_size + d * 0.05f;
+ }
+ else {
+ cd->voxel_size = cd->init_voxel_size + d;
+ }
+
+ if (event->type == EVT_LEFTSHIFTKEY && event->val == KM_PRESS) {
+ cd->slow_mode = true;
+ copy_v2_v2(cd->slow_mval, mval);
+ cd->slow_voxel_size = cd->voxel_size;
+ }
+ if (event->type == EVT_LEFTSHIFTKEY && event->val == KM_RELEASE) {
+ cd->slow_mode = false;
+ cd->slow_voxel_size = 0.0f;
+ }
+
+ cd->voxel_size = clamp_f(cd->voxel_size, 0.0001f, 1.0f);
+
+ ED_region_tag_redraw(ar);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ Object *active_object = CTX_data_active_object(C);
+ Mesh *mesh = (Mesh *)active_object->data;
+
+ VoxelSizeEditCustomData *cd = MEM_callocN(sizeof(VoxelSizeEditCustomData),
+ "Voxel Size Edit OP Custom Data");
+
+ /* Initial operator Custom Data setup. */
+ cd->draw_handle = ED_region_draw_cb_activate(
+ ar->type, voxel_size_edit_draw, cd, REGION_DRAW_POST_VIEW);
+ cd->active_object = active_object;
+ cd->init_mval[0] = event->mval[0];
+ cd->init_mval[1] = event->mval[1];
+ cd->init_voxel_size = mesh->remesh_voxel_size;
+ cd->voxel_size = mesh->remesh_voxel_size;
+ op->customdata = cd;
+
+ /* Select the front facing face of the mesh boundig box. */
+ BoundBox *bb = BKE_mesh_boundbox_get(cd->active_object);
+
+ /* Indices of the Bounding Box faces. */
+ int BB_faces[6][4] = {
+ {3, 0, 4, 7},
+ {1, 2, 6, 5},
+ {3, 2, 1, 0},
+ {4, 5, 6, 7},
+ {0, 1, 5, 4},
+ {2, 3, 7, 6},
+ };
+
+ copy_v3_v3(cd->preview_plane[0], bb->vec[BB_faces[0][0]]);
+ copy_v3_v3(cd->preview_plane[1], bb->vec[BB_faces[0][1]]);
+ copy_v3_v3(cd->preview_plane[2], bb->vec[BB_faces[0][2]]);
+ copy_v3_v3(cd->preview_plane[3], bb->vec[BB_faces[0][3]]);
+
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ float mat[3][3];
+ float current_normal[3];
+ float view_normal[3] = {0.0f, 0.0f, 1.0f};
+
+ /* Calculate the view normal. */
+ invert_m4_m4(active_object->imat, active_object->obmat);
+ copy_m3_m4(mat, rv3d->viewinv);
+ mul_m3_v3(mat, view_normal);
+ copy_m3_m4(mat, active_object->imat);
+ mul_m3_v3(mat, view_normal);
+ normalize_v3(view_normal);
+
+ normal_tri_v3(current_normal, cd->preview_plane[0], cd->preview_plane[1], cd->preview_plane[2]);
+
+ float min_dot = dot_v3v3(current_normal, view_normal);
+ float current_dot = 1;
+
+ /* Check if there is a face that is more aligned towards the view. */
+ for (int i = 0; i < 6; i++) {
+ normal_tri_v3(
+ current_normal, bb->vec[BB_faces[i][0]], bb->vec[BB_faces[i][1]], bb->vec[BB_faces[i][2]]);
+ current_dot = dot_v3v3(current_normal, view_normal);
+
+ if (current_dot < min_dot) {
+ min_dot = current_dot;
+ copy_v3_v3(cd->preview_plane[0], bb->vec[BB_faces[i][0]]);
+ copy_v3_v3(cd->preview_plane[1], bb->vec[BB_faces[i][1]]);
+ copy_v3_v3(cd->preview_plane[2], bb->vec[BB_faces[i][2]]);
+ copy_v3_v3(cd->preview_plane[3], bb->vec[BB_faces[i][3]]);
+ }
+ }
+
+ /* Matrix calculation to position the text in 3D space. */
+ float text_pos[3];
+ float scale_mat[4][4];
+
+ float d_a[3], d_b[3];
+ float d_a_proj[2], d_b_proj[2];
+ float preview_plane_proj[4][3];
+ float y_axis_proj[2] = {0.0f, 1.0f};
+
+ mid_v3_v3v3(text_pos, cd->preview_plane[0], cd->preview_plane[2]);
+
+ /* Project the selected face in the previous step of the Bounding Box. */
+ for (int i = 0; i < 4; i++) {
+ ED_view3d_project(ar, cd->preview_plane[i], preview_plane_proj[i]);
+ }
+
+ /* Get the initial X and Y axis of the basis from the edges of the Bounding Box face. */
+ sub_v3_v3v3(d_a, cd->preview_plane[1], cd->preview_plane[0]);
+ sub_v3_v3v3(d_b, cd->preview_plane[3], cd->preview_plane[0]);
+ normalize_v3(d_a);
+ normalize_v3(d_b);
+
+ /* Project the X and Y axis. */
+ sub_v2_v2v2(d_a_proj, preview_plane_proj[1], preview_plane_proj[0]);
+ sub_v2_v2v2(d_b_proj, preview_plane_proj[3], preview_plane_proj[0]);
+ normalize_v2(d_a_proj);
+ normalize_v2(d_b_proj);
+
+ unit_m4(cd->text_mat);
+
+ /* Select the axis that is aligned with the view Y axis to use it as the basis Y. */
+ if (fabsf(dot_v2v2(d_a_proj, y_axis_proj)) > fabsf(dot_v2v2(d_b_proj, y_axis_proj))) {
+ copy_v3_v3(cd->text_mat[0], d_b);
+ copy_v3_v3(cd->text_mat[1], d_a);
+
+ /* Flip the X and Y basis vectors to make sure they always point upwards and to the right. */
+ if (d_b_proj[0] < 0.0f) {
+ mul_v3_fl(cd->text_mat[0], -1.0f);
+ }
+ if (d_a_proj[1] < 0.0f) {
+ mul_v3_fl(cd->text_mat[1], -1.0f);
+ }
+ }
+ else {
+ copy_v3_v3(cd->text_mat[0], d_a);
+ copy_v3_v3(cd->text_mat[1], d_b);
+ if (d_a_proj[0] < 0.0f) {
+ mul_v3_fl(cd->text_mat[0], -1.0f);
+ }
+ if (d_b_proj[1] < 0.0f) {
+ mul_v3_fl(cd->text_mat[1], -1.0f);
+ }
+ }
+
+ /* Use the Bounding Box face normal as the basis Z. */
+ normal_tri_v3(cd->text_mat[2], cd->preview_plane[0], cd->preview_plane[1], cd->preview_plane[2]);
+
+ /* Write the text position into the matrix. */
+ copy_v3_v3(cd->text_mat[3], text_pos);
+
+ /* Scale the text. */
+ unit_m4(scale_mat);
+ scale_m4_fl(scale_mat, 0.0008f);
+ mul_m4_m4_post(cd->text_mat, scale_mat);
+
+ WM_event_add_modal_handler(C, op);
+
+ ED_region_tag_redraw(ar);
+
+ const char *status_str = TIP_(
+ "Move the mouse to change the voxel size. LMB: confirm size, ESC/RMB: cancel");
+ ED_workspace_status_text(C, status_str);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void OBJECT_OT_voxel_size_edit(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Edit Voxel Size";
+ ot->description = "Modify the mesh voxel size interactively used in the voxel remesher";
+ ot->idname = "OBJECT_OT_voxel_size_edit";
+
+ /* api callbacks */
+ ot->poll = object_remesh_poll;
+ ot->invoke = voxel_size_edit_invoke;
+ ot->modal = voxel_size_edit_modal;
+ ot->cancel = voxel_size_edit_cancel;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Quadriflow Remesh Operator
+ * \{ */
+
+#define QUADRIFLOW_MIRROR_BISECT_TOLERANCE 0.005f
+
enum {
QUADRIFLOW_REMESH_RATIO = 1,
QUADRIFLOW_REMESH_EDGE_LENGTH,
QUADRIFLOW_REMESH_FACES,
};
-/****************** quadriflow remesh operator *********************/
-
-#define QUADRIFLOW_MIRROR_BISECT_TOLERANCE 0.005f
-
typedef enum eSymmetryAxes {
SYMMETRY_AXES_X = (1 << 0),
SYMMETRY_AXES_Y = (1 << 1),
@@ -197,7 +623,6 @@ typedef enum eSymmetryAxes {
typedef struct QuadriFlowJob {
/* from wmJob */
struct Object *owner;
- struct Main *bmain;
short *stop, *do_update;
float *progress;
@@ -214,6 +639,7 @@ typedef struct QuadriFlowJob {
bool smooth_normals;
int success;
+ bool is_nonblocking_job;
} QuadriFlowJob;
static bool mesh_is_manifold_consistent(Mesh *mesh)
@@ -227,13 +653,13 @@ static bool mesh_is_manifold_consistent(Mesh *mesh)
const MLoop *mloop = mesh->mloop;
char *edge_faces = (char *)MEM_callocN(mesh->totedge * sizeof(char), "remesh_manifold_check");
int *edge_vert = (int *)MEM_malloc_arrayN(
- mesh->totedge, sizeof(unsigned int), "remesh_consistent_check");
+ mesh->totedge, sizeof(uint), "remesh_consistent_check");
- for (unsigned int i = 0; i < mesh->totedge; i++) {
+ for (uint i = 0; i < mesh->totedge; i++) {
edge_vert[i] = -1;
}
- for (unsigned int loop_idx = 0; loop_idx < mesh->totloop; loop_idx++) {
+ for (uint loop_idx = 0; loop_idx < mesh->totloop; loop_idx++) {
const MLoop *loop = &mloop[loop_idx];
edge_faces[loop->e] += 1;
if (edge_faces[loop->e] > 2) {
@@ -253,7 +679,7 @@ static bool mesh_is_manifold_consistent(Mesh *mesh)
if (is_manifold_consistent) {
/* check for wire edges */
- for (unsigned int i = 0; i < mesh->totedge; i++) {
+ for (uint i = 0; i < mesh->totedge; i++) {
if (edge_faces[i] == 0) {
is_manifold_consistent = false;
break;
@@ -307,13 +733,13 @@ static void quadriflow_update_job(void *customdata, float progress, int *cancel)
*(qj->progress) = progress;
}
-static Mesh *remesh_symmetry_bisect(Main *bmain, Mesh *mesh, eSymmetryAxes symmetry_axes)
+static Mesh *remesh_symmetry_bisect(Mesh *mesh, eSymmetryAxes symmetry_axes)
{
MirrorModifierData mmd = {{0}};
mmd.tolerance = QUADRIFLOW_MIRROR_BISECT_TOLERANCE;
Mesh *mesh_bisect, *mesh_bisect_temp;
- mesh_bisect = BKE_mesh_copy(bmain, mesh);
+ mesh_bisect = BKE_mesh_copy_for_eval(mesh, false);
int axis;
float plane_co[3], plane_no[3];
@@ -331,12 +757,12 @@ static Mesh *remesh_symmetry_bisect(Main *bmain, Mesh *mesh, eSymmetryAxes symme
mesh_bisect = BKE_mesh_mirror_bisect_on_mirror_plane(
&mmd, mesh_bisect, axis, plane_co, plane_no);
if (mesh_bisect_temp != mesh_bisect) {
- BKE_id_free(bmain, mesh_bisect_temp);
+ BKE_id_free(NULL, mesh_bisect_temp);
}
}
}
- BKE_id_free(bmain, mesh);
+ BKE_id_free(NULL, mesh);
return mesh_bisect;
}
@@ -377,7 +803,9 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
qj->progress = progress;
qj->success = 1;
- G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
+ if (qj->is_nonblocking_job) {
+ G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
+ }
Object *ob = qj->owner;
Mesh *mesh = ob->data;
@@ -392,28 +820,32 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
/* Run Quadriflow bisect operations on a copy of the mesh to keep the code readable without
* freeing the original ID */
- bisect_mesh = BKE_mesh_copy(qj->bmain, mesh);
+ bisect_mesh = BKE_mesh_copy_for_eval(mesh, false);
/* Bisect the input mesh using the paint symmetry settings */
- bisect_mesh = remesh_symmetry_bisect(qj->bmain, bisect_mesh, qj->symmetry_axes);
-
- new_mesh = BKE_mesh_remesh_quadriflow_to_mesh_nomain(bisect_mesh,
- qj->target_faces,
- qj->seed,
- qj->use_preserve_sharp,
- qj->use_preserve_boundary ||
- qj->use_paint_symmetry,
- qj->use_mesh_curvature,
- quadriflow_update_job,
- (void *)qj);
-
- BKE_id_free(qj->bmain, bisect_mesh);
+ bisect_mesh = remesh_symmetry_bisect(bisect_mesh, qj->symmetry_axes);
+
+ new_mesh = BKE_mesh_remesh_quadriflow_to_mesh_nomain(
+ bisect_mesh,
+ qj->target_faces,
+ qj->seed,
+ qj->use_preserve_sharp,
+ (qj->use_preserve_boundary || qj->use_paint_symmetry),
+#ifdef USE_MESH_CURVATURE
+ qj->use_mesh_curvature,
+#else
+ false,
+#endif
+ quadriflow_update_job,
+ (void *)qj);
+
+ BKE_id_free(NULL, bisect_mesh);
if (new_mesh == NULL) {
*do_update = true;
*stop = 0;
if (qj->success == 1) {
- /* This is not a user cancelation event */
+ /* This is not a user cancellation event. */
qj->success = 0;
}
return;
@@ -456,23 +888,25 @@ static void quadriflow_end_job(void *customdata)
Object *ob = qj->owner;
- WM_set_locked_interface(G_MAIN->wm.first, false);
+ if (qj->is_nonblocking_job) {
+ WM_set_locked_interface(G_MAIN->wm.first, false);
+ }
switch (qj->success) {
case 1:
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_reportf(RPT_INFO, "QuadriFlow: Completed remeshing!");
+ WM_reportf(RPT_INFO, "QuadriFlow: Remeshing completed");
break;
case 0:
- WM_reportf(RPT_ERROR, "QuadriFlow: remeshing failed!");
+ WM_reportf(RPT_ERROR, "QuadriFlow: Remeshing failed");
break;
case -1:
- WM_report(RPT_WARNING, "QuadriFlow: remeshing canceled!");
+ WM_report(RPT_WARNING, "QuadriFlow: Remeshing cancelled");
break;
case -2:
WM_report(RPT_WARNING,
"QuadriFlow: The mesh needs to be manifold and have face normals that point in a "
- "consistent direction.");
+ "consistent direction");
break;
}
}
@@ -482,7 +916,6 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op)
QuadriFlowJob *job = MEM_mallocN(sizeof(QuadriFlowJob), "QuadriFlowJob");
job->owner = CTX_data_active_object(C);
- job->bmain = CTX_data_main(C);
job->target_faces = RNA_int_get(op->ptr, "target_faces");
job->seed = RNA_int_get(op->ptr, "seed");
@@ -492,7 +925,9 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op)
job->use_preserve_sharp = RNA_boolean_get(op->ptr, "use_preserve_sharp");
job->use_preserve_boundary = RNA_boolean_get(op->ptr, "use_preserve_boundary");
+#ifdef USE_MESH_CURVATURE
job->use_mesh_curvature = RNA_boolean_get(op->ptr, "use_mesh_curvature");
+#endif
job->preserve_paint_mask = RNA_boolean_get(op->ptr, "preserve_paint_mask");
job->smooth_normals = RNA_boolean_get(op->ptr, "smooth_normals");
@@ -513,21 +948,34 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op)
job->symmetry_axes = 0;
}
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
- CTX_wm_window(C),
- CTX_data_scene(C),
- "QuadriFlow Remesh",
- WM_JOB_PROGRESS,
- WM_JOB_TYPE_QUADRIFLOW_REMESH);
+ if (op->flag == 0) {
+ /* This is called directly from the exec operator, this operation is now blocking */
+ job->is_nonblocking_job = false;
+ short stop = 0, do_update = true;
+ float progress;
+ quadriflow_start_job(job, &stop, &do_update, &progress);
+ quadriflow_end_job(job);
+ quadriflow_free_job(job);
+ }
+ else {
+ /* Non blocking call. For when the operator has been called from the gui */
+ job->is_nonblocking_job = true;
- WM_jobs_customdata_set(wm_job, job, quadriflow_free_job);
- WM_jobs_timer(wm_job, 0.1, NC_GEOM | ND_DATA, NC_GEOM | ND_DATA);
- WM_jobs_callbacks(wm_job, quadriflow_start_job, NULL, NULL, quadriflow_end_job);
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ CTX_data_scene(C),
+ "QuadriFlow Remesh",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_QUADRIFLOW_REMESH);
- WM_set_locked_interface(CTX_wm_manager(C), true);
+ WM_jobs_customdata_set(wm_job, job, quadriflow_free_job);
+ WM_jobs_timer(wm_job, 0.1, NC_GEOM | ND_DATA, NC_GEOM | ND_DATA);
+ WM_jobs_callbacks(wm_job, quadriflow_start_job, NULL, NULL, quadriflow_end_job);
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_set_locked_interface(CTX_wm_manager(C), true);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
return OPERATOR_FINISHED;
}
@@ -640,7 +1088,7 @@ void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
"use_paint_symmetry",
true,
"Use Paint Symmetry",
- "Generates a symmetrycal mesh using the paint symmetry configuration");
+ "Generates a symmetrical mesh using the paint symmetry configuration");
RNA_def_boolean(ot->srna,
"use_preserve_sharp",
@@ -653,13 +1101,13 @@ void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
false,
"Preserve Mesh Boundary",
"Try to preserve mesh boundary on the mesh");
-
+#ifdef USE_MESH_CURVATURE
RNA_def_boolean(ot->srna,
"use_mesh_curvature",
false,
"Use Mesh Curvature",
"Take the mesh curvature into account when remeshing");
-
+#endif
RNA_def_boolean(ot->srna,
"preserve_paint_mask",
false,
@@ -732,3 +1180,5 @@ void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
0,
255);
}
+
+/** \} */
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 40fa11994f4..5f9799710dc 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -27,18 +27,18 @@
#include <string.h>
#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
#include "DNA_collection_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_light_types.h"
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_light_types.h"
#include "DNA_workspace_types.h"
-#include "DNA_gpencil_types.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_bits.h"
-#include "BLI_listbase.h"
#include "BLI_rand.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
@@ -51,7 +51,7 @@
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
@@ -64,15 +64,15 @@
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "ED_armature.h"
+#include "ED_keyframing.h"
#include "ED_object.h"
#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "ED_keyframing.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -246,7 +246,7 @@ Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id)
Base *base_best = NULL;
int priority_best = 0;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->object && base->object->data == id) {
if (base->flag & BASE_SELECTED) {
return base;
@@ -523,7 +523,7 @@ static bool object_select_all_by_material(bContext *C, Material *mat)
int a;
for (a = 1; a <= ob->totcol; a++) {
- mat1 = give_current_material(ob, a);
+ mat1 = BKE_object_material_get(ob, a);
if (mat1 == mat) {
ED_object_base_select(base, BA_SELECT);
@@ -681,7 +681,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
else if (nr == OBJECT_SELECT_LINKED_MATERIAL) {
Material *mat = NULL;
- mat = give_current_material(ob, ob->actcol);
+ mat = BKE_object_material_get(ob, ob->actcol);
if (mat == NULL) {
return OPERATOR_CANCELLED;
}
@@ -836,14 +836,15 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel
/* Select objects in the same group as the active */
static bool select_grouped_collection(bContext *C, Object *ob)
{
+ Main *bmain = CTX_data_main(C);
bool changed = false;
Collection *collection, *ob_collections[COLLECTION_MENU_MAX];
int collection_count = 0, i;
uiPopupMenu *pup;
uiLayout *layout;
- for (collection = CTX_data_main(C)->collections.first;
- collection && collection_count < COLLECTION_MENU_MAX;
+ for (collection = bmain->collections.first;
+ collection && (collection_count < COLLECTION_MENU_MAX);
collection = collection->id.next) {
if (BKE_collection_has_object(collection, ob)) {
ob_collections[collection_count] = collection;
@@ -1324,7 +1325,7 @@ static bool object_select_more_less(bContext *C, const bool select)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
ob->flag &= ~OB_DONE;
ob->id.tag &= ~LIB_TAG_DOIT;
diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c
index db0c8c54186..30fcdfc88bc 100644
--- a/source/blender/editors/object/object_shader_fx.c
+++ b/source/blender/editors/object/object_shader_fx.c
@@ -28,9 +28,9 @@
#include "MEM_guardedalloc.h"
#include "DNA_gpencil_types.h"
-#include "DNA_shader_fx_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_shader_fx_types.h"
#include "BLI_listbase.h"
#include "BLI_string_utf8.h"
@@ -40,9 +40,9 @@
#include "BKE_context.h"
#include "BKE_main.h"
-#include "BKE_shader_fx.h"
-#include "BKE_report.h"
#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_shader_fx.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -66,7 +66,7 @@ ShaderFxData *ED_object_shaderfx_add(
ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
{
ShaderFxData *new_fx = NULL;
- const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(type);
+ const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(type);
if (ob->type != OB_GPENCIL) {
BKE_reportf(reports, RPT_WARNING, "Effect cannot be added to object '%s'", ob->id.name + 2);
@@ -74,7 +74,7 @@ ShaderFxData *ED_object_shaderfx_add(
}
if (fxi->flags & eShaderFxTypeFlag_Single) {
- if (BKE_shaderfx_findByType(ob, type)) {
+ if (BKE_shaderfx_findby_type(ob, type)) {
BKE_report(reports, RPT_WARNING, "Only one Effect of this type is allowed");
return NULL;
}
@@ -236,7 +236,7 @@ static const EnumPropertyItem *shaderfx_add_itemf(bContext *C,
for (a = 0; rna_enum_object_shaderfx_type_items[a].identifier; a++) {
fx_item = &rna_enum_object_shaderfx_type_items[a];
if (fx_item->identifier[0]) {
- mti = BKE_shaderfxType_getInfo(fx_item->value);
+ mti = BKE_shaderfx_get_info(fx_item->value);
if (mti->flags & eShaderFxTypeFlag_NoUserAdd) {
continue;
@@ -356,7 +356,7 @@ static ShaderFxData *edit_shaderfx_property_get(wmOperator *op, Object *ob, int
ShaderFxData *fx;
RNA_string_get(op->ptr, "shaderfx", shaderfx_name);
- fx = BKE_shaderfx_findByName(ob, shaderfx_name);
+ fx = BKE_shaderfx_findby_name(ob, shaderfx_name);
if (fx && type != 0 && fx->type != type) {
fx = NULL;
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index fb76ba6099d..26d33bbc375 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -55,8 +55,8 @@
#include "BLI_sys_types.h" // for intptr_t support
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -126,7 +126,7 @@ static bool object_shape_key_mirror(
float *fp1, *fp2;
float tvec[3];
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
+ ED_mesh_mirror_spatial_table_begin(ob, NULL, NULL);
for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology);
@@ -157,7 +157,7 @@ static bool object_shape_key_mirror(
}
}
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
+ ED_mesh_mirror_spatial_table_end(ob);
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = ob->data;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 45b9c6306ac..132b530455e 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -26,53 +26,55 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_collection_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_light_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
-#include "DNA_light_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_collection_types.h"
-#include "DNA_lattice_types.h"
-#include "BLI_math.h"
+#include "BLI_array.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_array.h"
+#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_curve.h"
+#include "BKE_editmesh.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_idtype.h"
+#include "BKE_lattice.h"
+#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
-#include "BKE_idcode.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
+#include "BKE_multires.h"
#include "BKE_object.h"
-#include "BKE_scene.h"
#include "BKE_report.h"
-#include "BKE_editmesh.h"
-#include "BKE_multires.h"
-#include "BKE_armature.h"
-#include "BKE_lattice.h"
-#include "BKE_library.h"
+#include "BKE_scene.h"
#include "BKE_tracking.h"
-#include "BKE_gpencil.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "RNA_define.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_armature.h"
+#include "ED_gpencil.h"
#include "ED_keyframing.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_gpencil.h"
-#include "ED_object.h"
#include "MEM_guardedalloc.h"
@@ -296,22 +298,43 @@ static int object_clear_transform_generic_exec(bContext *C,
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ /* May be NULL. */
+ View3D *v3d = CTX_wm_view3d(C);
KeyingSet *ks;
const bool clear_delta = RNA_boolean_get(op->ptr, "clear_delta");
- /* sanity checks */
- if (ELEM(NULL, clear_func, default_ksName)) {
- BKE_report(op->reports,
- RPT_ERROR,
- "Programming error: missing clear transform function or keying set name");
+ BLI_assert(!ELEM(NULL, clear_func, default_ksName));
+
+ Object **objects = NULL;
+ uint objects_len = 0;
+ {
+ BLI_array_declare(objects);
+ FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer, v3d, ob) {
+ BLI_array_append(objects, ob);
+ }
+ FOREACH_SELECTED_EDITABLE_OBJECT_END;
+ objects_len = BLI_array_len(objects);
+ }
+
+ if (objects == NULL) {
return OPERATOR_CANCELLED;
}
/* Support transforming the object data. */
+ const bool use_transform_skip_children = (scene->toolsettings->transform_flag &
+ SCE_XFORM_SKIP_CHILDREN);
const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
SCE_XFORM_DATA_ORIGIN);
+ struct XFormObjectSkipChild_Container *xcs = NULL;
struct XFormObjectData_Container *xds = NULL;
+ if (use_transform_skip_children) {
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+ xcs = ED_object_xform_skip_child_container_create();
+ ED_object_xform_skip_child_container_item_ensure_from_array(
+ xcs, view_layer, objects, objects_len);
+ }
if (use_transform_data_origin) {
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
xds = ED_object_data_xform_container_create();
@@ -320,13 +343,8 @@ static int object_clear_transform_generic_exec(bContext *C,
/* get KeyingSet to use */
ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
- /* operate on selected objects only if they aren't in weight-paint mode
- * (so that object-transform clearing won't be applied at same time as bone-clearing)
- */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- continue;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
if (use_transform_data_origin) {
ED_object_data_xform_container_item_ensure(xds, ob);
@@ -340,7 +358,12 @@ static int object_clear_transform_generic_exec(bContext *C,
/* tag for updates */
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
- CTX_DATA_END;
+ MEM_freeN(objects);
+
+ if (use_transform_skip_children) {
+ ED_object_xform_skip_child_container_update_all(xcs, bmain, depsgraph);
+ ED_object_xform_skip_child_container_destroy(xcs);
+ }
if (use_transform_data_origin) {
ED_object_data_xform_container_update_all(xds, bmain, depsgraph);
@@ -616,7 +639,7 @@ static int apply_objects_internal(bContext *C,
RPT_ERROR,
"Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2,
- BKE_idcode_to_name(GS(obdata->name)),
+ BKE_idtype_idcode_to_name(GS(obdata->name)),
obdata->name + 2);
changed = false;
}
@@ -626,7 +649,7 @@ static int apply_objects_internal(bContext *C,
RPT_ERROR,
"Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2,
- BKE_idcode_to_name(GS(obdata->name)),
+ BKE_idtype_idcode_to_name(GS(obdata->name)),
obdata->name + 2);
changed = false;
}
@@ -644,7 +667,7 @@ static int apply_objects_internal(bContext *C,
RPT_ERROR,
"Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2,
- BKE_idcode_to_name(GS(obdata->name)),
+ BKE_idtype_idcode_to_name(GS(obdata->name)),
obdata->name + 2);
changed = false;
}
@@ -653,7 +676,7 @@ static int apply_objects_internal(bContext *C,
RPT_ERROR,
"Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2,
- BKE_idcode_to_name(GS(obdata->name)),
+ BKE_idtype_idcode_to_name(GS(obdata->name)),
obdata->name + 2);
changed = false;
}
@@ -674,7 +697,7 @@ static int apply_objects_internal(bContext *C,
/* Unsupported configuration */
bool has_unparented_layers = false;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Parented layers aren't supported as we can't easily re-evaluate
* the scene to sample parent movement */
if (gpl->parent == NULL) {
@@ -689,7 +712,7 @@ static int apply_objects_internal(bContext *C,
"Can't apply to a GP datablock where all layers are parented: Object "
"\"%s\", %s \"%s\", aborting",
ob->id.name + 2,
- BKE_idcode_to_name(ID_GD),
+ BKE_idtype_idcode_to_name(ID_GD),
gpd->id.name + 2);
changed = false;
}
@@ -701,7 +724,7 @@ static int apply_objects_internal(bContext *C,
RPT_ERROR,
"Can't apply to GP datablock with no layers: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2,
- BKE_idcode_to_name(ID_GD),
+ BKE_idtype_idcode_to_name(ID_GD),
gpd->id.name + 2);
}
}
@@ -1372,13 +1395,13 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* recalculate all strokes
* (all layers are considered without evaluating lock attributes) */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* undo matrix */
invert_m4_m4(inverse_diff_mat, diff_mat);
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
float mpt[3];
mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
@@ -1585,6 +1608,7 @@ struct XFormAxisItem {
float rot_mat[3][3];
void *obtfm;
float xform_dist;
+ bool is_z_flip;
#ifdef USE_RELATIVE_ROTATION
/* use when translating multiple */
@@ -1615,7 +1639,7 @@ static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *x
struct XFormAxisItem *item = xfd->object_data;
float view_co_a[3], view_co_b[3];
const float mval_fl[2] = {UNPACK2(mval)};
- ED_view3d_win_to_ray(xfd->vc.ar, mval_fl, view_co_a, view_co_b);
+ ED_view3d_win_to_ray(xfd->vc.region, mval_fl, view_co_a, view_co_b);
add_v3_v3(view_co_b, view_co_a);
float center[3] = {0.0f};
int center_tot = 0;
@@ -1633,7 +1657,7 @@ static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *x
if (center_tot) {
mul_v3_fl(center, 1.0f / center_tot);
float center_proj[3];
- ED_view3d_project(xfd->vc.ar, center, center_proj);
+ ED_view3d_project(xfd->vc.region, center, center_proj);
xfd->prev.depth = center_proj[2];
xfd->prev.is_depth_valid = true;
}
@@ -1704,14 +1728,19 @@ static void object_apply_location(Object *ob, const float loc[3])
copy_v3_v3(ob->loc, mat[3]);
}
-static void object_orient_to_location(Object *ob,
+static bool object_orient_to_location(Object *ob,
const float rot_orig[3][3],
const float axis[3],
- const float location[3])
+ const float location[3],
+ const bool z_flip)
{
float delta[3];
sub_v3_v3v3(delta, ob->obmat[3], location);
if (normalize_v3(delta) != 0.0f) {
+ if (z_flip) {
+ negate_v3(delta);
+ }
+
if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
float delta_rot[3][3];
float final_rot[3][3];
@@ -1721,9 +1750,10 @@ static void object_orient_to_location(Object *ob,
object_apply_rotation(ob, final_rot);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ return true;
}
}
+ return false;
}
static void object_transform_axis_target_cancel(bContext *C, wmOperator *op)
@@ -1755,12 +1785,12 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons
vc.v3d->flag2 |= V3D_HIDE_OVERLAYS;
#endif
- ED_view3d_autodist_init(vc.depsgraph, vc.ar, vc.v3d, 0);
+ ED_view3d_autodist_init(vc.depsgraph, vc.region, vc.v3d, 0);
if (vc.rv3d->depths != NULL) {
vc.rv3d->depths->damaged = true;
}
- ED_view3d_depth_update(vc.ar);
+ ED_view3d_depth_update(vc.region);
#ifdef USE_RENDER_OVERRIDE
vc.v3d->flag2 = flag2_prev;
@@ -1771,7 +1801,7 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons
return OPERATOR_CANCELLED;
}
- ED_region_tag_redraw(vc.ar);
+ ED_region_tag_redraw(vc.region);
struct XFormAxisData *xfd;
xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), __func__);
@@ -1817,6 +1847,11 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons
for (int i = 0; i < xfd->object_data_len; i++, item++) {
item->obtfm = BKE_object_tfm_backup(item->ob);
BKE_object_rot_to_mat3(item->ob, item->rot_mat, true);
+
+ /* Detect negative scale matrix. */
+ float full_mat3[3][3];
+ BKE_object_to_mat3(item->ob, full_mat3);
+ item->is_z_flip = dot_v3v3(item->rot_mat[2], full_mat3[2]) < 0.0f;
}
}
@@ -1828,7 +1863,7 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons
static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
struct XFormAxisData *xfd = op->customdata;
- ARegion *ar = xfd->vc.ar;
+ ARegion *region = xfd->vc.region;
view3d_operator_needs_opengl(C);
@@ -1837,8 +1872,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
if (event->type == MOUSEMOVE || is_translate_init) {
const ViewDepths *depths = xfd->vc.rv3d->depths;
- if (depths && ((unsigned int)event->mval[0] < depths->w) &&
- ((unsigned int)event->mval[1] < depths->h)) {
+ if (depths && ((uint)event->mval[0] < depths->w) && ((uint)event->mval[1] < depths->h)) {
double depth = (double)ED_view3d_depth_read_cached(&xfd->vc, event->mval);
float location_world[3];
if (depth == 1.0f) {
@@ -1862,7 +1896,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
xfd->prev.depth = depth;
xfd->prev.is_depth_valid = true;
- if (ED_view3d_depth_unproject(ar, event->mval, depth, location_world)) {
+ if (ED_view3d_depth_unproject(region, event->mval, depth, location_world)) {
if (is_translate) {
float normal[3];
@@ -1871,9 +1905,9 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
normal_found = true;
/* cheap attempt to smooth normals out a bit! */
- const uint ofs = 2;
- for (uint x = -ofs; x <= ofs; x += ofs / 2) {
- for (uint y = -ofs; y <= ofs; y += ofs / 2) {
+ const int ofs = 2;
+ for (int x = -ofs; x <= ofs; x += ofs / 2) {
+ for (int y = -ofs; y <= ofs; y += ofs / 2) {
if (x != 0 && y != 0) {
int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
float n[3];
@@ -1890,7 +1924,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
normal_found = true;
}
- if (normal_found) {
+ {
#ifdef USE_RELATIVE_ROTATION
if (is_translate_init && xfd->object_data_len > 1) {
float xform_rot_offset_inv_first[3][3];
@@ -1919,16 +1953,26 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
item->xform_dist = len_v3v3(item->ob->obmat[3], location_world);
normalize_v3_v3(ob_axis, item->ob->obmat[2]);
/* Scale to avoid adding distance when moving between surfaces. */
- float scale = fabsf(dot_v3v3(ob_axis, normal));
- item->xform_dist *= scale;
+ if (normal_found) {
+ float scale = fabsf(dot_v3v3(ob_axis, normal));
+ item->xform_dist *= scale;
+ }
}
float target_normal[3];
- copy_v3_v3(target_normal, normal);
+
+ if (normal_found) {
+ copy_v3_v3(target_normal, normal);
+ }
+ else {
+ normalize_v3_v3(target_normal, item->ob->obmat[2]);
+ }
#ifdef USE_RELATIVE_ROTATION
- if (i != 0) {
- mul_m3_v3(item->xform_rot_offset, target_normal);
+ if (normal_found) {
+ if (i != 0) {
+ mul_m3_v3(item->xform_rot_offset, target_normal);
+ }
}
#endif
{
@@ -1942,18 +1986,28 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
}
object_orient_to_location(
- item->ob, item->rot_mat, item->rot_mat[2], location_world);
+ item->ob, item->rot_mat, item->rot_mat[2], location_world, item->is_z_flip);
+
+ DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
}
- copy_v3_v3(xfd->prev.normal, normal);
- xfd->prev.is_normal_valid = true;
+ if (normal_found) {
+ copy_v3_v3(xfd->prev.normal, normal);
+ xfd->prev.is_normal_valid = true;
+ }
}
}
else {
struct XFormAxisItem *item = xfd->object_data;
for (int i = 0; i < xfd->object_data_len; i++, item++) {
- object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+ if (object_orient_to_location(item->ob,
+ item->rot_mat,
+ item->rot_mat[2],
+ location_world,
+ item->is_z_flip)) {
+ DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+ }
}
xfd->prev.is_normal_valid = false;
}
@@ -1962,7 +2016,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
}
xfd->is_translate = is_translate;
- ED_region_tag_redraw(xfd->vc.ar);
+ ED_region_tag_redraw(xfd->vc.region);
}
bool is_finished = false;
@@ -1973,7 +2027,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
}
}
else {
- if (ELEM(event->type, LEFTMOUSE, RETKEY, PADENTER)) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_RETKEY, EVT_PADENTER)) {
is_finished = true;
}
}
@@ -1982,7 +2036,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
object_transform_axis_target_free_data(op);
return OPERATOR_FINISHED;
}
- else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
+ else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
object_transform_axis_target_cancel(C, op);
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/object/object_utils.c b/source/blender/editors/object/object_utils.c
index dbca0bbf97b..00aafc2120f 100644
--- a/source/blender/editors/object/object_utils.c
+++ b/source/blender/editors/object/object_utils.c
@@ -23,17 +23,21 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_collection_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_collection_types.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_action.h"
#include "BKE_editmesh.h"
#include "BKE_lattice.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph_query.h"
#include "WM_types.h"
@@ -41,6 +45,8 @@
#include "ED_curve.h"
#include "ED_object.h" /* own include */
+#include "MEM_guardedalloc.h"
+
/* -------------------------------------------------------------------- */
/** \name Active Element Center
* \{ */
@@ -142,3 +148,287 @@ bool ED_object_calc_active_center(Object *ob, const bool select_only, float r_ce
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Child Skip
+ *
+ * Don't transform unselected children, this is done using the parent inverse matrix.
+ *
+ * \note The complex logic here is caused by mixed selection within a single selection chain,
+ * otherwise we only need #XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM for single objects.
+ *
+ * \{ */
+
+struct XFormObjectSkipChild_Container {
+ GHash *obchild_in_obmode_map;
+};
+
+struct XFormObjectSkipChild {
+ float obmat_orig[4][4];
+ float parent_obmat_orig[4][4];
+ float parent_obmat_inv_orig[4][4];
+ float parent_recurse_obmat_orig[4][4];
+ float parentinv_orig[4][4];
+ Object *ob_parent_recurse;
+ int mode;
+};
+
+struct XFormObjectSkipChild_Container *ED_object_xform_skip_child_container_create(void)
+{
+ struct XFormObjectSkipChild_Container *xcs = MEM_callocN(sizeof(*xcs), __func__);
+ if (xcs->obchild_in_obmode_map == NULL) {
+ xcs->obchild_in_obmode_map = BLI_ghash_ptr_new(__func__);
+ }
+ return xcs;
+}
+
+void ED_object_xform_skip_child_container_item_ensure_from_array(
+ struct XFormObjectSkipChild_Container *xcs,
+ ViewLayer *view_layer,
+ Object **objects,
+ uint objects_len)
+{
+ GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BLI_gset_add(objects_in_transdata, ob);
+ }
+
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ Object *ob = base->object;
+ if (ob->parent != NULL) {
+ if (!BLI_gset_haskey(objects_in_transdata, ob)) {
+ if (BLI_gset_haskey(objects_in_transdata, ob->parent)) {
+ ED_object_xform_skip_child_container_item_ensure(
+ xcs, ob, NULL, XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM);
+ }
+ }
+ else {
+ if (!BLI_gset_haskey(objects_in_transdata, ob->parent)) {
+ Object *ob_parent_recurse = ob->parent;
+ if (ob_parent_recurse != NULL) {
+ while (ob_parent_recurse != NULL) {
+ if (BLI_gset_haskey(objects_in_transdata, ob_parent_recurse)) {
+ break;
+ }
+ ob_parent_recurse = ob_parent_recurse->parent;
+ }
+
+ if (ob_parent_recurse) {
+ ED_object_xform_skip_child_container_item_ensure(
+ xcs, ob, ob_parent_recurse, XFORM_OB_SKIP_CHILD_PARENT_APPLY);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ Object *ob = base->object;
+
+ if (BLI_gset_haskey(objects_in_transdata, ob)) {
+ /* pass. */
+ }
+ else if (ob->parent != NULL) {
+ if (BLI_gset_haskey(objects_in_transdata, ob->parent)) {
+ if (!BLI_gset_haskey(objects_in_transdata, ob)) {
+ ED_object_xform_skip_child_container_item_ensure(
+ xcs, ob, NULL, XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM);
+ }
+ }
+ }
+ }
+ BLI_gset_free(objects_in_transdata, NULL);
+}
+
+void ED_object_xform_skip_child_container_destroy(struct XFormObjectSkipChild_Container *xcs)
+{
+ BLI_ghash_free(xcs->obchild_in_obmode_map, NULL, MEM_freeN);
+ MEM_freeN(xcs);
+}
+
+void ED_object_xform_skip_child_container_item_ensure(struct XFormObjectSkipChild_Container *xcs,
+ Object *ob,
+ Object *ob_parent_recurse,
+ int mode)
+{
+ void **xf_p;
+ if (!BLI_ghash_ensure_p(xcs->obchild_in_obmode_map, ob, &xf_p)) {
+ struct XFormObjectSkipChild *xf = MEM_mallocN(sizeof(*xf), __func__);
+ copy_m4_m4(xf->parentinv_orig, ob->parentinv);
+ copy_m4_m4(xf->obmat_orig, ob->obmat);
+ copy_m4_m4(xf->parent_obmat_orig, ob->parent->obmat);
+ invert_m4_m4(xf->parent_obmat_inv_orig, ob->parent->obmat);
+ if (ob_parent_recurse) {
+ copy_m4_m4(xf->parent_recurse_obmat_orig, ob_parent_recurse->obmat);
+ }
+ xf->mode = mode;
+ xf->ob_parent_recurse = ob_parent_recurse;
+ *xf_p = xf;
+ }
+}
+
+void ED_object_xform_skip_child_container_update_all(struct XFormObjectSkipChild_Container *xcs,
+ struct Main *bmain,
+ struct Depsgraph *depsgraph)
+{
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, xcs->obchild_in_obmode_map) {
+ Object *ob = BLI_ghashIterator_getKey(&gh_iter);
+ struct XFormObjectSkipChild *xf = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* The following blocks below assign 'dmat'. */
+ float dmat[4][4];
+
+ if (xf->mode == XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM) {
+ /* Parent is transformed, this isn't so compensate. */
+ Object *ob_parent_eval = DEG_get_evaluated_object(depsgraph, ob->parent);
+ mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, ob_parent_eval->obmat);
+ invert_m4(dmat);
+ }
+ else if (xf->mode == XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT) {
+ /* Calculate parent matrix (from the root transform). */
+ Object *ob_parent_recurse_eval = DEG_get_evaluated_object(depsgraph, xf->ob_parent_recurse);
+ float parent_recurse_obmat_inv[4][4];
+ invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
+ mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
+ invert_m4(dmat);
+ float parent_obmat_calc[4][4];
+ mul_m4_m4m4(parent_obmat_calc, dmat, xf->parent_obmat_orig);
+
+ /* Apply to the parent inverse matrix. */
+ mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, parent_obmat_calc);
+ invert_m4(dmat);
+ }
+ else {
+ BLI_assert(xf->mode == XFORM_OB_SKIP_CHILD_PARENT_APPLY);
+ /* Transform this - without transform data. */
+ Object *ob_parent_recurse_eval = DEG_get_evaluated_object(depsgraph, xf->ob_parent_recurse);
+ float parent_recurse_obmat_inv[4][4];
+ invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
+ mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
+ invert_m4(dmat);
+ float obmat_calc[4][4];
+ mul_m4_m4m4(obmat_calc, dmat, xf->obmat_orig);
+ /* obmat_calc is just obmat. */
+
+ /* Get the matrices relative to the parent. */
+ float obmat_parent_relative_orig[4][4];
+ float obmat_parent_relative_calc[4][4];
+ float obmat_parent_relative_inv_orig[4][4];
+
+ mul_m4_m4m4(obmat_parent_relative_orig, xf->parent_obmat_inv_orig, xf->obmat_orig);
+ mul_m4_m4m4(obmat_parent_relative_calc, xf->parent_obmat_inv_orig, obmat_calc);
+ invert_m4_m4(obmat_parent_relative_inv_orig, obmat_parent_relative_orig);
+
+ /* Apply to the parent inverse matrix. */
+ mul_m4_m4m4(dmat, obmat_parent_relative_calc, obmat_parent_relative_inv_orig);
+ }
+
+ mul_m4_m4m4(ob->parentinv, dmat, xf->parentinv_orig);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Data Transform Container
+ *
+ * Use to implement 'Affect Only Origins' feature.
+ *
+ * \{ */
+
+struct XFormObjectData_Container {
+ GHash *obdata_in_obmode_map;
+};
+
+struct XFormObjectData_Extra {
+ Object *ob;
+ float obmat_orig[4][4];
+ struct XFormObjectData *xod;
+};
+
+void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container *xds, Object *ob)
+{
+ if (xds->obdata_in_obmode_map == NULL) {
+ xds->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
+ }
+
+ void **xf_p;
+ if (!BLI_ghash_ensure_p(xds->obdata_in_obmode_map, ob->data, &xf_p)) {
+ struct XFormObjectData_Extra *xf = MEM_mallocN(sizeof(*xf), __func__);
+ copy_m4_m4(xf->obmat_orig, ob->obmat);
+ xf->ob = ob;
+ /* Result may be NULL, that's OK. */
+ xf->xod = ED_object_data_xform_create(ob->data);
+ *xf_p = xf;
+ }
+}
+
+/**
+ * This may be called multiple times with the same data.
+ * Each time, the original transformations are re-applied, instead of accumulating the changes.
+ */
+void ED_object_data_xform_container_update_all(struct XFormObjectData_Container *xds,
+ struct Main *bmain,
+ Depsgraph *depsgraph)
+{
+ if (xds->obdata_in_obmode_map == NULL) {
+ return;
+ }
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, xds->obdata_in_obmode_map) {
+ ID *id = BLI_ghashIterator_getKey(&gh_iter);
+ struct XFormObjectData_Extra *xf = BLI_ghashIterator_getValue(&gh_iter);
+ if (xf->xod == NULL) {
+ continue;
+ }
+
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, xf->ob);
+ float imat[4][4], dmat[4][4];
+ invert_m4_m4(imat, xf->obmat_orig);
+ mul_m4_m4m4(dmat, imat, ob_eval->obmat);
+ invert_m4(dmat);
+
+ ED_object_data_xform_by_mat4(xf->xod, dmat);
+ if (xf->ob->type == OB_ARMATURE) {
+ /* TODO: none of the current flags properly update armatures, needs investigation. */
+ DEG_id_tag_update(id, 0);
+ }
+ else {
+ DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
+ }
+ }
+}
+
+/** Callback for #GHash free. */
+static void trans_obdata_in_obmode_free_elem(void *xf_p)
+{
+ struct XFormObjectData_Extra *xf = xf_p;
+ if (xf->xod) {
+ ED_object_data_xform_destroy(xf->xod);
+ }
+ MEM_freeN(xf);
+}
+
+struct XFormObjectData_Container *ED_object_data_xform_container_create(void)
+{
+ struct XFormObjectData_Container *xds = MEM_callocN(sizeof(*xds), __func__);
+ xds->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
+ return xds;
+}
+
+void ED_object_data_xform_container_destroy(struct XFormObjectData_Container *xds)
+{
+ BLI_ghash_free(xds->obdata_in_obmode_map, NULL, trans_obdata_in_obmode_free_elem);
+ MEM_freeN(xds);
+}
+
+/** \} */
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 05fa78aab1c..fb79cfb910e 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -21,17 +21,17 @@
* \ingroup edobj
*/
-#include <string.h>
-#include <stddef.h>
-#include <math.h>
#include <assert.h>
+#include <math.h>
+#include <stddef.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -39,23 +39,24 @@
#include "BLI_alloca.h"
#include "BLI_array.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_utildefines_stack.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_deform.h"
-#include "BKE_mesh_mapping.h"
-#include "BKE_mesh_runtime.h"
#include "BKE_editmesh.h"
+#include "BKE_lattice.h"
#include "BKE_layer.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
-#include "BKE_report.h"
-#include "BKE_object_deform.h"
#include "BKE_object.h"
-#include "BKE_lattice.h"
+#include "BKE_object_deform.h"
+#include "BKE_report.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -69,8 +70,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "UI_resources.h"
@@ -104,7 +105,7 @@ bool ED_vgroup_sync_from_pose(Object *ob)
if (armobj && (armobj->mode & OB_MODE_POSE)) {
struct bArmature *arm = armobj->data;
if (arm->act_bone) {
- int def_num = defgroup_name_index(ob, arm->act_bone->name);
+ int def_num = BKE_object_defgroup_name_index(ob, arm->act_bone->name);
if (def_num != -1) {
ob->actdef = def_num + 1;
return true;
@@ -129,7 +130,7 @@ void ED_vgroup_data_clamp_range(ID *id, const int total)
int j;
for (j = 0; j < dv->totweight; j++) {
if (dv->dw[j].def_nr >= total) {
- defvert_remove_group(dv, &dv->dw[j]);
+ BKE_defvert_remove_group(dv, &dv->dw[j]);
j--;
}
}
@@ -270,7 +271,7 @@ void ED_vgroup_parray_mirror_sync(Object *ob,
}
int flip_map_len;
- const int *flip_map = defgroup_flip_map(ob, &flip_map_len, true);
+ const int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true);
for (int i_src = 0; i_src < dvert_tot; i_src++) {
if (dvert_array[i_src] != NULL) {
@@ -281,7 +282,8 @@ void ED_vgroup_parray_mirror_sync(Object *ob,
const MDeformVert *dv_src = dvert_array[i_src];
MDeformVert *dv_dst = dvert_array_all[i_dst];
- defvert_mirror_subset(dv_dst, dv_src, vgroup_validmap, vgroup_tot, flip_map, flip_map_len);
+ BKE_defvert_mirror_subset(
+ dv_dst, dv_src, vgroup_validmap, vgroup_tot, flip_map, flip_map_len);
dvert_array[i_dst] = dvert_array_all[i_dst];
}
@@ -358,7 +360,7 @@ void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array,
dw = dv->dw + j;
if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
if (dw->weight <= epsilon) {
- defvert_remove_group(dv, dw);
+ BKE_defvert_remove_group(dv, dw);
}
}
}
@@ -460,7 +462,7 @@ void ED_vgroup_parray_to_weight_array(const MDeformVert **dvert_array,
for (i = 0; i < dvert_tot; i++) {
const MDeformVert *dv = dvert_array[i];
- dvert_weights[i] = dv ? defvert_find_weight(dv, def_nr) : 0.0f;
+ dvert_weights[i] = dv ? BKE_defvert_find_weight(dv, def_nr) : 0.0f;
}
}
@@ -476,15 +478,15 @@ void ED_vgroup_parray_from_weight_array(MDeformVert **dvert_array,
MDeformVert *dv = dvert_array[i];
if (dv) {
if (dvert_weights[i] > 0.0f) {
- MDeformWeight *dw = defvert_verify_index(dv, def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(dv, def_nr);
BLI_assert(IN_RANGE_INCL(dvert_weights[i], 0.0f, 1.0f));
dw->weight = dvert_weights[i];
}
else {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr);
if (dw) {
if (remove_zero) {
- defvert_remove_group(dv, dw);
+ BKE_defvert_remove_group(dv, dw);
}
else {
dw->weight = 0.0f;
@@ -504,15 +506,16 @@ static void mesh_defvert_mirror_update_internal(Object *ob,
if (def_nr == -1) {
/* all vgroups, add groups where needed */
int flip_map_len;
- int *flip_map = defgroup_flip_map(ob, &flip_map_len, true);
- defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true);
+ int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true);
+ BKE_defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true);
MEM_freeN(flip_map);
}
else {
/* single vgroup */
- MDeformWeight *dw = defvert_verify_index(dvert_dst, defgroup_flip_index(ob, def_nr, 1));
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert_dst,
+ BKE_object_defgroup_flip_index(ob, def_nr, 1));
if (dw) {
- dw->weight = defvert_find_weight(dvert_src, def_nr);
+ dw->weight = BKE_defvert_find_weight(dvert_src, def_nr);
}
}
}
@@ -588,8 +591,8 @@ static void vgroup_remove_weight(Object *ob, const int def_nr)
dvert_act = ED_mesh_active_dvert_get_only(ob);
- dw = defvert_find_index(dvert_act, def_nr);
- defvert_remove_group(dvert_act, dw);
+ dw = BKE_defvert_find_index(dvert_act, def_nr);
+ BKE_defvert_remove_group(dvert_act, dw);
}
static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type)
@@ -615,7 +618,7 @@ static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type
vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
ob, subset_type, &vgroup_tot, &subset_count);
- defvert_normalize_subset(dvert_act, vgroup_validmap, vgroup_tot);
+ BKE_defvert_normalize_subset(dvert_act, vgroup_validmap, vgroup_tot);
MEM_freeN((void *)vgroup_validmap);
if (me->editflag & ME_EDIT_MIRROR_X) {
@@ -650,7 +653,7 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve != eve_act) {
MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
+ BKE_defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
if (me->editflag & ME_EDIT_MIRROR_X) {
ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
}
@@ -667,7 +670,7 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
dv = me->dvert;
for (i = 0; i < me->totvert; i++, dv++) {
if ((me->mvert[i].flag & SELECT) && dv != dvert_act) {
- defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
+ BKE_defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
if (me->editflag & ME_EDIT_MIRROR_X) {
ED_mesh_defvert_mirror_update_ob(ob, -1, i);
}
@@ -701,7 +704,7 @@ const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext *
PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop),
bool *r_free,
- const unsigned int selection_mask)
+ const uint selection_mask)
{
Object *ob;
EnumPropertyItem *item = NULL;
@@ -803,7 +806,7 @@ static void ED_vgroup_nr_vert_add(
MDeformWeight *dw;
/* Lets first check to see if this vert is already in the weight group - if so lets update it. */
- dw = defvert_find_index(dv, def_nr);
+ dw = BKE_defvert_find_index(dv, def_nr);
if (dw) {
switch (assignmode) {
@@ -820,7 +823,7 @@ static void ED_vgroup_nr_vert_add(
dw->weight -= weight;
/* If the weight is zero or less than remove the vert from the deform group. */
if (dw->weight <= 0.0f) {
- defvert_remove_group(dv, dw);
+ BKE_defvert_remove_group(dv, dw);
}
break;
}
@@ -838,7 +841,7 @@ static void ED_vgroup_nr_vert_add(
/* If we are doing an additive assignment, then we need to create the deform weight. */
/* We checked if the vertex was added before so no need to test again, simply add. */
- defvert_add_index_notest(dv, def_nr, weight);
+ BKE_defvert_add_index_notest(dv, def_nr, weight);
break;
}
}
@@ -896,8 +899,8 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
MDeformVert *dv = &dvert[vertnum];
MDeformWeight *dw;
- dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
+ dw = BKE_defvert_find_index(dv, def_nr);
+ BKE_defvert_remove_group(dv, dw); /* dw can be NULL */
}
}
}
@@ -946,7 +949,7 @@ static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
}
if (dv) {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr);
if (dw) {
return dw->weight;
}
@@ -970,7 +973,7 @@ void ED_vgroup_select_by_name(Object *ob, const char *name)
{
/* note: ob->actdef==0 signals on painting to create a new one,
* if a bone in posemode is selected */
- ob->actdef = defgroup_name_index(ob, name) + 1;
+ ob->actdef = BKE_object_defgroup_name_index(ob, name) + 1;
}
/********************** Operator Implementations *********************/
@@ -998,7 +1001,7 @@ static void vgroup_select_verts(Object *ob, int select)
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- if (defvert_find_index(dv, def_nr)) {
+ if (BKE_defvert_find_index(dv, def_nr)) {
BM_vert_select_set(em->bm, eve, select);
}
}
@@ -1024,7 +1027,7 @@ static void vgroup_select_verts(Object *ob, int select)
for (i = 0; i < me->totvert; i++, mv++, dv++) {
if (!(mv->flag & ME_HIDE)) {
- if (defvert_find_index(dv, def_nr)) {
+ if (BKE_defvert_find_index(dv, def_nr)) {
if (select) {
mv->flag |= SELECT;
}
@@ -1051,7 +1054,7 @@ static void vgroup_select_verts(Object *ob, int select)
tot = lt->pntsu * lt->pntsv * lt->pntsw;
for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
- if (defvert_find_index(dv, def_nr)) {
+ if (BKE_defvert_find_index(dv, def_nr)) {
if (select) {
bp->f1 |= SELECT;
}
@@ -1087,9 +1090,9 @@ static void vgroup_duplicate(Object *ob)
BLI_strncpy(name, dg->name, sizeof(name));
}
- cdg = defgroup_duplicate(dg);
+ cdg = BKE_defgroup_duplicate(dg);
BLI_strncpy(cdg->name, name, sizeof(cdg->name));
- defgroup_unique_name(cdg, ob);
+ BKE_object_defgroup_unique_name(cdg, ob);
BLI_addtail(&ob->defbase, cdg);
@@ -1103,11 +1106,11 @@ static void vgroup_duplicate(Object *ob)
if (dvert_array) {
for (i = 0; i < dvert_tot; i++) {
MDeformVert *dv = dvert_array[i];
- dw_org = defvert_find_index(dv, idg);
+ dw_org = BKE_defvert_find_index(dv, idg);
if (dw_org) {
- /* defvert_verify_index re-allocs org so need to store the weight first */
+ /* BKE_defvert_ensure_index re-allocs org so need to store the weight first */
const float weight = dw_org->weight;
- dw_cpy = defvert_verify_index(dv, icdg);
+ dw_cpy = BKE_defvert_ensure_index(dv, icdg);
dw_cpy->weight = weight;
}
}
@@ -1141,7 +1144,7 @@ static bool vgroup_normalize(Object *ob)
continue;
}
- dw = defvert_find_index(dv, def_nr);
+ dw = BKE_defvert_find_index(dv, def_nr);
if (dw) {
weight_max = max_ff(dw->weight, weight_max);
}
@@ -1155,7 +1158,7 @@ static bool vgroup_normalize(Object *ob)
continue;
}
- dw = defvert_find_index(dv, def_nr);
+ dw = BKE_defvert_find_index(dv, def_nr);
if (dw) {
dw->weight /= weight_max;
@@ -1578,7 +1581,7 @@ static void vgroup_levels_subset(Object *ob,
j = vgroup_tot;
while (j--) {
if (vgroup_validmap[j]) {
- dw = defvert_find_index(dv, j);
+ dw = BKE_defvert_find_index(dv, j);
if (dw) {
dw->weight = gain * (dw->weight + offset);
@@ -1642,13 +1645,13 @@ static bool vgroup_normalize_all(Object *ob,
/* in case its not selected */
if ((dv = dvert_array[i])) {
if (lock_flags) {
- defvert_normalize_lock_map(dv, vgroup_validmap, vgroup_tot, lock_flags, defbase_tot);
+ BKE_defvert_normalize_lock_map(dv, vgroup_validmap, vgroup_tot, lock_flags, defbase_tot);
}
else if (lock_active) {
- defvert_normalize_lock_single(dv, vgroup_validmap, vgroup_tot, def_nr);
+ BKE_defvert_normalize_lock_single(dv, vgroup_validmap, vgroup_tot, def_nr);
}
else {
- defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
+ BKE_defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
}
}
}
@@ -1687,13 +1690,78 @@ static const EnumPropertyItem vgroup_lock_actions[] = {
{0, NULL, 0, NULL, NULL},
};
-static void vgroup_lock_all(Object *ob, int action)
+enum {
+ VGROUP_MASK_ALL,
+ VGROUP_MASK_SELECTED,
+ VGROUP_MASK_UNSELECTED,
+ VGROUP_MASK_INVERT_UNSELECTED,
+};
+
+static const EnumPropertyItem vgroup_lock_mask[] = {
+ {VGROUP_MASK_ALL, "ALL", 0, "All", "Apply action to all vertex groups"},
+ {VGROUP_MASK_SELECTED, "SELECTED", 0, "Selected", "Apply to selected vertex groups"},
+ {VGROUP_MASK_UNSELECTED, "UNSELECTED", 0, "Unselected", "Apply to unselected vertex groups"},
+ {VGROUP_MASK_INVERT_UNSELECTED,
+ "INVERT_UNSELECTED",
+ 0,
+ "Invert Unselected",
+ "Apply the opposite of Lock/Unlock to unselected vertex groups"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static bool *vgroup_selected_get(Object *ob)
+{
+ int sel_count = 0, defbase_tot = BLI_listbase_count(&ob->defbase);
+ bool *mask;
+
+ if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ mask = BKE_object_defgroup_selected_get(ob, defbase_tot, &sel_count);
+
+ /* Mirror the selection if X Mirror is enabled. */
+ Mesh *me = BKE_mesh_from_object(ob);
+
+ if (me && (me->editflag & ME_EDIT_MIRROR_X) != 0) {
+ BKE_object_defgroup_mirror_selection(ob, defbase_tot, mask, mask, &sel_count);
+ }
+ }
+ else {
+ mask = MEM_callocN(defbase_tot * sizeof(bool), __func__);
+ }
+
+ if (sel_count == 0 && ob->actdef >= 1 && ob->actdef <= defbase_tot) {
+ mask[ob->actdef - 1] = true;
+ }
+
+ return mask;
+}
+
+static void vgroup_lock_all(Object *ob, int action, int mask)
{
bDeformGroup *dg;
+ bool *selected = NULL;
+ int i;
+
+ if (mask != VGROUP_MASK_ALL) {
+ selected = vgroup_selected_get(ob);
+ }
if (action == VGROUP_TOGGLE) {
action = VGROUP_LOCK;
- for (dg = ob->defbase.first; dg; dg = dg->next) {
+
+ for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
+ switch (mask) {
+ case VGROUP_MASK_INVERT_UNSELECTED:
+ case VGROUP_MASK_SELECTED:
+ if (!selected[i])
+ continue;
+ break;
+ case VGROUP_MASK_UNSELECTED:
+ if (selected[i])
+ continue;
+ break;
+ default:;
+ }
+
if (dg->flag & DG_LOCK_WEIGHT) {
action = VGROUP_UNLOCK;
break;
@@ -1701,7 +1769,19 @@ static void vgroup_lock_all(Object *ob, int action)
}
}
- for (dg = ob->defbase.first; dg; dg = dg->next) {
+ for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
+ switch (mask) {
+ case VGROUP_MASK_SELECTED:
+ if (!selected[i])
+ continue;
+ break;
+ case VGROUP_MASK_UNSELECTED:
+ if (selected[i])
+ continue;
+ break;
+ default:;
+ }
+
switch (action) {
case VGROUP_LOCK:
dg->flag |= DG_LOCK_WEIGHT;
@@ -1713,6 +1793,14 @@ static void vgroup_lock_all(Object *ob, int action)
dg->flag ^= DG_LOCK_WEIGHT;
break;
}
+
+ if (mask == VGROUP_MASK_INVERT_UNSELECTED && !selected[i]) {
+ dg->flag ^= DG_LOCK_WEIGHT;
+ }
+ }
+
+ if (selected) {
+ MEM_freeN(selected);
}
}
@@ -1747,10 +1835,10 @@ static void vgroup_invert_subset(Object *ob,
if (vgroup_validmap[j]) {
if (auto_assign) {
- dw = defvert_verify_index(dv, j);
+ dw = BKE_defvert_ensure_index(dv, j);
}
else {
- dw = defvert_find_index(dv, j);
+ dw = BKE_defvert_find_index(dv, j);
}
if (dw) {
@@ -1807,10 +1895,10 @@ static void vgroup_smooth_subset(Object *ob,
float *weight_accum_prev;
float *weight_accum_curr;
- unsigned int subset_index;
+ uint subset_index;
/* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */
- unsigned int *verts_used;
+ uint *verts_used;
STACK_DECLARE(verts_used);
BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
@@ -1882,12 +1970,12 @@ static void vgroup_smooth_subset(Object *ob,
memcpy(weight_accum_curr, weight_accum_prev, sizeof(*weight_accum_curr) * dvert_tot);
for (iter = 0; iter < repeat; iter++) {
- unsigned *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used);
+ uint *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used);
/* avoid looping over all verts */
// for (i = 0; i < dvert_tot; i++)
for (vi_step = verts_used; vi_step != vi_end; vi_step++) {
- const unsigned int i = *vi_step;
+ const uint i = *vi_step;
float weight_tot = 0.0f;
float weight = 0.0f;
@@ -2188,28 +2276,28 @@ static void dvert_mirror_op(MDeformVert *dvert,
SWAP(MDeformVert, *dvert, *dvert_mirr);
}
else {
- MDeformWeight *dw = defvert_find_index(dvert, act_vgroup);
- MDeformWeight *dw_mirr = defvert_find_index(dvert_mirr, act_vgroup);
+ MDeformWeight *dw = BKE_defvert_find_index(dvert, act_vgroup);
+ MDeformWeight *dw_mirr = BKE_defvert_find_index(dvert_mirr, act_vgroup);
if (dw && dw_mirr) {
SWAP(float, dw->weight, dw_mirr->weight);
}
else if (dw) {
- dw_mirr = defvert_verify_index(dvert_mirr, act_vgroup);
+ dw_mirr = BKE_defvert_ensure_index(dvert_mirr, act_vgroup);
dw_mirr->weight = dw->weight;
- defvert_remove_group(dvert, dw);
+ BKE_defvert_remove_group(dvert, dw);
}
else if (dw_mirr) {
- dw = defvert_verify_index(dvert, act_vgroup);
+ dw = BKE_defvert_ensure_index(dvert, act_vgroup);
dw->weight = dw_mirr->weight;
- defvert_remove_group(dvert_mirr, dw_mirr);
+ BKE_defvert_remove_group(dvert_mirr, dw_mirr);
}
}
}
if (flip_vgroups) {
- defvert_flip(dvert, flip_map, flip_map_len);
- defvert_flip(dvert_mirr, flip_map, flip_map_len);
+ BKE_defvert_flip(dvert, flip_map, flip_map_len);
+ BKE_defvert_flip(dvert_mirr, flip_map, flip_map_len);
}
}
else {
@@ -2220,16 +2308,16 @@ static void dvert_mirror_op(MDeformVert *dvert,
if (mirror_weights) {
if (all_vgroups) {
- defvert_copy(dvert, dvert_mirr);
+ BKE_defvert_copy(dvert, dvert_mirr);
}
else {
- defvert_copy_index(dvert, act_vgroup, dvert_mirr, act_vgroup);
+ BKE_defvert_copy_index(dvert, act_vgroup, dvert_mirr, act_vgroup);
}
}
/* flip map already modified for 'all_vgroups' */
if (flip_vgroups) {
- defvert_flip(dvert, flip_map, flip_map_len);
+ BKE_defvert_flip(dvert, flip_map, flip_map_len);
}
}
}
@@ -2272,8 +2360,8 @@ void ED_vgroup_mirror(Object *ob,
}
if (flip_vgroups) {
- flip_map = all_vgroups ? defgroup_flip_map(ob, &flip_map_len, false) :
- defgroup_flip_map_single(ob, &flip_map_len, false, def_nr);
+ flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, &flip_map_len, false) :
+ BKE_object_defgroup_flip_map_single(ob, &flip_map_len, false, def_nr);
BLI_assert(flip_map != NULL);
@@ -2490,7 +2578,7 @@ static void vgroup_assign_verts(Object *ob, const float weight)
MDeformVert *dv;
MDeformWeight *dw;
dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); /* can be NULL */
- dw = defvert_verify_index(dv, def_nr);
+ dw = BKE_defvert_ensure_index(dv, def_nr);
if (dw) {
dw->weight = weight;
}
@@ -2512,7 +2600,7 @@ static void vgroup_assign_verts(Object *ob, const float weight)
for (i = 0; i < me->totvert; i++, mv++, dv++) {
if (mv->flag & SELECT) {
MDeformWeight *dw;
- dw = defvert_verify_index(dv, def_nr);
+ dw = BKE_defvert_ensure_index(dv, def_nr);
if (dw) {
dw->weight = weight;
}
@@ -2537,7 +2625,7 @@ static void vgroup_assign_verts(Object *ob, const float weight)
if (bp->f1 & SELECT) {
MDeformWeight *dw;
- dw = defvert_verify_index(dv, def_nr);
+ dw = BKE_defvert_ensure_index(dv, def_nr);
if (dw) {
dw->weight = weight;
}
@@ -3176,24 +3264,84 @@ static int vertex_group_lock_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
int action = RNA_enum_get(op->ptr, "action");
+ int mask = RNA_enum_get(op->ptr, "mask");
- vgroup_lock_all(ob, action);
+ vgroup_lock_all(ob, action, mask);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
+static char *vertex_group_lock_description(struct bContext *UNUSED(C),
+ struct wmOperatorType *UNUSED(op),
+ struct PointerRNA *params)
+{
+ int action = RNA_enum_get(params, "action");
+ int mask = RNA_enum_get(params, "mask");
+
+ const char *action_str, *target_str;
+
+ switch (action) {
+ case VGROUP_LOCK:
+ action_str = "Lock";
+ break;
+ case VGROUP_UNLOCK:
+ action_str = "Unlock";
+ break;
+ case VGROUP_TOGGLE:
+ action_str = "Toggle locks of";
+ break;
+ case VGROUP_INVERT:
+ action_str = "Invert locks of";
+ break;
+ default:
+ return NULL;
+ }
+
+ switch (mask) {
+ case VGROUP_MASK_ALL:
+ target_str = "all";
+ break;
+ case VGROUP_MASK_SELECTED:
+ target_str = "selected";
+ break;
+ case VGROUP_MASK_UNSELECTED:
+ target_str = "unselected";
+ break;
+ case VGROUP_MASK_INVERT_UNSELECTED:
+ switch (action) {
+ case VGROUP_INVERT:
+ target_str = "selected";
+ break;
+ case VGROUP_LOCK:
+ target_str = "selected and unlock unselected";
+ break;
+ case VGROUP_UNLOCK:
+ target_str = "selected and lock unselected";
+ break;
+ default:
+ target_str = "all and invert unselected";
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ return BLI_sprintfN("%s %s vertex groups of the active object", action_str, target_str);
+}
+
void OBJECT_OT_vertex_group_lock(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Change the Lock On Vertex Groups";
ot->idname = "OBJECT_OT_vertex_group_lock";
- ot->description = "Change the lock state of all vertex groups of active object";
+ ot->description = "Change the lock state of all or some vertex groups of active object";
/* api callbacks */
ot->poll = vertex_group_poll;
ot->exec = vertex_group_lock_exec;
+ ot->get_description = vertex_group_lock_description;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -3204,6 +3352,13 @@ void OBJECT_OT_vertex_group_lock(wmOperatorType *ot)
VGROUP_TOGGLE,
"Action",
"Lock action to execute on vertex groups");
+
+ RNA_def_enum(ot->srna,
+ "mask",
+ vgroup_lock_mask,
+ VGROUP_MASK_ALL,
+ "Mask",
+ "Apply the action based on vertex group selection");
}
static int vertex_group_invert_exec(bContext *C, wmOperator *op)
@@ -3732,7 +3887,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
if (dvert->totweight) {
- defvert_remap(dvert, sort_map, defbase_tot);
+ BKE_defvert_remap(dvert, sort_map, defbase_tot);
}
}
}
@@ -3752,7 +3907,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
if (dvert) {
while (dvert_tot--) {
if (dvert->totweight) {
- defvert_remap(dvert, sort_map, defbase_tot);
+ BKE_defvert_remap(dvert, sort_map, defbase_tot);
}
dvert++;
}
@@ -3790,7 +3945,7 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
{
if (bonebase == NULL) {
- Object *armobj = modifiers_isDeformedByArmature(ob);
+ Object *armobj = BKE_modifiers_is_deformed_by_armature(ob);
if (armobj != NULL) {
bArmature *armature = armobj->data;
bonebase = &armature->bonebase;
@@ -3800,7 +3955,7 @@ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
if (bonebase != NULL) {
Bone *bone;
for (bone = bonebase->last; bone; bone = bone->prev) {
- bDeformGroup *dg = defgroup_find_name(ob, bone->name);
+ bDeformGroup *dg = BKE_object_defgroup_find_name(ob, bone->name);
vgroup_sort_bone_hierarchy(ob, &bone->childbase);
if (dg != NULL) {
@@ -3952,12 +4107,12 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
if (dvert_act == NULL) {
return;
}
- weight_act = defvert_find_weight(dvert_act, def_nr);
+ weight_act = BKE_defvert_find_weight(dvert_act, def_nr);
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && (eve != eve_act)) {
MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr);
if (dw) {
dw->weight = weight_act;
@@ -3980,12 +4135,12 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
if (dvert_act == NULL) {
return;
}
- weight_act = defvert_find_weight(dvert_act, def_nr);
+ weight_act = BKE_defvert_find_weight(dvert_act, def_nr);
dv = me->dvert;
for (i = 0; i < me->totvert; i++, dv++) {
if ((me->mvert[i].flag & SELECT) && (dv != dvert_act)) {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr);
if (dw) {
dw->weight = weight_act;
if (me->editflag & ME_EDIT_MIRROR_X) {
diff --git a/source/blender/editors/object/object_volume.c b/source/blender/editors/object/object_volume.c
new file mode 100644
index 00000000000..3c1f7da2bd6
--- /dev/null
+++ b/source/blender/editors/object/object_volume.c
@@ -0,0 +1,197 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edobj
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_fileops.h"
+#include "BLI_listbase.h"
+#include "BLI_math_base.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "DNA_object_types.h"
+#include "DNA_volume_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BKE_context.h"
+#include "BKE_lib_id.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_volume.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_image.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+
+#include "object_intern.h"
+
+/* Volume Add */
+
+static Object *object_volume_add(bContext *C, wmOperator *op, const char *name)
+{
+ ushort local_view_bits;
+ float loc[3], rot[3];
+
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return false;
+ }
+ return ED_object_add_type(C, OB_VOLUME, name, loc, rot, false, local_view_bits);
+}
+
+static int object_volume_add_exec(bContext *C, wmOperator *op)
+{
+ return (object_volume_add(C, op, NULL) != NULL) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_volume_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Volume";
+ ot->description = "Add a volume object to the scene";
+ ot->idname = "OBJECT_OT_volume_add";
+
+ /* api callbacks */
+ ot->exec = object_volume_add_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, false);
+}
+
+/* Volume Import */
+
+static int volume_import_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ bool imported = false;
+
+ ListBase ranges = ED_image_filesel_detect_sequences(bmain, op, false);
+ LISTBASE_FOREACH (ImageFrameRange *, range, &ranges) {
+ char filename[FILE_MAX];
+ BLI_split_file_part(range->filepath, filename, sizeof(filename));
+ BLI_path_extension_replace(filename, sizeof(filename), "");
+
+ Object *object = object_volume_add(C, op, filename);
+ Volume *volume = (Volume *)object->data;
+
+ STRNCPY(volume->filepath, range->filepath);
+ if (is_relative_path) {
+ BLI_path_rel(volume->filepath, BKE_main_blendfile_path(bmain));
+ }
+
+ if (!BKE_volume_load(volume, bmain)) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Volume \"%s\" failed to load: %s",
+ filename,
+ BKE_volume_grids_error_msg(volume));
+ BKE_id_delete(bmain, &object->id);
+ BKE_id_delete(bmain, &volume->id);
+ continue;
+ }
+ else if (BKE_volume_is_points_only(volume)) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Volume \"%s\" contains points, only voxel grids are supported",
+ filename);
+ BKE_id_delete(bmain, &object->id);
+ BKE_id_delete(bmain, &volume->id);
+ continue;
+ }
+
+ /* Set sequence parameters after trying to load the first frame, for file validation we want
+ * to use a consistent frame rather than whatever corresponds to the current scene frame. */
+ volume->is_sequence = (range->length > 1);
+ volume->frame_duration = (volume->is_sequence) ? range->length : 0;
+ volume->frame_start = 1;
+ volume->frame_offset = (volume->is_sequence) ? range->offset - 1 : 0;
+
+ if (BKE_volume_is_y_up(volume)) {
+ object->rot[0] += M_PI_2;
+ }
+
+ BKE_volume_unload(volume);
+
+ imported = true;
+ }
+ BLI_freelistN(&ranges);
+
+ return (imported) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+static int volume_import_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ return volume_import_exec(C, op);
+ }
+
+ RNA_string_set(op->ptr, "filepath", U.textudir);
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* called by other space types too */
+void OBJECT_OT_volume_import(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Import OpenVDB Volume";
+ ot->description = "Import OpenVDB volume file";
+ ot->idname = "OBJECT_OT_volume_import";
+
+ /* api callbacks */
+ ot->exec = volume_import_exec;
+ ot->invoke = volume_import_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_VOLUME,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES |
+ WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+
+ RNA_def_boolean(
+ ot->srna,
+ "use_sequence_detection",
+ true,
+ "Detect Sequences",
+ "Automatically detect animated sequences in selected volume files (based on file names)");
+
+ ED_object_add_generic_props(ot, false);
+}
diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c
index 836e38e3676..00f9330c8a7 100644
--- a/source/blender/editors/object/object_warp.c
+++ b/source/blender/editors/object/object_warp.c
@@ -35,8 +35,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_view3d.h"
#include "ED_transverts.h"
+#include "ED_view3d.h"
#include "object_intern.h"
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index c06c21b9057..6922a03b12f 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -37,11 +37,11 @@
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_object_deform.h"
#include "BKE_dynamicpaint.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "BKE_object_deform.h"
#include "BKE_report.h"
#include "BKE_screen.h"
@@ -50,8 +50,8 @@
#include "DEG_depsgraph_query.h"
#include "ED_mesh.h"
-#include "ED_screen.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -59,8 +59,8 @@
#include "PIL_time.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "physics_intern.h" /* own include */
@@ -72,7 +72,7 @@ static int surface_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
DynamicPaintSurface *surface;
/* Make sure we're dealing with a canvas */
- pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
+ pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type(cObject, eModifierType_DynamicPaint);
if (!pmd || !pmd->canvas) {
return OPERATOR_CANCELLED;
}
@@ -117,7 +117,7 @@ static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op))
int id = 0;
/* Make sure we're dealing with a canvas */
- pmd = (DynamicPaintModifierData *)modifiers_findByType(obj_ctx, eModifierType_DynamicPaint);
+ pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type(obj_ctx, eModifierType_DynamicPaint);
if (!pmd || !pmd->canvas) {
return OPERATOR_CANCELLED;
}
@@ -162,7 +162,7 @@ static int type_toggle_exec(bContext *C, wmOperator *op)
Object *cObject = ED_object_context(C);
Scene *scene = CTX_data_scene(C);
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type(
cObject, eModifierType_DynamicPaint);
int type = RNA_enum_get(op->ptr, "type");
@@ -222,7 +222,7 @@ static int output_toggle_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
DynamicPaintSurface *surface;
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type(
ob, eModifierType_DynamicPaint);
int output = RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */
@@ -259,7 +259,7 @@ static int output_toggle_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(CTX_data_main(C));
}
else {
- bDeformGroup *defgroup = defgroup_find_name(ob, name);
+ bDeformGroup *defgroup = BKE_object_defgroup_find_name(ob, name);
if (defgroup) {
BKE_object_defgroup_remove(ob, defgroup);
DEG_relations_tag_update(CTX_data_main(C));
@@ -483,7 +483,7 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
/*
* Get modifier data
*/
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type(
object_eval, eModifierType_DynamicPaint);
if (pmd == NULL) {
BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found");
diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c
index 55fc49165c9..22cfa50aee9 100644
--- a/source/blender/editors/physics/particle_boids.c
+++ b/source/blender/editors/physics/particle_boids.c
@@ -39,8 +39,8 @@
#include "DEG_depsgraph_build.h"
#include "RNA_access.h"
-#include "RNA_enum_types.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 120c4929ecf..6cafc51231c 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -21,26 +21,26 @@
* \ingroup edphys
*/
-#include <stdlib.h>
+#include <assert.h>
#include <math.h>
+#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
-#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_view3d_types.h"
+#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
-#include "BLI_math.h"
+#include "BLI_kdtree.h"
#include "BLI_lasso_2d.h"
#include "BLI_listbase.h"
-#include "BLI_rect.h"
-#include "BLI_kdtree.h"
+#include "BLI_math.h"
#include "BLI_rand.h"
+#include "BLI_rect.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
@@ -59,10 +59,10 @@
#include "DEG_depsgraph.h"
-#include "ED_object.h"
-#include "ED_physics.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_particle.h"
+#include "ED_physics.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_view3d.h"
@@ -74,9 +74,9 @@
#include "UI_resources.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -135,11 +135,11 @@ bool PE_hair_poll(bContext *C)
bool PE_poll_view3d(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
- return (PE_poll(C) && (sa && sa->spacetype == SPACE_VIEW3D) &&
- (ar && ar->regiontype == RGN_TYPE_WINDOW));
+ return (PE_poll(C) && (area && area->spacetype == SPACE_VIEW3D) &&
+ (region && region->regiontype == RGN_TYPE_WINDOW));
}
void PE_free_ptcache_edit(PTCacheEdit *edit)
@@ -207,7 +207,7 @@ static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *br
// UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
// float size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
- return brush->size * U.pixelsize;
+ return brush->size;
}
PTCacheEdit *PE_get_current_from_psys(ParticleSystem *psys)
@@ -481,14 +481,15 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
/* we may need to force an update here by setting the rv3d as dirty
* for now it seems ok, but take care!:
* rv3d->depths->dirty = 1; */
- ED_view3d_depth_update(data->vc.ar);
+ ED_view3d_depth_update(data->vc.region);
}
}
}
static bool PE_create_shape_tree(PEData *data, Object *shapeob)
{
- Mesh *mesh = BKE_object_get_evaluated_mesh(data->depsgraph, shapeob);
+ Object *shapeob_eval = DEG_get_evaluated_object(data->depsgraph, shapeob);
+ Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval);
memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
@@ -535,7 +536,7 @@ static bool key_test_depth(const PEData *data, const float co[3], const int scre
/* used to calculate here but all callers have the screen_co already, so pass as arg */
#if 0
- if (ED_view3d_project_int_global(data->vc.ar,
+ if (ED_view3d_project_int_global(data->vc.region,
co,
screen_co,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN |
@@ -555,7 +556,7 @@ static bool key_test_depth(const PEData *data, const float co[3], const int scre
}
float win[3];
- ED_view3d_project(data->vc.ar, co, win);
+ ED_view3d_project(data->vc.region, co, win);
if (win[2] - 0.00001f > depth) {
return 0;
@@ -571,7 +572,7 @@ static bool key_inside_circle(const PEData *data, float rad, const float co[3],
int screen_co[2];
/* TODO, should this check V3D_PROJ_TEST_CLIP_BB too? */
- if (ED_view3d_project_int_global(data->vc.ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) !=
+ if (ED_view3d_project_int_global(data->vc.region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) !=
V3D_PROJ_RET_OK) {
return 0;
}
@@ -599,7 +600,7 @@ static bool key_inside_rect(PEData *data, const float co[3])
{
int screen_co[2];
- if (ED_view3d_project_int_global(data->vc.ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) !=
+ if (ED_view3d_project_int_global(data->vc.region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) !=
V3D_PROJ_RET_OK) {
return 0;
}
@@ -848,7 +849,6 @@ static void foreach_mouse_hit_key(PEData *data, ForHitKeyMatFunc func, int selec
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
BLI_task_parallel_range(0, edit->totpoint, &iter_data, foreach_mouse_hit_key_iter, &settings);
}
@@ -1228,7 +1228,6 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
BLI_task_parallel_range(0, edit->totpoint, &iter_data, deflect_emitter_iter, &settings);
}
@@ -1277,7 +1276,6 @@ static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
BLI_task_parallel_range(0, edit->totpoint, &iter_data, apply_lengths_iter, &settings);
}
@@ -1352,7 +1350,6 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
BLI_task_parallel_range(0, edit->totpoint, &iter_data, iterate_lengths_iter, &settings);
}
@@ -2075,7 +2072,38 @@ void PARTICLE_OT_select_random(wmOperatorType *ot)
/************************ select linked operator ************************/
-static int select_linked_exec(bContext *C, wmOperator *op)
+static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PEData data;
+ PE_set_data(C, &data);
+ data.select = true;
+
+ foreach_selected_key(&data, select_keys);
+
+ PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked All";
+ ot->idname = "PARTICLE_OT_select_linked";
+ ot->description = "Select all keys linked to already selected ones";
+
+ /* api callbacks */
+ ot->exec = select_linked_exec;
+ ot->poll = PE_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+}
+
+static int select_linked_pick_exec(bContext *C, wmOperator *op)
{
PEData data;
int mval[2];
@@ -2097,22 +2125,22 @@ static int select_linked_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RNA_int_set_array(op->ptr, "location", event->mval);
- return select_linked_exec(C, op);
+ return select_linked_pick_exec(C, op);
}
-void PARTICLE_OT_select_linked(wmOperatorType *ot)
+void PARTICLE_OT_select_linked_pick(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select Linked";
- ot->idname = "PARTICLE_OT_select_linked";
+ ot->idname = "PARTICLE_OT_select_linked_pick";
ot->description = "Select nearest particle from mouse pointer";
/* api callbacks */
- ot->exec = select_linked_exec;
- ot->invoke = select_linked_invoke;
+ ot->exec = select_linked_pick_exec;
+ ot->invoke = select_linked_pick_invoke;
ot->poll = PE_poll_view3d;
/* flags */
@@ -2224,12 +2252,12 @@ bool PE_circle_select(bContext *C, const int sel_op, const int mval[2], float ra
/************************ lasso select operator ************************/
-int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const int sel_op)
+int PE_lasso_select(bContext *C, const int mcoords[][2], const int mcoords_len, const int sel_op)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ParticleEditSettings *pset = PE_settings(scene);
PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob);
ParticleSystem *psys = edit->psys;
@@ -2266,9 +2294,10 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const
mul_m4_v3(mat, co);
const bool is_select = key->flag & PEK_SELECT;
const bool is_inside =
- ((ED_view3d_project_int_global(ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) ==
+ ((ED_view3d_project_int_global(region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) ==
V3D_PROJ_RET_OK) &&
- BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) &&
+ BLI_lasso_is_point_inside(
+ mcoords, mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED) &&
key_test_depth(&data, co, screen_co));
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
@@ -2285,9 +2314,10 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const
mul_m4_v3(mat, co);
const bool is_select = key->flag & PEK_SELECT;
const bool is_inside =
- ((ED_view3d_project_int_global(ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) ==
+ ((ED_view3d_project_int_global(region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) ==
V3D_PROJ_RET_OK) &&
- BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) &&
+ BLI_lasso_is_point_inside(
+ mcoords, mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED) &&
key_test_depth(&data, co, screen_co));
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
@@ -2801,8 +2831,8 @@ static void remove_tagged_keys(Depsgraph *depsgraph, Object *ob, ParticleSystem
if (pe_x_mirror(ob)) {
/* mirror key tags */
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- ParticleSystemModifierData *psmd_eval = (ParticleSystemModifierData *)modifier_get_evaluated(
- depsgraph, ob, &psmd->modifier);
+ ParticleSystemModifierData *psmd_eval = (ParticleSystemModifierData *)
+ BKE_modifier_get_evaluated(depsgraph, ob, &psmd->modifier);
LOOP_POINTS {
LOOP_TAGGED_KEYS {
@@ -3519,7 +3549,7 @@ static void brush_comb(PEData *data,
static void brush_cut(PEData *data, int pa_index)
{
PTCacheEdit *edit = data->edit;
- ARegion *ar = data->vc.ar;
+ ARegion *region = data->vc.region;
Object *ob = data->ob;
ParticleEditSettings *pset = PE_settings(data->scene);
ParticleCacheKey *key = edit->pathcache[pa_index];
@@ -3539,7 +3569,7 @@ static void brush_cut(PEData *data, int pa_index)
return;
}
- if (ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) !=
+ if (ED_view3d_project_int_global(region, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) !=
V3D_PROJ_RET_OK) {
return;
}
@@ -3566,7 +3596,7 @@ static void brush_cut(PEData *data, int pa_index)
/* calculate path time closest to root that was inside the circle */
for (k = 1, key++; k <= keys; k++, key++) {
- if ((ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) !=
+ if ((ED_view3d_project_int_global(region, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) !=
V3D_PROJ_RET_OK) ||
key_test_depth(data, key->co, screen_co) == 0) {
x0 = (float)screen_co[0];
@@ -4052,7 +4082,6 @@ typedef struct BrushAddCountIterData {
short size;
float imat[4][4];
ParticleData *add_pars;
- int num_added;
} BrushAddCountIterData;
typedef struct BrushAddCountIterTLSData {
@@ -4081,7 +4110,7 @@ static void brush_add_count_iter(void *__restrict iter_data_v,
dmy = size;
if (tls->rng == NULL) {
tls->rng = BLI_rng_new_srandom(psys->seed + data->mval[0] + data->mval[1] +
- tls_v->thread_id);
+ BLI_task_parallel_thread_id(tls_v));
}
/* rejection sampling to get points in circle */
while (dmx * dmx + dmy * dmy > size2) {
@@ -4099,7 +4128,7 @@ static void brush_add_count_iter(void *__restrict iter_data_v,
mco[1] = data->mval[1] + dmy;
float co1[3], co2[3];
- ED_view3d_win_to_segment_clipped(depsgraph, data->vc.ar, data->vc.v3d, mco, co1, co2, true);
+ ED_view3d_win_to_segment_clipped(depsgraph, data->vc.region, data->vc.v3d, mco, co1, co2, true);
mul_m4_v3(iter_data->imat, co1);
mul_m4_v3(iter_data->imat, co2);
@@ -4144,12 +4173,19 @@ static void brush_add_count_iter(void *__restrict iter_data_v,
}
}
-static void brush_add_count_iter_finalize(void *__restrict userdata_v,
- void *__restrict userdata_chunk_v)
+static void brush_add_count_iter_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict join_v,
+ void *__restrict chunk_v)
+{
+ BrushAddCountIterTLSData *join = (BrushAddCountIterTLSData *)join_v;
+ BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v;
+ join->num_added += tls->num_added;
+}
+
+static void brush_add_count_iter_free(const void *__restrict UNUSED(userdata_v),
+ void *__restrict chunk_v)
{
- BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v;
- BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v;
- iter_data->num_added += tls->num_added;
+ BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v;
if (tls->rng != NULL) {
BLI_rng_free(tls->rng);
}
@@ -4213,23 +4249,22 @@ static int brush_add(const bContext *C, PEData *data, short number)
iter_data.number = number;
iter_data.size = size;
iter_data.add_pars = add_pars;
- iter_data.num_added = 0;
copy_m4_m4(iter_data.imat, imat);
BrushAddCountIterTLSData tls = {NULL};
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
settings.userdata_chunk = &tls;
settings.userdata_chunk_size = sizeof(BrushAddCountIterTLSData);
- settings.func_finalize = brush_add_count_iter_finalize;
+ settings.func_reduce = brush_add_count_iter_reduce;
+ settings.func_free = brush_add_count_iter_free;
BLI_task_parallel_range(0, number, &iter_data, brush_add_count_iter, &settings);
/* Convert add_parse to a dense array, where all new particles are in the
* beginning of the array.
*/
- n = iter_data.num_added;
+ n = tls.num_added;
for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) {
if (add_pars[current_iter].num == DMCACHE_NOTFOUND) {
continue;
@@ -4455,7 +4490,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = CTX_data_active_object(C);
PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
BrushEdit *bedit;
float min[3], max[3];
@@ -4477,7 +4512,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
bedit->ob = ob;
bedit->edit = edit;
- bedit->zfac = ED_view3d_calc_zfac(ar->regiondata, min, NULL);
+ bedit->zfac = ED_view3d_calc_zfac(region->regiondata, min, NULL);
/* cache view depths and settings for re-use */
PE_set_view3d_data(C, &bedit->data);
@@ -4496,7 +4531,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
ParticleEditSettings *pset = PE_settings(scene);
ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
ParticleBrushData *brush = &pset->brush[pset->brushtype];
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float vec[3], mousef[2];
int mval[2];
int flip, mouse[2], removed = 0, added = 0, selected = 0, tot_steps = 1, step = 1;
@@ -4564,7 +4599,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
invert_m4_m4(ob->imat, ob->obmat);
- ED_view3d_win_to_delta(ar, mval_f, vec, bedit->zfac);
+ ED_view3d_win_to_delta(region, mval_f, vec, bedit->zfac);
data.dvec = vec;
foreach_mouse_hit_key(&data, brush_comb, selected);
@@ -4858,7 +4893,7 @@ static void point_inside_bvh_cb(void *userdata,
}
/* true if the point is inside the shape mesh */
-static bool shape_cut_test_point(PEData *data, ParticleCacheKey *key)
+static bool shape_cut_test_point(PEData *data, ParticleEditSettings *pset, ParticleCacheKey *key)
{
BVHTreeFromMesh *shape_bvh = &data->shape_bvh;
const float dir[3] = {1.0f, 0.0f, 0.0f};
@@ -4867,8 +4902,11 @@ static bool shape_cut_test_point(PEData *data, ParticleCacheKey *key)
userdata.bvhdata = data->shape_bvh;
userdata.num_hits = 0;
+ float co_shape[3];
+ mul_v3_m4v3(co_shape, pset->shape_object->imat, key->co);
+
BLI_bvhtree_ray_cast_all(
- shape_bvh->tree, key->co, dir, 0.0f, BVH_RAYCAST_DIST_MAX, point_inside_bvh_cb, &userdata);
+ shape_bvh->tree, co_shape, dir, 0.0f, BVH_RAYCAST_DIST_MAX, point_inside_bvh_cb, &userdata);
/* for any point inside a watertight mesh the number of hits is uneven */
return (userdata.num_hits % 2) == 1;
@@ -4894,32 +4932,37 @@ static void shape_cut(PEData *data, int pa_index)
/* check if root is inside the cut shape */
key = edit->pathcache[pa_index];
- if (!shape_cut_test_point(data, key)) {
+ if (!shape_cut_test_point(data, pset, key)) {
cut_time = -1.0f;
cut = true;
}
else {
for (k = 0; k < totkeys; k++, key++) {
BVHTreeRayHit hit;
- float dir[3];
- float len;
- sub_v3_v3v3(dir, (key + 1)->co, key->co);
- len = normalize_v3(dir);
+ float co_curr_shape[3], co_next_shape[3];
+ float dir_shape[3];
+ float len_shape;
+
+ mul_v3_m4v3(co_curr_shape, pset->shape_object->imat, key->co);
+ mul_v3_m4v3(co_next_shape, pset->shape_object->imat, (key + 1)->co);
+
+ sub_v3_v3v3(dir_shape, co_next_shape, co_curr_shape);
+ len_shape = normalize_v3(dir_shape);
memset(&hit, 0, sizeof(hit));
hit.index = -1;
- hit.dist = len;
+ hit.dist = len_shape;
BLI_bvhtree_ray_cast(data->shape_bvh.tree,
- key->co,
- dir,
+ co_curr_shape,
+ dir_shape,
0.0f,
&hit,
data->shape_bvh.raycast_callback,
&data->shape_bvh);
if (hit.index >= 0) {
- if (hit.dist < len) {
- cut_time = (hit.dist / len + (float)k) / (float)totkeys;
+ if (hit.dist < len_shape) {
+ cut_time = ((hit.dist / len_shape) + (float)k) / (float)totkeys;
cut = true;
break;
}
@@ -5084,7 +5127,8 @@ void PE_create_particle_edit(
int totpoint;
if (psmd != NULL) {
- psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name);
+ psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findny_name(ob_eval,
+ psmd->modifier.name);
}
/* no psmd->dm happens in case particle system modifier is not enabled */
@@ -5188,14 +5232,6 @@ void PE_create_particle_edit(
psys = NULL;
}
- /* Causes assert on startup. */
-#if 0
- UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
- UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
-#else
- memset(edit->sel_col, 0xff, sizeof(edit->sel_col));
- memset(edit->nosel_col, 0x00, sizeof(edit->nosel_col));
-#endif
recalc_lengths(edit);
if (psys && !cache) {
recalc_emitter_field(depsgraph, ob, psys);
@@ -5219,8 +5255,8 @@ static bool particle_edit_toggle_poll(bContext *C)
return 0;
}
- return (ob->particlesystem.first || modifiers_findByType(ob, eModifierType_Cloth) ||
- modifiers_findByType(ob, eModifierType_Softbody));
+ return (ob->particlesystem.first || BKE_modifiers_findby_type(ob, eModifierType_Cloth) ||
+ BKE_modifiers_findby_type(ob, eModifierType_Softbody));
}
static void free_all_psys_edit(Object *object)
@@ -5265,7 +5301,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
* with possible changes applied when object was outside of the
* edit mode. */
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
- edit->psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(
+ edit->psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findny_name(
object_eval, edit->psmd->modifier.name);
recalc_emitter_field(depsgraph, ob, edit->psys);
}
diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c
index e85b025e28e..5b363bdca78 100644
--- a/source/blender/editors/physics/particle_edit_undo.c
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -21,15 +21,15 @@
* \ingroup edphys
*/
-#include <stdlib.h>
+#include <assert.h>
#include <math.h>
+#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
-#include "DNA_scene_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
#include "BLI_listbase.h"
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index c666697d15a..e75169a476b 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -31,15 +31,15 @@
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BKE_bvhutils.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
@@ -59,9 +59,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_object.h"
#include "ED_particle.h"
#include "ED_screen.h"
-#include "ED_object.h"
#include "UI_resources.h"
@@ -1037,9 +1037,6 @@ static void copy_particle_edit(Depsgraph *depsgraph,
}
update_world_cos(ob, edit);
- UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
- UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
-
recalc_lengths(edit);
recalc_emitter_field(depsgraph, ob, psys);
PE_update_object(depsgraph, scene, ob, true);
@@ -1067,7 +1064,7 @@ static void remove_particle_systems_from_object(Object *ob_to)
eModifierType_DynamicPaint,
eModifierType_Fluid)) {
BLI_remlink(&ob_to->modifiers, md);
- modifier_free(md);
+ BKE_modifier_free(md);
}
}
@@ -1141,13 +1138,13 @@ static bool copy_particle_systems_to_object(const bContext *C,
psys_unique_name(ob_to, psys, psys->name);
/* add a particle system modifier for each system */
- md = modifier_new(eModifierType_ParticleSystem);
+ md = BKE_modifier_new(eModifierType_ParticleSystem);
psmd = (ParticleSystemModifierData *)md;
/* push on top of the stack, no use trying to reproduce old stack order */
BLI_addtail(&ob_to->modifiers, md);
BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i);
- modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
+ BKE_modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
psmd->psys = psys;
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index 63979e247bf..ceaac201da3 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -18,7 +18,7 @@
*/
/** \file
- * \ingroup edphys
+ * \ingroup edphys
*/
#include <math.h>
@@ -33,37 +33,37 @@
#include "DNA_object_types.h"
#include "BLI_blenlib.h"
-#include "BLI_path_util.h"
#include "BLI_math.h"
+#include "BLI_path_util.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
+#include "BKE_fluid.h"
+#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BKE_fluid.h"
-#include "BKE_global.h"
#include "DEG_depsgraph.h"
#include "ED_screen.h"
#include "PIL_time.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
-#include "physics_intern.h" // own include
#include "manta_fluid_API.h"
+#include "physics_intern.h" // own include
-#include "DNA_scene_types.h"
#include "DNA_fluid_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
#define FLUID_JOB_BAKE_ALL "FLUID_OT_bake_all"
#define FLUID_JOB_BAKE_DATA "FLUID_OT_bake_data"
@@ -156,7 +156,7 @@ static bool fluid_initjob(
FluidDomainSettings *mds;
Object *ob = CTX_data_active_object(C);
- mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid);
if (!mmd) {
BLI_strncpy(error_msg, N_("Bake failed: no Fluid modifier found"), error_size);
return false;
@@ -185,12 +185,13 @@ static bool fluid_validatepaths(FluidJob *job, ReportList *reports)
temp_dir[0] = '\0';
bool is_relative = false;
- const char *relbase = modifier_path_relbase(job->bmain, job->ob);
+ const char *relbase = BKE_modifier_path_relbase(job->bmain, job->ob);
/* We do not accept empty paths, they can end in random places silently, see T51176. */
if (mds->cache_directory[0] == '\0') {
- modifier_path_init(
- mds->cache_directory, sizeof(mds->cache_directory), FLUID_DOMAIN_DIR_DEFAULT);
+ char cache_name[64];
+ BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name);
+ BKE_modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name);
BKE_reportf(reports,
RPT_WARNING,
"Fluid: Empty cache path, reset to default '%s'",
@@ -206,8 +207,9 @@ static bool fluid_validatepaths(FluidJob *job, ReportList *reports)
/* We change path to some presumably valid default value, but do not allow bake process to
* continue, this gives user chance to set manually another path. */
if (!dir_exists) {
- modifier_path_init(
- mds->cache_directory, sizeof(mds->cache_directory), FLUID_DOMAIN_DIR_DEFAULT);
+ char cache_name[64];
+ BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name);
+ BKE_modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name);
BKE_reportf(reports,
RPT_ERROR,
@@ -303,6 +305,12 @@ static void fluid_bake_sequence(FluidJob *job)
/* Update animation system */
ED_update_for_newframe(job->bmain, job->depsgraph);
+
+ /* If user requested stop, quit baking */
+ if (G.is_break) {
+ job->success = 0;
+ return;
+ }
}
/* Restore frame position that we were on before bake */
@@ -353,7 +361,7 @@ static void fluid_bake_endjob(void *customdata)
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start);
}
else {
- if (mds->error != NULL && mds->error[0] != '\0') {
+ if (mds->error[0] != '\0') {
WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error);
}
else { /* User canceled the bake */
@@ -368,7 +376,7 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update,
FluidDomainSettings *mds = job->mmd->domain;
char temp_dir[FILE_MAX];
- const char *relbase = modifier_path_relbase_from_global(job->ob);
+ const char *relbase = BKE_modifier_path_relbase_from_global(job->ob);
job->stop = stop;
job->do_update = do_update;
@@ -465,7 +473,7 @@ static void fluid_free_endjob(void *customdata)
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start);
}
else {
- if (mds->error != NULL && mds->error[0] != '\0') {
+ if (mds->error[0] != '\0') {
WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error);
}
else { /* User canceled the free job */
@@ -505,7 +513,9 @@ static void fluid_free_startjob(void *customdata, short *stop, short *do_update,
cache_map |= FLUID_DOMAIN_OUTDATED_PARTICLES;
}
if (fluid_is_free_guiding(job) || fluid_is_free_all(job)) {
- cache_map |= FLUID_DOMAIN_OUTDATED_GUIDE;
+ cache_map |= (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES |
+ FLUID_DOMAIN_OUTDATED_GUIDE);
}
#ifdef WITH_FLUID
BKE_fluid_cache_free(mds, job->ob, cache_map);
@@ -537,6 +547,8 @@ static int fluid_bake_exec(struct bContext *C, struct wmOperator *op)
if (!fluid_validatepaths(job, op->reports)) {
return OPERATOR_CANCELLED;
}
+ WM_report_banners_cancel(job->bmain);
+
fluid_bake_startjob(job, NULL, NULL, NULL);
fluid_bake_endjob(job);
fluid_bake_free(job);
@@ -564,6 +576,9 @@ static int fluid_bake_invoke(struct bContext *C,
return OPERATOR_CANCELLED;
}
+ /* Clear existing banners so that the upcoming progress bar from this job has more room. */
+ WM_report_banners_cancel(job->bmain);
+
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
CTX_wm_window(C),
scene,
@@ -591,7 +606,7 @@ static int fluid_bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *
}
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_PASS_THROUGH;
@@ -607,7 +622,7 @@ static int fluid_free_exec(struct bContext *C, struct wmOperator *op)
/*
* Get modifier data
*/
- mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid);
if (!mmd) {
BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found");
return OPERATOR_CANCELLED;
@@ -638,6 +653,9 @@ static int fluid_free_exec(struct bContext *C, struct wmOperator *op)
return OPERATOR_CANCELLED;
}
+ /* Clear existing banners so that the upcoming progress bar from this job has more room. */
+ WM_report_banners_cancel(job->bmain);
+
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
CTX_wm_window(C),
scene,
@@ -666,7 +684,7 @@ static int fluid_pause_exec(struct bContext *C, struct wmOperator *op)
/*
* Get modifier data
*/
- mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid);
if (!mmd) {
BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found");
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index 3af818b3a9d..87c3a709d47 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -38,6 +38,7 @@ void PARTICLE_OT_select_roots(struct wmOperatorType *ot);
void PARTICLE_OT_select_tips(struct wmOperatorType *ot);
void PARTICLE_OT_select_random(struct wmOperatorType *ot);
void PARTICLE_OT_select_linked(struct wmOperatorType *ot);
+void PARTICLE_OT_select_linked_pick(struct wmOperatorType *ot);
void PARTICLE_OT_select_less(struct wmOperatorType *ot);
void PARTICLE_OT_select_more(struct wmOperatorType *ot);
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index d1536733b9b..f6943c25063 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -28,9 +28,9 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_select_utils.h"
-#include "ED_physics.h"
#include "ED_object.h"
+#include "ED_physics.h"
+#include "ED_select_utils.h"
#include "physics_intern.h" // own include
@@ -43,6 +43,7 @@ static void operatortypes_particle(void)
WM_operatortype_append(PARTICLE_OT_select_tips);
WM_operatortype_append(PARTICLE_OT_select_random);
WM_operatortype_append(PARTICLE_OT_select_linked);
+ WM_operatortype_append(PARTICLE_OT_select_linked_pick);
WM_operatortype_append(PARTICLE_OT_select_less);
WM_operatortype_append(PARTICLE_OT_select_more);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 303a0714388..a59b031298c 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -31,7 +31,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 43ca421b9d0..78369345b9a 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -35,7 +35,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 11821fcdc45..17049fdb28b 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -22,15 +22,15 @@
*/
#include <math.h>
-#include <string.h>
#include <stddef.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
-#include "BLI_timecode.h"
#include "BLI_math.h"
#include "BLI_threads.h"
+#include "BLI_timecode.h"
#include "BLI_utildefines.h"
#include "PIL_time.h"
@@ -39,25 +39,25 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_view3d_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
#include "BKE_blender_undo.h"
#include "BKE_blender_version.h"
#include "BKE_camera.h"
-#include "BKE_context.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_report.h"
-#include "BKE_sequencer.h"
-#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_sequencer.h"
#include "BKE_undo_system.h"
#include "DEG_depsgraph.h"
@@ -68,14 +68,14 @@
#include "ED_object.h"
#include "ED_render.h"
#include "ED_screen.h"
-#include "ED_util.h"
#include "ED_undo.h"
+#include "ED_util.h"
#include "ED_view3d.h"
#include "BIF_glutil.h"
-#include "RE_pipeline.h"
#include "RE_engine.h"
+#include "RE_pipeline.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
@@ -112,7 +112,7 @@ typedef struct RenderJob {
ReportList *reports;
int orig_layer;
int last_layer;
- ScrArea *sa;
+ ScrArea *area;
ColorManagedViewSettings view_settings;
ColorManagedDisplaySettings display_settings;
bool supports_glsl_draw;
@@ -333,9 +333,11 @@ static int screen_render_exec(bContext *C, wmOperator *op)
re = RE_NewSceneRender(scene);
G.is_break = false;
+
+ RE_draw_lock_cb(re, NULL, NULL);
RE_test_break_cb(re, NULL, render_break);
- ima = BKE_image_verify_viewer(mainp, IMA_TYPE_R_RESULT, "Render Result");
+ ima = BKE_image_ensure_viewer(mainp, IMA_TYPE_R_RESULT, "Render Result");
BKE_image_signal(mainp, ima, NULL, IMA_SIGNAL_FREE);
BKE_image_backup_render(scene, ima, true);
@@ -541,24 +543,24 @@ static void render_progress_update(void *rjv, float progress)
static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr, ImageUser *iuser)
{
wmWindowManager *wm;
- ScrArea *first_sa = NULL, *matched_sa = NULL;
+ ScrArea *first_area = NULL, *matched_area = NULL;
/* image window, compo node users */
- for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */
+ for (wm = rj->main->wm.first; wm && matched_area == NULL; wm = wm->id.next) { /* only 1 wm */
wmWindow *win;
- for (win = wm->windows.first; win && matched_sa == NULL; win = win->next) {
+ for (win = wm->windows.first; win && matched_area == NULL; win = win->next) {
const bScreen *screen = WM_window_get_active_screen(win);
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
- // sa->spacedata might be empty when toggling fullscreen mode.
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = area->spacedata.first;
+ // area->spacedata might be empty when toggling fullscreen mode.
if (sima != NULL && sima->image == rj->image) {
- if (first_sa == NULL) {
- first_sa = sa;
+ if (first_area == NULL) {
+ first_area = area;
}
- if (sa == rj->sa) {
- matched_sa = sa;
+ if (area == rj->area) {
+ matched_area = area;
break;
}
}
@@ -567,12 +569,12 @@ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr,
}
}
- if (matched_sa == NULL) {
- matched_sa = first_sa;
+ if (matched_area == NULL) {
+ matched_area = first_area;
}
- if (matched_sa) {
- SpaceImage *sima = matched_sa->spacedata.first;
+ if (matched_area) {
+ SpaceImage *sima = matched_area->spacedata.first;
RenderResult *main_rr = RE_AcquireResultRead(rj->re);
/* TODO(sergey): is there faster way to get the layer index? */
@@ -687,10 +689,10 @@ static void render_image_restore_layer(RenderJob *rj)
for (win = wm->windows.first; win; win = win->next) {
const bScreen *screen = WM_window_get_active_screen(win);
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa == rj->sa) {
- if (sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area == rj->area) {
+ if (area->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = area->spacedata.first;
if (RE_HasSingleLayer(rj->re)) {
/* For single layer renders keep the active layer
@@ -746,7 +748,7 @@ static void render_endjob(void *rjv)
WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
}
- if (rj->sa) {
+ if (rj->area) {
render_image_restore_layer(rj);
}
@@ -842,7 +844,7 @@ static int screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event
/* running render */
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_PASS_THROUGH;
@@ -885,7 +887,7 @@ static void clean_viewport_memory(Main *bmain, Scene *scene)
/* Go over all the visible objects. */
for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
for (base = view_layer->object_bases.first; base; base = base->next) {
@@ -918,7 +920,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL;
struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
const char *name;
- ScrArea *sa;
+ ScrArea *area;
/* Cannot do render if there is not this function. */
if (re_type->render == NULL) {
@@ -943,6 +945,12 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
return OPERATOR_CANCELLED;
}
+ /* Reports are done inside check function, and it will return false if there are other strips to
+ * render. */
+ if ((scene->r.scemode & R_DOSEQ) && BKE_sequencer_check_scene_recursion(scene, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+
/* stop all running jobs, except screen one. currently previews frustrate Render */
WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C));
@@ -968,7 +976,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
// store spare
/* ensure at least 1 area shows result */
- sa = render_view_open(C, event->x, event->y, op->reports);
+ area = render_view_open(C, event->x, event->y, op->reports);
/* job custom data */
rj = MEM_callocN(sizeof(RenderJob), "render job");
@@ -989,14 +997,14 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->reports = op->reports;
rj->orig_layer = 0;
rj->last_layer = 0;
- rj->sa = sa;
+ rj->area = area;
rj->supports_glsl_draw = IMB_colormanagement_support_glsl_draw(&scene->view_settings);
BKE_color_managed_display_settings_copy(&rj->display_settings, &scene->display_settings);
BKE_color_managed_view_settings_copy(&rj->view_settings, &scene->view_settings);
- if (sa) {
- SpaceImage *sima = sa->spacedata.first;
+ if (area) {
+ SpaceImage *sima = area->spacedata.first;
rj->orig_layer = sima->iuser.layer;
}
@@ -1047,7 +1055,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
}
/* get a render result image, and make sure it is empty */
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
+ ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE);
BKE_image_backup_render(rj->scene, ima, true);
rj->image = ima;
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 43670c8fb1a..f2e8209b099 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -22,35 +22,35 @@
*/
#include <math.h>
-#include <string.h>
#include <stddef.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
-#include "DNA_camera_types.h"
#include "BLI_bitmap.h"
+#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-#include "BLI_threads.h"
#include "BLI_task.h"
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+#include "DNA_camera_types.h"
-#include "DNA_anim_types.h"
#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
#include "DNA_curve_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -65,14 +65,15 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_gpencil.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_gpencil.h"
+#include "ED_view3d_offscreen.h"
-#include "RE_pipeline.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "RE_pipeline.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -104,7 +105,7 @@ typedef struct OGLRender {
View3D *v3d;
RegionView3D *rv3d;
- ARegion *ar;
+ ARegion *region;
ScrArea *prevsa;
ARegion *prevar;
@@ -143,14 +144,13 @@ typedef struct OGLRender {
wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/
void **movie_ctx_arr;
- TaskScheduler *task_scheduler;
TaskPool *task_pool;
bool pool_ok;
bool is_animation;
eImageFormatDepth color_depth;
SpinLock reports_lock;
- unsigned int num_scheduled_frames;
+ uint num_scheduled_frames;
ThreadMutex task_mutex;
ThreadCondition task_condition;
@@ -286,7 +286,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = oglrender->scene;
- ARegion *ar = oglrender->ar;
+ ARegion *region = oglrender->region;
View3D *v3d = oglrender->v3d;
RegionView3D *rv3d = oglrender->rv3d;
Object *camera = NULL;
@@ -295,7 +295,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
const short view_context = (v3d != NULL);
bool draw_sky = (scene->r.alphamode == R_ADDSKY);
float *rectf = NULL;
- unsigned char *rect = NULL;
+ uchar *rect = NULL;
const char *viewname = RE_GetActiveRenderView(oglrender->re);
ImBuf *ibuf_result = NULL;
@@ -333,9 +333,8 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
if (gpd) {
int i;
- unsigned char *gp_rect;
- unsigned char *render_rect =
- (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32;
+ uchar *gp_rect;
+ uchar *render_rect = (uchar *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32;
DRW_opengl_context_enable();
GPU_offscreen_bind(oglrender->ofs, true);
@@ -351,7 +350,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
ED_annotation_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
G.f &= ~G_FLAG_RENDER_VIEWPORT;
- gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
+ gp_rect = MEM_mallocN(sizex * sizey * sizeof(uchar) * 4, "offscreen rect");
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect);
for (i = 0; i < sizex * sizey * 4; i += 4) {
@@ -368,17 +367,18 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
char err_out[256] = "unknown";
ImBuf *ibuf_view;
const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL;
- int output_flags = oglrender->color_depth <= R_IMF_CHAN_DEPTH_8 ? IB_rect : IB_rectfloat;
+ eImBufFlags imbuf_flags = oglrender->color_depth <= R_IMF_CHAN_DEPTH_8 ? IB_rect :
+ IB_rectfloat;
if (view_context) {
ibuf_view = ED_view3d_draw_offscreen_imbuf(depsgraph,
scene,
v3d->shading.type,
v3d,
- ar,
+ region,
sizex,
sizey,
- output_flags,
+ imbuf_flags,
alpha_mode,
viewname,
oglrender->ofs,
@@ -397,7 +397,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
scene->camera,
oglrender->sizex,
oglrender->sizey,
- output_flags,
+ imbuf_flags,
V3D_OFSDRAW_SHOW_ANNOTATION,
alpha_mode,
viewname,
@@ -412,7 +412,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
rectf = ibuf_view->rect_float;
}
else {
- rect = (unsigned char *)ibuf_view->rect;
+ rect = (uchar *)ibuf_view->rect;
}
}
else {
@@ -584,20 +584,23 @@ static void gather_frames_to_render_for_grease_pencil(const OGLRender *oglrender
}
}
-static int gather_frames_to_render_for_id(void *user_data_v, ID *id_self, ID **id_p, int cb_flag)
+static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data)
{
- if (id_p == NULL || *id_p == NULL) {
+ ID **id_p = cb_data->id_pointer;
+ if (*id_p == NULL) {
return IDWALK_RET_NOP;
}
ID *id = *id_p;
+ ID *id_self = cb_data->id_self;
+ const int cb_flag = cb_data->cb_flag;
if (cb_flag == IDWALK_CB_LOOPBACK || id == id_self) {
/* IDs may end up referencing themselves one way or the other, and those
* (the id_self ones) have always already been processed. */
return IDWALK_RET_STOP_RECURSION;
}
- OGLRender *oglrender = user_data_v;
+ OGLRender *oglrender = cb_data->user_data;
/* Whitelist of datablocks to follow pointers into. */
const ID_Type id_type = GS(id->name);
@@ -623,6 +626,10 @@ static int gather_frames_to_render_for_id(void *user_data_v, ID *id_self, ID **i
case ID_MC: /* MovieClip */
case ID_MSK: /* Mask */
case ID_LP: /* LightProbe */
+ case ID_HA: /* Hair */
+ case ID_PT: /* PointCloud */
+ case ID_VO: /* Volume */
+ case ID_SIM: /* Simulation */
break;
/* Blacklist: */
@@ -801,9 +808,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
if (is_view_context) {
/* so quad view renders camera */
- ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->ar);
+ ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->region);
- oglrender->rv3d = oglrender->ar->regiondata;
+ oglrender->rv3d = oglrender->region->regiondata;
/* MUST be cleared on exit */
memset(&oglrender->scene->customdata_mask_modal,
@@ -822,7 +829,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->re = RE_NewSceneRender(scene);
/* create image and image user */
- oglrender->ima = BKE_image_verify_viewer(oglrender->bmain, IMA_TYPE_R_RESULT, "Render Result");
+ oglrender->ima = BKE_image_ensure_viewer(oglrender->bmain, IMA_TYPE_R_RESULT, "Render Result");
BKE_image_signal(oglrender->bmain, oglrender->ima, NULL, IMA_SIGNAL_FREE);
BKE_image_backup_render(oglrender->scene, oglrender->ima, true);
@@ -848,21 +855,16 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
gather_frames_to_render(C, oglrender);
}
- TaskScheduler *task_scheduler = BLI_task_scheduler_get();
if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- task_scheduler = BLI_task_scheduler_create(1);
- oglrender->task_scheduler = task_scheduler;
- oglrender->task_pool = BLI_task_pool_create_background(task_scheduler, oglrender);
+ oglrender->task_pool = BLI_task_pool_create_background_serial(oglrender, TASK_PRIORITY_LOW);
}
else {
- oglrender->task_scheduler = NULL;
- oglrender->task_pool = BLI_task_pool_create(task_scheduler, oglrender);
+ oglrender->task_pool = BLI_task_pool_create(oglrender, TASK_PRIORITY_LOW);
}
oglrender->pool_ok = true;
BLI_spin_init(&oglrender->reports_lock);
}
else {
- oglrender->task_scheduler = NULL;
oglrender->task_pool = NULL;
}
oglrender->num_scheduled_frames = 0;
@@ -901,10 +903,6 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
}
BLI_task_pool_work_and_wait(oglrender->task_pool);
BLI_task_pool_free(oglrender->task_pool);
- /* Depending on various things we might or might not use global scheduler. */
- if (oglrender->task_scheduler != NULL) {
- BLI_task_scheduler_free(oglrender->task_scheduler);
- }
BLI_spin_end(&oglrender->reports_lock);
}
BLI_mutex_end(&oglrender->task_mutex);
@@ -1024,9 +1022,9 @@ typedef struct WriteTaskData {
Scene tmp_scene;
} WriteTaskData;
-static void write_result_func(TaskPool *__restrict pool, void *task_data_v, int UNUSED(thread_id))
+static void write_result_func(TaskPool *__restrict pool, void *task_data_v)
{
- OGLRender *oglrender = (OGLRender *)BLI_task_pool_userdata(pool);
+ OGLRender *oglrender = (OGLRender *)BLI_task_pool_user_data(pool);
WriteTaskData *task_data = (WriteTaskData *)task_data_v;
Scene *scene = &task_data->tmp_scene;
RenderResult *rr = task_data->rr;
@@ -1116,7 +1114,7 @@ static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr)
BLI_condition_wait(&oglrender->task_condition, &oglrender->task_mutex);
}
BLI_mutex_unlock(&oglrender->task_mutex);
- BLI_task_pool_push(oglrender->task_pool, write_result_func, task_data, true, TASK_PRIORITY_LOW);
+ BLI_task_pool_push(oglrender->task_pool, write_result_func, task_data, true, NULL);
return true;
}
@@ -1214,7 +1212,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent
bool ret;
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
/* cancel */
oglrender->pool_ok = false; /* Flag pool for cancel. */
screen_opengl_render_end(C, op->customdata);
@@ -1268,7 +1266,7 @@ static int screen_opengl_render_invoke(bContext *C, wmOperator *op, const wmEven
oglrender = op->customdata;
render_view_open(C, event->x, event->y, op->reports);
- /* view may be changed above (R_OUTPUT_WINDOW) */
+ /* View may be changed above #USER_RENDER_DISPLAY_WINDOW. */
oglrender->win = CTX_wm_window(C);
WM_event_add_modal_handler(C, op);
@@ -1379,6 +1377,3 @@ void RENDER_OT_opengl(wmOperatorType *ot)
"Use the current 3D view for rendering, else use scene settings");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-
-/* function for getting an opengl buffer from a View3D, used by sequencer */
-// extern void *sequencer_view3d_cb;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 0ed37bbc5af..0432057bb47 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -23,8 +23,8 @@
/* global includes */
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include <string.h>
#ifndef WIN32
@@ -34,37 +34,37 @@
#endif
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "PIL_time.h"
#include "BLO_readfile.h"
-#include "DNA_world_types.h"
+#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_collection_types.h"
+#include "DNA_light_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_light_types.h"
-#include "DNA_space_types.h"
#include "DNA_scene_types.h"
-#include "DNA_brush_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_world_types.h"
#include "BKE_appdir.h"
#include "BKE_brush.h"
-#include "BKE_context.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
-#include "BKE_icons.h"
-#include "BKE_library.h"
-#include "BKE_light.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
+#include "BKE_light.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
@@ -73,8 +73,8 @@
#include "BKE_world.h"
#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -82,11 +82,11 @@
#include "BIF_glutil.h"
-#include "GPU_shader.h"
#include "GPU_glew.h"
+#include "GPU_shader.h"
-#include "RE_pipeline.h"
#include "RE_engine.h"
+#include "RE_pipeline.h"
#include "RE_shader_ext.h"
#include "WM_api.h"
@@ -167,7 +167,7 @@ typedef struct ShaderPreview {
float color[4];
int sizex, sizey;
- unsigned int *pr_rect;
+ uint *pr_rect;
int pr_method;
bool own_id_copy;
@@ -178,7 +178,7 @@ typedef struct ShaderPreview {
typedef struct IconPreviewSize {
struct IconPreviewSize *next, *prev;
int sizex, sizey;
- unsigned int *rect;
+ uint *rect;
} IconPreviewSize;
typedef struct IconPreview {
@@ -304,7 +304,7 @@ static void set_preview_visibility(Scene *scene,
}
/* Hide floor for icon renders. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (STREQ(base->object->id.name + 2, "Floor")) {
if (pr_method == PR_ICON_RENDER) {
base->object->restrictflag |= OB_RESTRICT_RENDER;
@@ -371,6 +371,10 @@ static Scene *preview_prepare_scene(
if (sce) {
ViewLayer *view_layer = sce->view_layers.first;
+ /* Only enable the combined renderpass */
+ view_layer->passflag = SCE_PASS_COMBINED;
+ view_layer->eevee.render_passes = 0;
+
/* this flag tells render to not execute depsgraph or ipos etc */
sce->r.scemode |= R_BUTS_PREVIEW;
/* set world always back, is used now */
@@ -459,14 +463,15 @@ static Scene *preview_prepare_scene(
sce->display.render_aa = SCE_DISPLAY_AA_OFF;
}
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->object->id.name[2] == 'p') {
/* copy over object color, in case material uses it */
copy_v4_v4(base->object->color, sp->color);
if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
- /* don't use assign_material, it changed mat->id.us, which shows in the UI */
- Material ***matar = give_matarar(base->object);
+ /* don't use BKE_object_material_assign, it changed mat->id.us, which shows in the UI
+ */
+ Material ***matar = BKE_object_material_array_p(base->object);
int actcol = max_ii(base->object->actcol - 1, 0);
if (matar && actcol < base->object->totcol) {
@@ -517,7 +522,7 @@ static Scene *preview_prepare_scene(
sce->world->horb = 0.0f;
}
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->object->id.name[2] == 'p') {
if (base->object->type == OB_LAMP) {
base->object->data = la;
@@ -561,7 +566,7 @@ static Scene *preview_prepare_scene(
/* new UI convention: draw is in pixel space already. */
/* uses UI_BTYPE_ROUNDBOX button in block to get the rect */
-static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect)
+static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect, rcti *newrect)
{
Render *re;
RenderView *rv;
@@ -573,10 +578,10 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
bool ok = false;
if (!split || first) {
- sprintf(name, "Preview %p", (void *)sa);
+ sprintf(name, "Preview %p", (void *)area);
}
else {
- sprintf(name, "SecondPreview %p", (void *)sa);
+ sprintf(name, "SecondPreview %p", (void *)area);
}
if (split) {
@@ -610,20 +615,20 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
if (rv && rv->rectf) {
- if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) {
+ if (abs(rres.rectx - newx) < 2 && abs(rres.recty - newy) < 2) {
newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
if (rres.rectx && rres.recty) {
- unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int),
- "ed_preview_draw_rect");
+ uchar *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int),
+ "ed_preview_draw_rect");
float fx = rect->xmin + offx;
float fy = rect->ymin;
/* material preview only needs monoscopy (view 0) */
if (re) {
- RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0);
+ RE_AcquiredResultGet32(re, &rres, (uint *)rect_byte, 0);
}
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
@@ -656,12 +661,12 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
{
if (idp) {
wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
ID *id = (ID *)idp;
ID *parent = (ID *)parentp;
MTex *slot = (MTex *)slotp;
SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ShaderPreview *sp = WM_jobs_customdata(wm, sa);
+ ShaderPreview *sp = WM_jobs_customdata(wm, area);
rcti newrect;
int ok;
int newx = BLI_rcti_size_x(rect);
@@ -673,11 +678,11 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
newrect.ymax = rect->ymin;
if (parent) {
- ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect);
- ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect);
+ ok = ed_preview_draw_rect(area, 1, 1, rect, &newrect);
+ ok &= ed_preview_draw_rect(area, 1, 0, rect, &newrect);
}
else {
- ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
+ ok = ed_preview_draw_rect(area, 0, 0, rect, &newrect);
}
if (ok) {
@@ -688,12 +693,12 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
* if no render result was found and no preview render job is running,
* or if the job is running and the size of preview changed */
if ((sbuts != NULL && sbuts->preview) ||
- (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)) ||
- (sp && (ABS(sp->sizex - newx) >= 2 || ABS(sp->sizey - newy) > 2))) {
+ (!ok && !WM_jobs_test(wm, area, WM_JOB_TYPE_RENDER_PREVIEW)) ||
+ (sp && (abs(sp->sizex - newx) >= 2 || abs(sp->sizey - newy) > 2))) {
if (sbuts != NULL) {
sbuts->preview = 0;
}
- ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER);
+ ED_preview_shader_job(C, area, id, parent, slot, newx, newy, PR_BUTS_RENDER);
}
}
}
@@ -953,23 +958,7 @@ static void preview_id_copy_free(ID *id)
IDP_FreePropertyContent_ex(properties, false);
MEM_freeN(properties);
}
- switch (GS(id->name)) {
- case ID_MA:
- BKE_material_free((Material *)id);
- break;
- case ID_TE:
- BKE_texture_free((Tex *)id);
- break;
- case ID_LA:
- BKE_light_free((Light *)id);
- break;
- case ID_WO:
- BKE_world_free((World *)id);
- break;
- default:
- BLI_assert(!"ID type preview not supported.");
- break;
- }
+ BKE_libblock_free_datablock(id, 0);
MEM_freeN(id);
}
@@ -1025,10 +1014,10 @@ static void shader_preview_free(void *customdata)
/* ************************* icon preview ********************** */
-static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect)
+static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect)
{
struct ImBuf *ima;
- unsigned int *drect, *srect;
+ uint *drect, *srect;
float scaledx, scaledy;
short ex, ey, dx, dy;
@@ -1155,7 +1144,7 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
br->icon_imbuf = get_brush_icon(br);
- memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int));
+ memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(uint));
if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) {
return;
@@ -1204,7 +1193,7 @@ static void common_preview_startjob(void *customdata,
/* exported functions */
-static void icon_preview_add_size(IconPreview *ip, unsigned int *rect, int sizex, int sizey)
+static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey)
{
IconPreviewSize *cur_size = ip->sizes.first, *new_size;
@@ -1335,8 +1324,7 @@ static void icon_preview_free(void *customdata)
MEM_freeN(ip);
}
-void ED_preview_icon_render(
- Main *bmain, Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey)
+void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, uint *rect, int sizex, int sizey)
{
IconPreview ip = {NULL};
short stop = false, update = false;
@@ -1359,13 +1347,8 @@ 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,
- const bool delay)
+void ED_preview_icon_job(
+ const bContext *C, void *owner, ID *id, uint *rect, int sizex, int sizey, const bool delay)
{
wmJob *wm_job;
IconPreview *ip, *old_ip;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 7970d491877..49ab2c485b1 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -36,12 +36,13 @@
#include "DNA_space_types.h"
#include "DNA_world_types.h"
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
+#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_brush.h"
#include "BKE_context.h"
@@ -51,7 +52,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -76,10 +77,10 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_object.h"
#include "ED_curve.h"
#include "ED_mesh.h"
#include "ED_node.h"
+#include "ED_object.h"
#include "ED_render.h"
#include "ED_scene.h"
#include "ED_screen.h"
@@ -100,15 +101,15 @@
*/
static Object **object_array_for_shading(bContext *C, uint *r_objects_len)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceProperties *sbuts = NULL;
View3D *v3d = NULL;
- if (sa != NULL) {
- if (sa->spacetype == SPACE_PROPERTIES) {
- sbuts = sa->spacedata.first;
+ if (area != NULL) {
+ if (area->spacetype == SPACE_PROPERTIES) {
+ sbuts = area->spacedata.first;
}
- else if (sa->spacetype == SPACE_VIEW3D) {
- v3d = sa->spacedata.first;
+ else if (area->spacetype == SPACE_VIEW3D) {
+ v3d = area->spacedata.first;
}
}
@@ -217,13 +218,38 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
View3D *v3d = CTX_wm_view3d(C);
bool changed_multi = false;
+ Object *obact = CTX_data_active_object(C);
+ const Material *mat_active = obact ? BKE_object_material_get(obact, obact->actcol) : NULL;
+
uint objects_len = 0;
Object **objects = object_array_for_shading(C, &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *ob = objects[ob_index];
- if (ob->actcol <= 0) {
+ short mat_nr_active = -1;
+
+ if (ob->totcol == 0) {
continue;
}
+ if (obact && (mat_active == BKE_object_material_get(ob, obact->actcol))) {
+ /* Avoid searching since there may be multiple slots with the same material.
+ * For the active object or duplicates: match the material slot index first. */
+ mat_nr_active = obact->actcol - 1;
+ }
+ else {
+ /* Find the first matching material.
+ * Note: there may be multiple but that's not a common use case. */
+ for (short i = 0; i < ob->totcol; i++) {
+ const Material *mat = BKE_object_material_get(ob, i + 1);
+ if (mat_active == mat) {
+ mat_nr_active = i;
+ break;
+ }
+ }
+ if (mat_nr_active == -1) {
+ continue;
+ }
+ }
+
bool changed = false;
if (ob->type == OB_MESH) {
BMEditMesh *em = BKE_editmesh_from_object(ob);
@@ -234,7 +260,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
changed = true;
- efa->mat_nr = ob->actcol - 1;
+ efa->mat_nr = mat_nr_active;
}
}
}
@@ -247,7 +273,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
for (nu = nurbs->first; nu; nu = nu->next) {
if (ED_curve_nurb_select_check(v3d, nu)) {
changed = true;
- nu->mat_nr = ob->actcol - 1;
+ nu->mat_nr = mat_nr_active;
}
}
}
@@ -259,7 +285,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
if (ef && BKE_vfont_select_get(ob, &selstart, &selend)) {
for (i = selstart; i <= selend; i++) {
changed = true;
- ef->textbufinfo[i].mat_nr = ob->actcol;
+ ef->textbufinfo[i].mat_nr = mat_nr_active + 1;
}
}
}
@@ -294,7 +320,7 @@ static int material_slot_de_select(bContext *C, bool select)
{
bool changed_multi = false;
Object *obact = CTX_data_active_object(C);
- const Material *mat_active = obact ? give_current_material(obact, obact->actcol) : NULL;
+ const Material *mat_active = obact ? BKE_object_material_get(obact, obact->actcol) : NULL;
uint objects_len = 0;
Object **objects = object_array_for_shading(C, &objects_len);
@@ -305,7 +331,7 @@ static int material_slot_de_select(bContext *C, bool select)
if (ob->totcol == 0) {
continue;
}
- if (obact && (mat_active == give_current_material(ob, obact->actcol))) {
+ if (obact && (mat_active == BKE_object_material_get(ob, obact->actcol))) {
/* Avoid searching since there may be multiple slots with the same material.
* For the active object or duplicates: match the material slot index first. */
mat_nr_active = obact->actcol - 1;
@@ -314,7 +340,7 @@ static int material_slot_de_select(bContext *C, bool select)
/* Find the first matching material.
* Note: there may be multiple but that's not a common use case. */
for (short i = 0; i < ob->totcol; i++) {
- const Material *mat = give_current_material(ob, i + 1);
+ const Material *mat = BKE_object_material_get(ob, i + 1);
if (mat_active == mat) {
mat_nr_active = i;
break;
@@ -441,14 +467,14 @@ static int material_slot_copy_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_context(C);
Material ***matar;
- if (!ob || !(matar = give_matarar(ob))) {
+ if (!ob || !(matar = BKE_object_material_array_p(ob))) {
return OPERATOR_CANCELLED;
}
CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
- if (ob != ob_iter && give_matarar(ob_iter)) {
+ if (ob != ob_iter && BKE_object_material_array_p(ob_iter)) {
if (ob->data != ob_iter->data) {
- assign_matarar(bmain, ob_iter, matar, ob->totcol);
+ BKE_object_material_array_assign(bmain, ob_iter, matar, ob->totcol);
}
if (ob_iter->totcol == ob->totcol) {
@@ -481,7 +507,7 @@ static int material_slot_move_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
- unsigned int *slot_remap;
+ uint *slot_remap;
int index_pair[2];
int dir = RNA_enum_get(op->ptr, "direction");
@@ -506,14 +532,14 @@ static int material_slot_move_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__);
+ slot_remap = MEM_mallocN(sizeof(uint) * ob->totcol, __func__);
range_vn_u(slot_remap, ob->totcol, 0);
slot_remap[index_pair[0]] = index_pair[1];
slot_remap[index_pair[1]] = index_pair[0];
- BKE_material_remap_object(ob, slot_remap);
+ BKE_object_material_remap(ob, slot_remap);
MEM_freeN(slot_remap);
@@ -644,7 +670,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_material_add(bmain, name);
}
else {
- ma = BKE_material_add_gpencil(bmain, name);
+ ma = BKE_gpencil_material_add(bmain, name);
}
ED_node_shader_default(C, &ma->id);
ma->use_nodes = true;
@@ -654,7 +680,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
if (ob != NULL) {
/* Add slot follows user-preferences for creating new slots,
* RNA pointer assignment doesn't, see: T60014. */
- if (give_current_material_p(ob, ob->actcol) == NULL) {
+ if (BKE_object_material_get_p(ob, ob->actcol) == NULL) {
BKE_object_material_slot_add(bmain, ob);
}
}
@@ -789,14 +815,16 @@ void WORLD_OT_new(wmOperatorType *ot)
/********************** render layer operators *********************/
-static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
+static int view_layer_add_exec(bContext *C, wmOperator *op)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = BKE_view_layer_add(scene, NULL);
+ ViewLayer *view_layer_current = WM_window_get_active_view_layer(win);
+ ViewLayer *view_layer_new = BKE_view_layer_add(
+ scene, view_layer_current->name, view_layer_current, RNA_enum_get(op->ptr, "type"));
if (win) {
- WM_window_set_active_view_layer(win, view_layer);
+ WM_window_set_active_view_layer(win, view_layer_new);
}
DEG_id_tag_update(&scene->id, 0);
@@ -808,6 +836,17 @@ static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
void SCENE_OT_view_layer_add(wmOperatorType *ot)
{
+ static EnumPropertyItem type_items[] = {
+ {VIEWLAYER_ADD_NEW, "NEW", 0, "New", "Add a new view layer"},
+ {VIEWLAYER_ADD_COPY, "COPY", 0, "Copy Settings", "Copy settings of current view layer"},
+ {VIEWLAYER_ADD_EMPTY,
+ "EMPTY",
+ 0,
+ "Blank",
+ "Add a new view layer with all collections disabled"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
/* identifiers */
ot->name = "Add View Layer";
ot->idname = "SCENE_OT_view_layer_add";
@@ -815,9 +854,13 @@ void SCENE_OT_view_layer_add(wmOperatorType *ot)
/* api callbacks */
ot->exec = view_layer_add_exec;
+ ot->invoke = WM_menu_invoke;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
static bool view_layer_remove_poll(bContext *C)
@@ -865,14 +908,14 @@ enum {
static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op)
{
- if (scene->eevee.light_cache != NULL) {
+ if (scene->eevee.light_cache_data != NULL) {
int subset = RNA_enum_get(op->ptr, "subset");
switch (subset) {
case LIGHTCACHE_SUBSET_ALL:
- scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_UPDATE_CUBE;
+ scene->eevee.light_cache_data->flag |= LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_UPDATE_CUBE;
break;
case LIGHTCACHE_SUBSET_CUBE:
- scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
+ scene->eevee.light_cache_data->flag |= LIGHTCACHE_UPDATE_CUBE;
break;
case LIGHTCACHE_SUBSET_DIRTY:
/* Leave tag untouched. */
@@ -893,7 +936,7 @@ static int light_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *ev
/* running render */
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_PASS_THROUGH;
@@ -1021,7 +1064,7 @@ static bool light_cache_free_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- return scene->eevee.light_cache;
+ return scene->eevee.light_cache_data;
}
static int light_cache_free_exec(bContext *C, wmOperator *UNUSED(op))
@@ -1032,12 +1075,12 @@ static int light_cache_free_exec(bContext *C, wmOperator *UNUSED(op))
wmWindowManager *wm = CTX_wm_manager(C);
WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
- if (!scene->eevee.light_cache) {
+ if (!scene->eevee.light_cache_data) {
return OPERATOR_CANCELLED;
}
- EEVEE_lightcache_free(scene->eevee.light_cache);
- scene->eevee.light_cache = NULL;
+ EEVEE_lightcache_free(scene->eevee.light_cache_data);
+ scene->eevee.light_cache_data = NULL;
EEVEE_lightcache_info_update(&scene->eevee);
@@ -1915,7 +1958,7 @@ static int copy_material_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- copy_matcopybuf(CTX_data_main(C), ma);
+ BKE_material_copybuf_copy(CTX_data_main(C), ma);
return OPERATOR_FINISHED;
}
@@ -1943,7 +1986,7 @@ static int paste_material_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- paste_matcopybuf(CTX_data_main(C), ma);
+ BKE_material_copybuf_paste(CTX_data_main(C), ma);
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index b5b56017134..b4e5eb2a047 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -32,9 +32,9 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
#include "DNA_workspace_types.h"
#include "DNA_world_types.h"
-#include "DNA_windowmanager_types.h"
#include "DRW_engine.h"
@@ -113,31 +113,31 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int update
wm = bmain->wm.first;
for (win = wm->windows.first; win; win = win->next) {
- bScreen *sc = WM_window_get_active_screen(win);
- ScrArea *sa;
- ARegion *ar;
+ bScreen *screen = WM_window_get_active_screen(win);
+ ScrArea *area;
+ ARegion *region;
CTX_wm_window_set(C, win);
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype != SPACE_VIEW3D) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ if (area->spacetype != SPACE_VIEW3D) {
continue;
}
- View3D *v3d = sa->spacedata.first;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype != RGN_TYPE_WINDOW) {
+ View3D *v3d = area->spacedata.first;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype != RGN_TYPE_WINDOW) {
continue;
}
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
RenderEngine *engine = rv3d->render_engine;
/* call update if the scene changed, or if the render engine
* tagged itself for update (e.g. because it was busy at the
* time of the last update) */
if (engine && (updated || (engine->flag & RE_ENGINE_DO_UPDATE))) {
- CTX_wm_screen_set(C, sc);
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
+ CTX_wm_screen_set(C, screen);
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
engine->flag &= ~RE_ENGINE_DO_UPDATE;
/* NOTE: Important to pass non-updated depsgraph, This is because this function is called
@@ -153,8 +153,8 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int update
.depsgraph = update_ctx->depsgraph,
.scene = scene,
.view_layer = view_layer,
- .ar = ar,
- .v3d = (View3D *)sa->spacedata.first,
+ .region = region,
+ .v3d = (View3D *)area->spacedata.first,
.engine_type = engine_type,
}));
}
@@ -168,30 +168,30 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int update
recursive_check = false;
}
-void ED_render_engine_area_exit(Main *bmain, ScrArea *sa)
+void ED_render_engine_area_exit(Main *bmain, ScrArea *area)
{
/* clear all render engines in this area */
- ARegion *ar;
+ ARegion *region;
wmWindowManager *wm = bmain->wm.first;
- if (sa->spacetype != SPACE_VIEW3D) {
+ if (area->spacetype != SPACE_VIEW3D) {
return;
}
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype != RGN_TYPE_WINDOW || !(ar->regiondata)) {
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype != RGN_TYPE_WINDOW || !(region->regiondata)) {
continue;
}
- ED_view3d_stop_render_preview(wm, ar);
+ ED_view3d_stop_render_preview(wm, region);
}
}
void ED_render_engine_changed(Main *bmain)
{
/* on changing the render engine type, clear all running render engines */
- for (bScreen *sc = bmain->screens.first; sc; sc = sc->id.next) {
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- ED_render_engine_area_exit(bmain, sa);
+ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ ED_render_engine_area_exit(bmain, area);
}
}
RE_FreePersistentData();
@@ -212,10 +212,10 @@ void ED_render_engine_changed(Main *bmain)
}
}
-void ED_render_view_layer_changed(Main *bmain, bScreen *sc)
+void ED_render_view_layer_changed(Main *bmain, bScreen *screen)
{
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- ED_render_engine_area_exit(bmain, sa);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ ED_render_engine_area_exit(bmain, area);
}
}
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index 9849be2a57b..a9c855b14b0 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -21,8 +21,8 @@
* \ingroup edrend
*/
-#include <string.h>
#include <stddef.h>
+#include <string.h>
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
@@ -31,11 +31,11 @@
#include "DNA_userdef_types.h"
#include "BKE_context.h"
-#include "BKE_image.h"
#include "BKE_global.h"
+#include "BKE_image.h"
#include "BKE_main.h"
-#include "BKE_screen.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "BLT_translation.h"
@@ -56,23 +56,23 @@
/* would use BKE_screen_find_big_area(...) but this is too specific */
static ScrArea *biggest_non_image_area(bContext *C)
{
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa, *big = NULL;
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area, *big = NULL;
int size, maxsize = 0, bwmaxsize = 0;
short foundwin = 0;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->winx > 30 && sa->winy > 30) {
- size = sa->winx * sa->winy;
- if (!sa->full && sa->spacetype == SPACE_PROPERTIES) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ if (area->winx > 30 && area->winy > 30) {
+ size = area->winx * area->winy;
+ if (!area->full && area->spacetype == SPACE_PROPERTIES) {
if (foundwin == 0 && size > bwmaxsize) {
bwmaxsize = size;
- big = sa;
+ big = area;
}
}
- else if (sa->spacetype != SPACE_IMAGE && size > maxsize) {
+ else if (area->spacetype != SPACE_IMAGE && size > maxsize) {
maxsize = size;
- big = sa;
+ big = area;
foundwin = 1;
}
}
@@ -84,7 +84,7 @@ static ScrArea *biggest_non_image_area(bContext *C)
static ScrArea *find_area_showing_r_result(bContext *C, Scene *scene, wmWindow **win)
{
wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = NULL;
+ ScrArea *area = NULL;
SpaceImage *sima;
/* find an imagewindow showing render result */
@@ -92,40 +92,40 @@ static ScrArea *find_area_showing_r_result(bContext *C, Scene *scene, wmWindow *
if (WM_window_get_active_scene(*win) == scene) {
const bScreen *screen = WM_window_get_active_screen(*win);
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_IMAGE) {
- sima = sa->spacedata.first;
+ for (area = screen->areabase.first; area; area = area->next) {
+ if (area->spacetype == SPACE_IMAGE) {
+ sima = area->spacedata.first;
if (sima->image && sima->image->type == IMA_TYPE_R_RESULT) {
break;
}
}
}
- if (sa) {
+ if (area) {
break;
}
}
}
- return sa;
+ return area;
}
static ScrArea *find_area_image_empty(bContext *C)
{
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa;
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area;
SpaceImage *sima;
/* find an imagewindow showing render result */
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_IMAGE) {
- sima = sa->spacedata.first;
+ for (area = screen->areabase.first; area; area = area->next) {
+ if (area->spacetype == SPACE_IMAGE) {
+ sima = area->spacedata.first;
if ((sima->mode == SI_MODE_VIEW) && !sima->image) {
break;
}
}
}
- return sa;
+ return area;
}
/********************** open image editor for render *************************/
@@ -136,7 +136,7 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
wmWindow *win = NULL;
- ScrArea *sa = NULL;
+ ScrArea *area = NULL;
SpaceImage *sima;
bool area_was_image = false;
@@ -163,34 +163,34 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
return NULL;
}
- sa = CTX_wm_area(C);
- if (BLI_listbase_is_single(&sa->spacedata) == false) {
- sima = sa->spacedata.first;
+ area = CTX_wm_area(C);
+ if (BLI_listbase_is_single(&area->spacedata) == false) {
+ sima = area->spacedata.first;
sima->flag |= SI_PREVSPACE;
}
}
else if (U.render_display_type == USER_RENDER_DISPLAY_SCREEN) {
- sa = CTX_wm_area(C);
+ area = CTX_wm_area(C);
/* if the active screen is already in fullscreen mode, skip this and
* unset the area, so that the fullscreen area is just changed later */
- if (sa && sa->full) {
- sa = NULL;
+ if (area && area->full) {
+ area = NULL;
}
else {
- if (sa && sa->spacetype == SPACE_IMAGE) {
+ if (area && area->spacetype == SPACE_IMAGE) {
area_was_image = true;
}
/* this function returns with changed context */
- sa = ED_screen_full_newspace(C, sa, SPACE_IMAGE);
+ area = ED_screen_full_newspace(C, area, SPACE_IMAGE);
}
}
- if (!sa) {
- sa = find_area_showing_r_result(C, scene, &win);
- if (sa == NULL) {
- sa = find_area_image_empty(C);
+ if (!area) {
+ area = find_area_showing_r_result(C, scene, &win);
+ if (area == NULL) {
+ area = find_area_image_empty(C);
}
/* if area found in other window, we make that one show in front */
@@ -198,27 +198,27 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
wm_window_raise(win);
}
- if (sa == NULL) {
+ if (area == NULL) {
/* find largest open non-image area */
- sa = biggest_non_image_area(C);
- if (sa) {
- ED_area_newspace(C, sa, SPACE_IMAGE, true);
- sima = sa->spacedata.first;
+ area = biggest_non_image_area(C);
+ if (area) {
+ ED_area_newspace(C, area, SPACE_IMAGE, true);
+ sima = area->spacedata.first;
/* makes ESC go back to prev space */
sima->flag |= SI_PREVSPACE;
/* we already had a fullscreen here -> mark new space as a stacked fullscreen */
- if (sa->full) {
- sa->flag |= AREA_FLAG_STACKED_FULLSCREEN;
+ if (area->full) {
+ area->flag |= AREA_FLAG_STACKED_FULLSCREEN;
}
}
else {
/* use any area of decent size */
- sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TYPE_ANY, 0);
- if (sa->spacetype != SPACE_IMAGE) {
- // XXX newspace(sa, SPACE_IMAGE);
- sima = sa->spacedata.first;
+ area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TYPE_ANY, 0);
+ if (area->spacetype != SPACE_IMAGE) {
+ // XXX newspace(area, SPACE_IMAGE);
+ sima = area->spacedata.first;
/* makes ESC go back to prev space */
sima->flag |= SI_PREVSPACE;
@@ -226,15 +226,15 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
}
}
}
- sima = sa->spacedata.first;
+ sima = area->spacedata.first;
sima->link_flag |= SPACE_FLAG_TYPE_TEMPORARY;
/* get the correct image, and scale it */
- sima->image = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
+ sima->image = BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
/* If we're rendering to full screen, set appropriate hints on image editor
* so it can restore properly on pressing escape. */
- if (sa->full) {
+ if (area->full) {
sima->flag |= SI_FULLWINDOW;
/* Tell the image editor to revert to previous space in space list on close
@@ -253,7 +253,7 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
old_sl->link_flag |= SPACE_FLAG_TYPE_WAS_ACTIVE;
}
- return sa;
+ return area;
}
/*************************** cancel render viewer **********************/
@@ -261,11 +261,11 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op))
{
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
- SpaceImage *sima = sa->spacedata.first;
+ ScrArea *area = CTX_wm_area(C);
+ SpaceImage *sima = area->spacedata.first;
/* ensure image editor fullscreen and area fullscreen states are in sync */
- if ((sima->flag & SI_FULLWINDOW) && !sa->full) {
+ if ((sima->flag & SI_FULLWINDOW) && !area->full) {
sima->flag &= ~SI_FULLWINDOW;
}
@@ -275,17 +275,17 @@ static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op))
if (sima->flag & SI_FULLWINDOW) {
sima->flag &= ~SI_FULLWINDOW;
- ED_screen_full_prevspace(C, sa);
+ ED_screen_full_prevspace(C, area);
}
else {
- ED_area_prevspace(C, sa);
+ ED_area_prevspace(C, area);
}
return OPERATOR_FINISHED;
}
else if (sima->flag & SI_FULLWINDOW) {
sima->flag &= ~SI_FULLWINDOW;
- ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
+ ED_screen_state_toggle(C, win, area, SCREENMAXIMIZED);
return OPERATOR_FINISHED;
}
else if (WM_window_is_temp_screen(win)) {
@@ -320,14 +320,14 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
else {
wmWindow *win, *winshow;
- ScrArea *sa = find_area_showing_r_result(C, CTX_data_scene(C), &winshow);
+ ScrArea *area = find_area_showing_r_result(C, CTX_data_scene(C), &winshow);
/* is there another window on current scene showing result? */
for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) {
- const bScreen *sc = WM_window_get_active_screen(win);
+ const bScreen *screen = WM_window_get_active_screen(win);
if ((WM_window_is_temp_screen(win) &&
- ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
+ ((ScrArea *)screen->areabase.first)->spacetype == SPACE_IMAGE) ||
(win == winshow && winshow != wincur)) {
wm_window_raise(win);
return OPERATOR_FINISHED;
@@ -335,20 +335,20 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
/* determine if render already shows */
- if (sa) {
+ if (area) {
/* but don't close it when rendering */
if (G.is_rendering == false) {
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
if (sima->flag & SI_PREVSPACE) {
sima->flag &= ~SI_PREVSPACE;
if (sima->flag & SI_FULLWINDOW) {
sima->flag &= ~SI_FULLWINDOW;
- ED_screen_full_prevspace(C, sa);
+ ED_screen_full_prevspace(C, area);
}
else {
- ED_area_prevspace(C, sa);
+ ED_area_prevspace(C, area);
}
}
}
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
index 22c91686bbf..d78b1532a39 100644
--- a/source/blender/editors/scene/scene_edit.c
+++ b/source/blender/editors/scene/scene_edit.c
@@ -28,7 +28,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
@@ -99,7 +99,7 @@ bool ED_scene_delete(bContext *C, Main *bmain, Scene *scene)
return false;
}
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
if (win->parent != NULL) { /* We only care about main windows here... */
continue;
}
@@ -175,13 +175,15 @@ bool ED_scene_view_layer_delete(Main *bmain, Scene *scene, ViewLayer *layer, Rep
/* Remove from windows. */
wmWindowManager *wm = bmain->wm.first;
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
if (win->scene == scene && STREQ(win->view_layer_name, layer->name)) {
ViewLayer *first_layer = BKE_view_layer_default_view(scene);
STRNCPY(win->view_layer_name, first_layer->name);
}
}
+ BKE_scene_free_view_layer_depsgraph(scene, layer);
+
BKE_view_layer_free(layer);
DEG_id_tag_update(&scene->id, 0);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 7db634660af..48b54ddcea3 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -21,18 +21,18 @@
* \ingroup edscr
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
#include "BLI_blenlib.h"
+#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "BLI_linklist_stack.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -44,20 +44,20 @@
#include "RNA_types.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
#include "ED_time_scrub_ui.h"
+#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
-#include "GPU_framebuffer.h"
#include "BLF_api.h"
@@ -82,15 +82,15 @@ enum RegionEmbossSide {
/* general area and region code */
-static void region_draw_emboss(const ARegion *ar, const rcti *scirct, int sides)
+static void region_draw_emboss(const ARegion *region, const rcti *scirct, int sides)
{
rcti rect;
/* translate scissor rect to region space */
- rect.xmin = scirct->xmin - ar->winrct.xmin;
- rect.ymin = scirct->ymin - ar->winrct.ymin;
- rect.xmax = scirct->xmax - ar->winrct.xmin;
- rect.ymax = scirct->ymax - ar->winrct.ymin;
+ rect.xmin = scirct->xmin - region->winrct.xmin;
+ rect.ymin = scirct->ymin - region->winrct.ymin;
+ rect.xmax = scirct->xmax - region->winrct.xmin;
+ rect.ymax = scirct->ymax - region->winrct.ymin;
/* set transp line */
GPU_blend(true);
@@ -138,50 +138,50 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct, int sides)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
-void ED_region_pixelspace(ARegion *ar)
+void ED_region_pixelspace(ARegion *region)
{
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
GPU_matrix_identity_set();
}
/* only exported for WM */
void ED_region_do_listen(
- wmWindow *win, ScrArea *sa, ARegion *ar, wmNotifier *note, const Scene *scene)
+ wmWindow *win, ScrArea *area, ARegion *region, wmNotifier *note, const Scene *scene)
{
/* generic notes first */
switch (note->category) {
case NC_WM:
if (note->data == ND_FILEREAD) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_WINDOW:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
- if (ar->type && ar->type->listener) {
- ar->type->listener(win, sa, ar, note, scene);
+ if (region->type && region->type->listener) {
+ region->type->listener(win, area, region, note, scene);
}
}
/* only exported for WM */
-void ED_area_do_listen(wmWindow *win, ScrArea *sa, wmNotifier *note, Scene *scene)
+void ED_area_do_listen(wmWindow *win, ScrArea *area, wmNotifier *note, Scene *scene)
{
/* no generic notes? */
- if (sa->type && sa->type->listener) {
- sa->type->listener(win, sa, note, scene);
+ if (area->type && area->type->listener) {
+ area->type->listener(win, area, note, scene);
}
}
/* only exported for WM */
-void ED_area_do_refresh(bContext *C, ScrArea *sa)
+void ED_area_do_refresh(bContext *C, ScrArea *area)
{
/* no generic notes? */
- if (sa->type && sa->type->refresh) {
- sa->type->refresh(C, sa);
+ if (area->type && area->type->refresh) {
+ area->type->refresh(C, area);
}
- sa->do_refresh = false;
+ area->do_refresh = false;
}
/**
@@ -249,7 +249,9 @@ static void draw_azone_arrow(float x1, float y1, float x2, float y2, AZEdge edge
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_blend(true);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ /* NOTE(fclem): There is something strange going on with Mesa and GPU_SHADER_2D_UNIFORM_COLOR
+ * that causes a crash on some GPUs (see T76113). Using 3D variant avoid the issue. */
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4f(0.8f, 0.8f, 0.8f, 0.4f);
immBegin(GPU_PRIM_TRI_FAN, 6);
@@ -267,7 +269,7 @@ static void draw_azone_arrow(float x1, float y1, float x2, float y2, AZEdge edge
GPU_blend(false);
}
-static void region_draw_azone_tab_arrow(AZone *az)
+static void region_draw_azone_tab_arrow(ScrArea *area, ARegion *region, AZone *az)
{
GPU_blend(true);
@@ -287,23 +289,25 @@ static void region_draw_azone_tab_arrow(AZone *az)
break;
}
- float color[4] = {0.05f, 0.05f, 0.05f, 0.4f};
+ /* Workaround for different color spaces between normal areas and the ones using GPUViewports. */
+ float alpha = WM_region_use_viewport(area, region) ? 0.6f : 0.4f;
+ float color[4] = {0.05f, 0.05f, 0.05f, alpha};
UI_draw_roundbox_aa(
true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, color);
draw_azone_arrow((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, az->edge);
}
-static void area_azone_tag_update(ScrArea *sa)
+static void area_azone_tag_update(ScrArea *area)
{
- sa->flag |= AREA_FLAG_ACTIONZONES_UPDATE;
+ area->flag |= AREA_FLAG_ACTIONZONES_UPDATE;
}
-static void region_draw_azones(ScrArea *sa, ARegion *ar)
+static void region_draw_azones(ScrArea *area, ARegion *region)
{
AZone *az;
- if (!sa) {
+ if (!area) {
return;
}
@@ -313,22 +317,22 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_matrix_push();
- GPU_matrix_translate_2f(-ar->winrct.xmin, -ar->winrct.ymin);
+ GPU_matrix_translate_2f(-region->winrct.xmin, -region->winrct.ymin);
- for (az = sa->actionzones.first; az; az = az->next) {
+ for (az = area->actionzones.first; az; az = az->next) {
/* test if action zone is over this region */
rcti azrct;
BLI_rcti_init(&azrct, az->x1, az->x2, az->y1, az->y2);
- if (BLI_rcti_isect(&ar->drawrct, &azrct, NULL)) {
+ if (BLI_rcti_isect(&region->drawrct, &azrct, NULL)) {
if (az->type == AZONE_AREA) {
area_draw_azone(az->x1, az->y1, az->x2, az->y2);
}
else if (az->type == AZONE_REGION) {
- if (az->ar) {
+ if (az->region) {
/* only display tab or icons when the region is hidden */
- if (az->ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
- region_draw_azone_tab_arrow(az);
+ if (az->region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
+ region_draw_azone_tab_arrow(area, region, az);
}
}
}
@@ -339,7 +343,7 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
}
}
if (!IS_EQF(az->alpha, 0.0f) && ELEM(az->type, AZONE_FULLSCREEN, AZONE_REGION_SCROLL)) {
- area_azone_tag_update(sa);
+ area_azone_tag_update(area);
}
}
@@ -348,9 +352,9 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
GPU_blend(false);
}
-static void region_draw_status_text(ScrArea *sa, ARegion *ar)
+static void region_draw_status_text(ScrArea *area, ARegion *region)
{
- bool overlap = ED_region_is_overlap(sa->spacetype, ar->regiontype);
+ bool overlap = ED_region_is_overlap(area->spacetype, region->regiontype);
if (overlap) {
GPU_clear_color(0.0, 0.0, 0.0, 0.0);
@@ -363,7 +367,7 @@ static void region_draw_status_text(ScrArea *sa, ARegion *ar)
int fontid = BLF_set_default();
- const float width = BLF_width(fontid, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
+ const float width = BLF_width(fontid, region->headerstr, BLF_DRAW_STR_DUMMY_MAX);
const float x = UI_UNIT_X;
const float y = 0.4f * UI_UNIT_Y;
@@ -372,7 +376,7 @@ static void region_draw_status_text(ScrArea *sa, ARegion *ar)
const float x1 = x - (UI_UNIT_X - pad);
const float x2 = x + width + (UI_UNIT_X - pad);
const float y1 = pad;
- const float y2 = ar->winy - pad;
+ const float y2 = region->winy - pad;
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
@@ -389,7 +393,7 @@ static void region_draw_status_text(ScrArea *sa, ARegion *ar)
}
BLF_position(fontid, x, y, 0.0f);
- BLF_draw(fontid, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_draw(fontid, region->headerstr, BLF_DRAW_STR_DUMMY_MAX);
}
void ED_region_do_msg_notify_tag_redraw(
@@ -398,18 +402,18 @@ void ED_region_do_msg_notify_tag_redraw(
wmMsgSubscribeKey *UNUSED(msg_key),
wmMsgSubscribeValue *msg_val)
{
- ARegion *ar = msg_val->owner;
- ED_region_tag_redraw(ar);
+ ARegion *region = msg_val->owner;
+ ED_region_tag_redraw(region);
/* This avoids _many_ situations where header/properties control display settings.
* the common case is space properties in the header */
- if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_UI)) {
- while (ar && ar->prev) {
- ar = ar->prev;
+ if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_UI)) {
+ while (region && region->prev) {
+ region = region->prev;
}
- for (; ar; ar = ar->next) {
- if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS)) {
- ED_region_tag_redraw(ar);
+ for (; region; region = region->next) {
+ if (ELEM(region->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS)) {
+ ED_region_tag_redraw(region);
}
}
}
@@ -421,8 +425,8 @@ void ED_area_do_msg_notify_tag_refresh(
wmMsgSubscribeKey *UNUSED(msg_key),
wmMsgSubscribeValue *msg_val)
{
- ScrArea *sa = msg_val->user_data;
- ED_area_tag_refresh(sa);
+ ScrArea *area = msg_val->user_data;
+ ED_area_tag_refresh(area);
}
void ED_area_do_mgs_subscribe_for_tool_header(
@@ -431,14 +435,14 @@ void ED_area_do_mgs_subscribe_for_tool_header(
struct WorkSpace *workspace,
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
- struct ScrArea *UNUSED(sa),
- struct ARegion *ar,
+ struct ScrArea *UNUSED(area),
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
- BLI_assert(ar->regiontype == RGN_TYPE_TOOL_HEADER);
+ BLI_assert(region->regiontype == RGN_TYPE_TOOL_HEADER);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
WM_msg_subscribe_rna_prop(
@@ -451,16 +455,16 @@ void ED_area_do_mgs_subscribe_for_tool_ui(
struct WorkSpace *workspace,
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
- struct ScrArea *UNUSED(sa),
- struct ARegion *ar,
+ struct ScrArea *UNUSED(area),
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
- BLI_assert(ar->regiontype == RGN_TYPE_UI);
- const char *category = UI_panel_category_active_get(ar, false);
+ BLI_assert(region->regiontype == RGN_TYPE_UI);
+ const char *category = UI_panel_category_active_get(region, false);
if (category && STREQ(category, "Tool")) {
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
WM_msg_subscribe_rna_prop(
@@ -480,67 +484,67 @@ static bool area_is_pseudo_minimized(const ScrArea *area)
}
/* only exported for WM */
-void ED_region_do_layout(bContext *C, ARegion *ar)
+void ED_region_do_layout(bContext *C, ARegion *region)
{
/* This is optional, only needed for dynamically sized regions. */
- ScrArea *sa = CTX_wm_area(C);
- ARegionType *at = ar->type;
+ ScrArea *area = CTX_wm_area(C);
+ ARegionType *at = region->type;
if (!at->layout) {
return;
}
- if (at->do_lock || (sa && area_is_pseudo_minimized(sa))) {
+ if (at->do_lock || (area && area_is_pseudo_minimized(area))) {
return;
}
- ar->do_draw |= RGN_DRAWING;
+ region->do_draw |= RGN_DRAWING;
- UI_SetTheme(sa ? sa->spacetype : 0, at->regionid);
- at->layout(C, ar);
+ UI_SetTheme(area ? area->spacetype : 0, at->regionid);
+ at->layout(C, region);
}
/* only exported for WM */
-void ED_region_do_draw(bContext *C, ARegion *ar)
+void ED_region_do_draw(bContext *C, ARegion *region)
{
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegionType *at = ar->type;
+ ScrArea *area = CTX_wm_area(C);
+ ARegionType *at = region->type;
/* see BKE_spacedata_draw_locks() */
if (at->do_lock) {
return;
}
- ar->do_draw |= RGN_DRAWING;
+ region->do_draw |= RGN_DRAWING;
- /* Set viewport, scissor, ortho and ar->drawrct. */
- wmPartialViewport(&ar->drawrct, &ar->winrct, &ar->drawrct);
+ /* Set viewport, scissor, ortho and region->drawrct. */
+ wmPartialViewport(&region->drawrct, &region->winrct, &region->drawrct);
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
- UI_SetTheme(sa ? sa->spacetype : 0, at->regionid);
+ UI_SetTheme(area ? area->spacetype : 0, at->regionid);
- if (sa && area_is_pseudo_minimized(sa)) {
+ if (area && area_is_pseudo_minimized(area)) {
UI_ThemeClearColor(TH_EDITOR_OUTLINE);
glClear(GL_COLOR_BUFFER_BIT);
return;
}
/* optional header info instead? */
- else if (ar->headerstr) {
- region_draw_status_text(sa, ar);
+ else if (region->headerstr) {
+ region_draw_status_text(area, region);
}
else if (at->draw) {
- at->draw(C, ar);
+ at->draw(C, region);
}
/* XXX test: add convention to end regions always in pixel space,
* for drawing of borders/gestures etc */
- ED_region_pixelspace(ar);
+ ED_region_pixelspace(region);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_PIXEL);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_PIXEL);
- region_draw_azones(sa, ar);
+ region_draw_azones(area, region);
/* for debugging unneeded area redraws and partial redraw */
if (G.debug_value == 888) {
@@ -550,26 +554,26 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(BLI_thread_frand(0), BLI_thread_frand(0), BLI_thread_frand(0), 0.1f);
immRectf(pos,
- ar->drawrct.xmin - ar->winrct.xmin,
- ar->drawrct.ymin - ar->winrct.ymin,
- ar->drawrct.xmax - ar->winrct.xmin,
- ar->drawrct.ymax - ar->winrct.ymin);
+ region->drawrct.xmin - region->winrct.xmin,
+ region->drawrct.ymin - region->winrct.ymin,
+ region->drawrct.xmax - region->winrct.xmin,
+ region->drawrct.ymax - region->winrct.ymin);
immUnbindProgram();
GPU_blend(false);
}
- memset(&ar->drawrct, 0, sizeof(ar->drawrct));
+ memset(&region->drawrct, 0, sizeof(region->drawrct));
- UI_blocklist_free_inactive(C, &ar->uiblocks);
+ UI_blocklist_free_inactive(C, &region->uiblocks);
- if (sa) {
+ if (area) {
const bScreen *screen = WM_window_get_active_screen(win);
/* Only region emboss for top-bar */
- if ((screen->state != SCREENFULL) && ED_area_is_global(sa)) {
- region_draw_emboss(ar, &ar->winrct, (REGION_EMBOSS_LEFT | REGION_EMBOSS_RIGHT));
+ if ((screen->state != SCREENFULL) && ED_area_is_global(area)) {
+ region_draw_emboss(region, &region->winrct, (REGION_EMBOSS_LEFT | REGION_EMBOSS_RIGHT));
}
- else if ((ar->regiontype == RGN_TYPE_WINDOW) && (ar->alignment == RGN_ALIGN_QSPLIT)) {
+ else if ((region->regiontype == RGN_TYPE_WINDOW) && (region->alignment == RGN_ALIGN_QSPLIT)) {
/* draw separating lines between the quad views */
@@ -580,8 +584,11 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(color);
GPU_line_width(1.0f);
- imm_draw_box_wire_2d(
- pos, 0, 0, ar->winrct.xmax - ar->winrct.xmin + 1, ar->winrct.ymax - ar->winrct.ymin + 1);
+ imm_draw_box_wire_2d(pos,
+ 0,
+ 0,
+ region->winrct.xmax - region->winrct.xmin + 1,
+ region->winrct.ymax - region->winrct.ymin + 1);
immUnbindProgram();
}
}
@@ -593,28 +600,29 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
bScreen *screen = WM_window_get_active_screen(win);
Scene *scene = CTX_data_scene(C);
struct wmMsgBus *mbus = wm->message_bus;
- WM_msgbus_clear_by_owner(mbus, ar);
+ WM_msgbus_clear_by_owner(mbus, region);
/* Cheat, always subscribe to this space type properties.
*
* This covers most cases and avoids copy-paste similar code for each space type.
*/
- if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS, RGN_TYPE_UI, RGN_TYPE_TOOLS)) {
- SpaceLink *sl = sa->spacedata.first;
+ if (ELEM(
+ region->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS, RGN_TYPE_UI, RGN_TYPE_TOOLS)) {
+ SpaceLink *sl = area->spacedata.first;
PointerRNA ptr;
RNA_pointer_create(&screen->id, &RNA_Space, sl, &ptr);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
/* All properties for this space type. */
WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_region_tag_redraw, __func__);
}
- ED_region_message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
+ ED_region_message_subscribe(C, workspace, scene, screen, area, region, mbus);
}
}
@@ -623,136 +631,152 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
* to keep these tags protected
* ********************************** */
-void ED_region_tag_redraw(ARegion *ar)
+void ED_region_tag_redraw(ARegion *region)
{
/* don't tag redraw while drawing, it shouldn't happen normally
* but python scripts can cause this to happen indirectly */
- if (ar && !(ar->do_draw & RGN_DRAWING)) {
+ if (region && !(region->do_draw & RGN_DRAWING)) {
/* zero region means full region redraw */
- ar->do_draw &= ~(RGN_DRAW_PARTIAL | RGN_DRAW_NO_REBUILD);
- ar->do_draw |= RGN_DRAW;
- memset(&ar->drawrct, 0, sizeof(ar->drawrct));
+ region->do_draw &= ~(RGN_DRAW_PARTIAL | RGN_DRAW_NO_REBUILD | RGN_DRAW_EDITOR_OVERLAYS);
+ region->do_draw |= RGN_DRAW;
+ memset(&region->drawrct, 0, sizeof(region->drawrct));
}
}
-void ED_region_tag_redraw_overlay(ARegion *ar)
+void ED_region_tag_redraw_cursor(ARegion *region)
{
- if (ar) {
- ar->do_draw_overlay = RGN_DRAW;
+ if (region) {
+ region->do_draw_overlay = RGN_DRAW;
}
}
-void ED_region_tag_redraw_no_rebuild(ARegion *ar)
+void ED_region_tag_redraw_no_rebuild(ARegion *region)
{
- if (ar && !(ar->do_draw & (RGN_DRAWING | RGN_DRAW))) {
- ar->do_draw &= ~RGN_DRAW_PARTIAL;
- ar->do_draw |= RGN_DRAW_NO_REBUILD;
- memset(&ar->drawrct, 0, sizeof(ar->drawrct));
+ if (region && !(region->do_draw & (RGN_DRAWING | RGN_DRAW))) {
+ region->do_draw &= ~(RGN_DRAW_PARTIAL | RGN_DRAW_EDITOR_OVERLAYS);
+ region->do_draw |= RGN_DRAW_NO_REBUILD;
+ memset(&region->drawrct, 0, sizeof(region->drawrct));
}
}
-void ED_region_tag_refresh_ui(ARegion *ar)
+void ED_region_tag_refresh_ui(ARegion *region)
{
- if (ar) {
- ar->do_draw |= RGN_REFRESH_UI;
+ if (region) {
+ region->do_draw |= RGN_REFRESH_UI;
}
}
-void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct, bool rebuild)
+/**
+ * Tag editor overlays to be redrawn. If in doubt about which parts need to be redrawn (partial
+ * clipping rectangle set), redraw everything.
+ */
+void ED_region_tag_redraw_editor_overlays(struct ARegion *region)
{
- if (ar && !(ar->do_draw & RGN_DRAWING)) {
- if (ar->do_draw & RGN_DRAW_PARTIAL) {
+ if (region && !(region->do_draw & (RGN_DRAWING | RGN_DRAW))) {
+ if (region->do_draw & RGN_DRAW_PARTIAL) {
+ ED_region_tag_redraw(region);
+ }
+ else {
+ region->do_draw |= RGN_DRAW_EDITOR_OVERLAYS;
+ }
+ }
+}
+
+void ED_region_tag_redraw_partial(ARegion *region, const rcti *rct, bool rebuild)
+{
+ if (region && !(region->do_draw & RGN_DRAWING)) {
+ if (region->do_draw & RGN_DRAW_PARTIAL) {
/* Partial redraw already set, expand region. */
- BLI_rcti_union(&ar->drawrct, rct);
+ BLI_rcti_union(&region->drawrct, rct);
if (rebuild) {
- ar->do_draw &= ~RGN_DRAW_NO_REBUILD;
+ region->do_draw &= ~RGN_DRAW_NO_REBUILD;
}
}
- else if (ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD)) {
+ else if (region->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD)) {
/* Full redraw already requested. */
if (rebuild) {
- ar->do_draw &= ~RGN_DRAW_NO_REBUILD;
+ region->do_draw &= ~RGN_DRAW_NO_REBUILD;
}
}
else {
/* No redraw set yet, set partial region. */
- ar->drawrct = *rct;
- ar->do_draw |= RGN_DRAW_PARTIAL;
+ region->drawrct = *rct;
+ region->do_draw |= RGN_DRAW_PARTIAL;
if (!rebuild) {
- ar->do_draw |= RGN_DRAW_NO_REBUILD;
+ region->do_draw |= RGN_DRAW_NO_REBUILD;
}
}
}
}
-void ED_area_tag_redraw(ScrArea *sa)
+void ED_area_tag_redraw(ScrArea *area)
{
- ARegion *ar;
+ ARegion *region;
- if (sa) {
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- ED_region_tag_redraw(ar);
+ if (area) {
+ for (region = area->regionbase.first; region; region = region->next) {
+ ED_region_tag_redraw(region);
}
}
}
-void ED_area_tag_redraw_no_rebuild(ScrArea *sa)
+void ED_area_tag_redraw_no_rebuild(ScrArea *area)
{
- ARegion *ar;
+ ARegion *region;
- if (sa) {
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- ED_region_tag_redraw_no_rebuild(ar);
+ if (area) {
+ for (region = area->regionbase.first; region; region = region->next) {
+ ED_region_tag_redraw_no_rebuild(region);
}
}
}
-void ED_area_tag_redraw_regiontype(ScrArea *sa, int regiontype)
+void ED_area_tag_redraw_regiontype(ScrArea *area, int regiontype)
{
- ARegion *ar;
+ ARegion *region;
- if (sa) {
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == regiontype) {
- ED_region_tag_redraw(ar);
+ if (area) {
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == regiontype) {
+ ED_region_tag_redraw(region);
}
}
}
}
-void ED_area_tag_refresh(ScrArea *sa)
+void ED_area_tag_refresh(ScrArea *area)
{
- if (sa) {
- sa->do_refresh = true;
+ if (area) {
+ area->do_refresh = true;
}
}
/* *************************************************************** */
/* use NULL to disable it */
-void ED_area_status_text(ScrArea *sa, const char *str)
+void ED_area_status_text(ScrArea *area, const char *str)
{
- ARegion *ar;
+ ARegion *region;
/* happens when running transform operators in background mode */
- if (sa == NULL) {
+ if (area == NULL) {
return;
}
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_HEADER) {
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_HEADER) {
if (str) {
- if (ar->headerstr == NULL) {
- ar->headerstr = MEM_mallocN(UI_MAX_DRAW_STR, "headerprint");
+ if (region->headerstr == NULL) {
+ region->headerstr = MEM_mallocN(UI_MAX_DRAW_STR, "headerprint");
}
- BLI_strncpy(ar->headerstr, str, UI_MAX_DRAW_STR);
- BLI_str_rstrip(ar->headerstr);
+ BLI_strncpy(region->headerstr, str, UI_MAX_DRAW_STR);
+ BLI_str_rstrip(region->headerstr);
}
- else if (ar->headerstr) {
- MEM_freeN(ar->headerstr);
- ar->headerstr = NULL;
+ else if (region->headerstr) {
+ MEM_freeN(region->headerstr);
+ region->headerstr = NULL;
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
}
@@ -779,9 +803,9 @@ void ED_workspace_status_text(bContext *C, const char *str)
}
/* Redraw status bar. */
- for (ScrArea *sa = win->global_areas.areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_STATUSBAR) {
- ED_area_tag_redraw(sa);
+ LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) {
+ if (area->spacetype == SPACE_STATUSBAR) {
+ ED_area_tag_redraw(area);
break;
}
}
@@ -789,12 +813,12 @@ void ED_workspace_status_text(bContext *C, const char *str)
/* ************************************************************ */
-static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea *sa)
+static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea *area)
{
AZone *az;
/* reinitialize entirely, regions and fullscreen add azones too */
- BLI_freelistN(&sa->actionzones);
+ BLI_freelistN(&area->actionzones);
if (screen->state != SCREENNORMAL) {
return;
@@ -804,7 +828,7 @@ static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea
return;
}
- if (ED_area_is_global(sa)) {
+ if (ED_area_is_global(area)) {
return;
}
@@ -814,25 +838,25 @@ static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea
const float coords[4][4] = {
/* Bottom-left. */
- {sa->totrct.xmin - U.pixelsize,
- sa->totrct.ymin - U.pixelsize,
- sa->totrct.xmin + AZONESPOTW,
- sa->totrct.ymin + AZONESPOTH},
+ {area->totrct.xmin - U.pixelsize,
+ area->totrct.ymin - U.pixelsize,
+ area->totrct.xmin + AZONESPOTW,
+ area->totrct.ymin + AZONESPOTH},
/* Bottom-right. */
- {sa->totrct.xmax - AZONESPOTW,
- sa->totrct.ymin - U.pixelsize,
- sa->totrct.xmax + U.pixelsize,
- sa->totrct.ymin + AZONESPOTH},
+ {area->totrct.xmax - AZONESPOTW,
+ area->totrct.ymin - U.pixelsize,
+ area->totrct.xmax + U.pixelsize,
+ area->totrct.ymin + AZONESPOTH},
/* Top-left. */
- {sa->totrct.xmin - U.pixelsize,
- sa->totrct.ymax - AZONESPOTH,
- sa->totrct.xmin + AZONESPOTW,
- sa->totrct.ymax + U.pixelsize},
+ {area->totrct.xmin - U.pixelsize,
+ area->totrct.ymax - AZONESPOTH,
+ area->totrct.xmin + AZONESPOTW,
+ area->totrct.ymax + U.pixelsize},
/* Top-right. */
- {sa->totrct.xmax - AZONESPOTW,
- sa->totrct.ymax - AZONESPOTH,
- sa->totrct.xmax + U.pixelsize,
- sa->totrct.ymax + U.pixelsize},
+ {area->totrct.xmax - AZONESPOTW,
+ area->totrct.ymax - AZONESPOTH,
+ area->totrct.xmax + U.pixelsize,
+ area->totrct.ymax + U.pixelsize},
};
for (int i = 0; i < 4; i++) {
@@ -849,7 +873,7 @@ static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea
/* set area action zones */
az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
- BLI_addtail(&(sa->actionzones), az);
+ BLI_addtail(&(area->actionzones), az);
az->type = AZONE_AREA;
az->x1 = coords[i][0];
az->y1 = coords[i][1];
@@ -859,28 +883,28 @@ static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea
}
}
-static void fullscreen_azone_initialize(ScrArea *sa, ARegion *ar)
+static void fullscreen_azone_initialize(ScrArea *area, ARegion *region)
{
AZone *az;
- if (ED_area_is_global(sa) || (ar->regiontype != RGN_TYPE_WINDOW)) {
+ if (ED_area_is_global(area) || (region->regiontype != RGN_TYPE_WINDOW)) {
return;
}
az = (AZone *)MEM_callocN(sizeof(AZone), "fullscreen action zone");
- BLI_addtail(&(sa->actionzones), az);
+ BLI_addtail(&(area->actionzones), az);
az->type = AZONE_FULLSCREEN;
- az->ar = ar;
+ az->region = region;
az->alpha = 0.0f;
if (U.uiflag2 & USER_REGION_OVERLAP) {
- const rcti *rect_visible = ED_region_visible_rect(ar);
- az->x2 = ar->winrct.xmin + rect_visible->xmax;
- az->y2 = ar->winrct.ymin + rect_visible->ymax;
+ const rcti *rect_visible = ED_region_visible_rect(region);
+ az->x2 = region->winrct.xmin + rect_visible->xmax;
+ az->y2 = region->winrct.ymin + rect_visible->ymax;
}
else {
- az->x2 = ar->winrct.xmax;
- az->y2 = ar->winrct.ymax;
+ az->x2 = region->winrct.xmax;
+ az->y2 = region->winrct.ymax;
}
az->x1 = az->x2 - AZONEFADEOUT;
az->y1 = az->y2 - AZONEFADEOUT;
@@ -890,39 +914,39 @@ static void fullscreen_azone_initialize(ScrArea *sa, ARegion *ar)
#define AZONEPAD_EDGE (0.1f * U.widget_unit)
#define AZONEPAD_ICON (0.45f * U.widget_unit)
-static void region_azone_edge(AZone *az, ARegion *ar)
+static void region_azone_edge(AZone *az, ARegion *region)
{
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- az->x1 = ar->winrct.xmin;
- az->y1 = ar->winrct.ymax - AZONEPAD_EDGE;
- az->x2 = ar->winrct.xmax;
- az->y2 = ar->winrct.ymax + AZONEPAD_EDGE;
+ az->x1 = region->winrct.xmin;
+ az->y1 = region->winrct.ymax - AZONEPAD_EDGE;
+ az->x2 = region->winrct.xmax;
+ az->y2 = region->winrct.ymax + AZONEPAD_EDGE;
break;
case AE_BOTTOM_TO_TOPLEFT:
- az->x1 = ar->winrct.xmin;
- az->y1 = ar->winrct.ymin + AZONEPAD_EDGE;
- az->x2 = ar->winrct.xmax;
- az->y2 = ar->winrct.ymin - AZONEPAD_EDGE;
+ az->x1 = region->winrct.xmin;
+ az->y1 = region->winrct.ymin + AZONEPAD_EDGE;
+ az->x2 = region->winrct.xmax;
+ az->y2 = region->winrct.ymin - AZONEPAD_EDGE;
break;
case AE_LEFT_TO_TOPRIGHT:
- az->x1 = ar->winrct.xmin - AZONEPAD_EDGE;
- az->y1 = ar->winrct.ymin;
- az->x2 = ar->winrct.xmin + AZONEPAD_EDGE;
- az->y2 = ar->winrct.ymax;
+ az->x1 = region->winrct.xmin - AZONEPAD_EDGE;
+ az->y1 = region->winrct.ymin;
+ az->x2 = region->winrct.xmin + AZONEPAD_EDGE;
+ az->y2 = region->winrct.ymax;
break;
case AE_RIGHT_TO_TOPLEFT:
- az->x1 = ar->winrct.xmax + AZONEPAD_EDGE;
- az->y1 = ar->winrct.ymin;
- az->x2 = ar->winrct.xmax - AZONEPAD_EDGE;
- az->y2 = ar->winrct.ymax;
+ az->x1 = region->winrct.xmax + AZONEPAD_EDGE;
+ az->y1 = region->winrct.ymin;
+ az->x2 = region->winrct.xmax - AZONEPAD_EDGE;
+ az->y2 = region->winrct.ymax;
break;
}
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
/* region already made zero sized, in shape of edge */
-static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
+static void region_azone_tab_plus(ScrArea *area, AZone *az, ARegion *region)
{
AZone *azt;
int tot = 0, add;
@@ -932,7 +956,7 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
const float tab_size_x = 0.7f * U.widget_unit;
const float tab_size_y = 0.4f * U.widget_unit;
- for (azt = sa->actionzones.first; azt; azt = azt->next) {
+ for (azt = area->actionzones.first; azt; azt = azt->next) {
if (azt->edge == az->edge) {
tot++;
}
@@ -940,95 +964,95 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0;
- az->x1 = ar->winrct.xmax - ((edge_offset + 1.0f) * tab_size_x);
- az->y1 = ar->winrct.ymax - add;
- az->x2 = ar->winrct.xmax - (edge_offset * tab_size_x);
- az->y2 = ar->winrct.ymax - add + tab_size_y;
+ add = (region->winrct.ymax == area->totrct.ymin) ? 1 : 0;
+ az->x1 = region->winrct.xmax - ((edge_offset + 1.0f) * tab_size_x);
+ az->y1 = region->winrct.ymax - add;
+ az->x2 = region->winrct.xmax - (edge_offset * tab_size_x);
+ az->y2 = region->winrct.ymax - add + tab_size_y;
break;
case AE_BOTTOM_TO_TOPLEFT:
- az->x1 = ar->winrct.xmax - ((edge_offset + 1.0f) * tab_size_x);
- az->y1 = ar->winrct.ymin - tab_size_y;
- az->x2 = ar->winrct.xmax - (edge_offset * tab_size_x);
- az->y2 = ar->winrct.ymin;
+ az->x1 = region->winrct.xmax - ((edge_offset + 1.0f) * tab_size_x);
+ az->y1 = region->winrct.ymin - tab_size_y;
+ az->x2 = region->winrct.xmax - (edge_offset * tab_size_x);
+ az->y2 = region->winrct.ymin;
break;
case AE_LEFT_TO_TOPRIGHT:
- az->x1 = ar->winrct.xmin - tab_size_y;
- az->y1 = ar->winrct.ymax - ((edge_offset + 1.0f) * tab_size_x);
- az->x2 = ar->winrct.xmin;
- az->y2 = ar->winrct.ymax - (edge_offset * tab_size_x);
+ az->x1 = region->winrct.xmin - tab_size_y;
+ az->y1 = region->winrct.ymax - ((edge_offset + 1.0f) * tab_size_x);
+ az->x2 = region->winrct.xmin;
+ az->y2 = region->winrct.ymax - (edge_offset * tab_size_x);
break;
case AE_RIGHT_TO_TOPLEFT:
- az->x1 = ar->winrct.xmax;
- az->y1 = ar->winrct.ymax - ((edge_offset + 1.0f) * tab_size_x);
- az->x2 = ar->winrct.xmax + tab_size_y;
- az->y2 = ar->winrct.ymax - (edge_offset * tab_size_x);
+ az->x1 = region->winrct.xmax;
+ az->y1 = region->winrct.ymax - ((edge_offset + 1.0f) * tab_size_x);
+ az->x2 = region->winrct.xmax + tab_size_y;
+ az->y2 = region->winrct.ymax - (edge_offset * tab_size_x);
break;
}
/* rect needed for mouse pointer test */
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
-static bool region_azone_edge_poll(const ARegion *ar, const bool is_fullscreen)
+static bool region_azone_edge_poll(const ARegion *region, const bool is_fullscreen)
{
- const bool is_hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
+ const bool is_hidden = (region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
if (is_hidden && is_fullscreen) {
return false;
}
- if (!is_hidden && ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ if (!is_hidden && ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
return false;
}
return true;
}
-static void region_azone_edge_initialize(ScrArea *sa,
- ARegion *ar,
+static void region_azone_edge_initialize(ScrArea *area,
+ ARegion *region,
AZEdge edge,
const bool is_fullscreen)
{
AZone *az = NULL;
- const bool is_hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
+ const bool is_hidden = (region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
- if (!region_azone_edge_poll(ar, is_fullscreen)) {
+ if (!region_azone_edge_poll(region, is_fullscreen)) {
return;
}
az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
- BLI_addtail(&(sa->actionzones), az);
+ BLI_addtail(&(area->actionzones), az);
az->type = AZONE_REGION;
- az->ar = ar;
+ az->region = region;
az->edge = edge;
if (is_hidden) {
- region_azone_tab_plus(sa, az, ar);
+ region_azone_tab_plus(area, az, region);
}
else {
- region_azone_edge(az, ar);
+ region_azone_edge(az, region);
}
}
-static void region_azone_scrollbar_initialize(ScrArea *sa,
- ARegion *ar,
+static void region_azone_scrollbar_initialize(ScrArea *area,
+ ARegion *region,
AZScrollDirection direction)
{
- rcti scroller_vert = (direction == AZ_SCROLL_VERT) ? ar->v2d.vert : ar->v2d.hor;
+ rcti scroller_vert = (direction == AZ_SCROLL_VERT) ? region->v2d.vert : region->v2d.hor;
AZone *az = MEM_callocN(sizeof(*az), __func__);
- BLI_addtail(&sa->actionzones, az);
+ BLI_addtail(&area->actionzones, az);
az->type = AZONE_REGION_SCROLL;
- az->ar = ar;
+ az->region = region;
az->direction = direction;
if (direction == AZ_SCROLL_VERT) {
- az->ar->v2d.alpha_vert = 0;
+ az->region->v2d.alpha_vert = 0;
}
else if (direction == AZ_SCROLL_HOR) {
- az->ar->v2d.alpha_hor = 0;
+ az->region->v2d.alpha_hor = 0;
}
- BLI_rcti_translate(&scroller_vert, ar->winrct.xmin, ar->winrct.ymin);
+ BLI_rcti_translate(&scroller_vert, region->winrct.xmin, region->winrct.ymin);
az->x1 = scroller_vert.xmin - AZONEFADEIN;
az->y1 = scroller_vert.ymin - AZONEFADEIN;
az->x2 = scroller_vert.xmax + AZONEFADEIN;
@@ -1037,64 +1061,65 @@ static void region_azone_scrollbar_initialize(ScrArea *sa,
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
-static void region_azones_scrollbars_initialize(ScrArea *sa, ARegion *ar)
+static void region_azones_scrollbars_initialize(ScrArea *area, ARegion *region)
{
- const View2D *v2d = &ar->v2d;
+ const View2D *v2d = &region->v2d;
if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) == 0)) {
- region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_VERT);
+ region_azone_scrollbar_initialize(area, region, AZ_SCROLL_VERT);
}
if ((v2d->scroll & V2D_SCROLL_HORIZONTAL) &&
((v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) == 0)) {
- region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_HOR);
+ region_azone_scrollbar_initialize(area, region, AZ_SCROLL_HOR);
}
}
/* *************************************************************** */
-static void region_azones_add_edge(ScrArea *sa,
- ARegion *ar,
+static void region_azones_add_edge(ScrArea *area,
+ ARegion *region,
const int alignment,
const bool is_fullscreen)
{
/* edge code (t b l r) is along which area edge azone will be drawn */
if (alignment == RGN_ALIGN_TOP) {
- region_azone_edge_initialize(sa, ar, AE_BOTTOM_TO_TOPLEFT, is_fullscreen);
+ region_azone_edge_initialize(area, region, AE_BOTTOM_TO_TOPLEFT, is_fullscreen);
}
else if (alignment == RGN_ALIGN_BOTTOM) {
- region_azone_edge_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen);
+ region_azone_edge_initialize(area, region, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen);
}
else if (alignment == RGN_ALIGN_RIGHT) {
- region_azone_edge_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT, is_fullscreen);
+ region_azone_edge_initialize(area, region, AE_LEFT_TO_TOPRIGHT, is_fullscreen);
}
else if (alignment == RGN_ALIGN_LEFT) {
- region_azone_edge_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT, is_fullscreen);
+ region_azone_edge_initialize(area, region, AE_RIGHT_TO_TOPLEFT, is_fullscreen);
}
}
-static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar)
+static void region_azones_add(const bScreen *screen, ScrArea *area, ARegion *region)
{
const bool is_fullscreen = screen->state == SCREENFULL;
/* Only display tab or icons when the header region is hidden
* (not the tool header - they overlap). */
- if (ar->regiontype == RGN_TYPE_TOOL_HEADER) {
+ if (region->regiontype == RGN_TYPE_TOOL_HEADER) {
return;
}
- region_azones_add_edge(sa, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->alignment), is_fullscreen);
+ region_azones_add_edge(area, region, RGN_ALIGN_ENUM_FROM_MASK(region->alignment), is_fullscreen);
/* For a split region also continue the azone edge from the next region if this region is aligned
* with the next */
- if ((ar->alignment & RGN_SPLIT_PREV) && ar->prev) {
- region_azones_add_edge(sa, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->prev->alignment), is_fullscreen);
+ if ((region->alignment & RGN_SPLIT_PREV) && region->prev) {
+ region_azones_add_edge(
+ area, region, RGN_ALIGN_ENUM_FROM_MASK(region->prev->alignment), is_fullscreen);
}
if (is_fullscreen) {
- fullscreen_azone_initialize(sa, ar);
+ fullscreen_azone_initialize(area, region);
}
- region_azones_scrollbars_initialize(sa, ar);
+ region_azones_scrollbars_initialize(area, region);
}
/* dir is direction to check, not the splitting edge direction! */
@@ -1110,16 +1135,16 @@ static int rct_fits(const rcti *rect, char dir, int size)
/* *************************************************************** */
-/* ar should be overlapping */
+/* region should be overlapping */
/* function checks if some overlapping region was defined before - on same place */
-static void region_overlap_fix(ScrArea *sa, ARegion *ar)
+static void region_overlap_fix(ScrArea *area, ARegion *region)
{
ARegion *ar1;
- const int align = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment);
+ const int align = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
int align1 = 0;
/* find overlapping previous region on same place */
- for (ar1 = ar->prev; ar1; ar1 = ar1->prev) {
+ for (ar1 = region->prev; ar1; ar1 = ar1->prev) {
if (ar1->flag & (RGN_FLAG_HIDDEN)) {
continue;
}
@@ -1129,10 +1154,10 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
continue;
}
align1 = ar1->alignment;
- if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
+ if (BLI_rcti_isect(&ar1->winrct, &region->winrct, NULL)) {
if (align1 != align) {
/* Left overlapping right or vice-versa, forbid this! */
- ar->flag |= RGN_FLAG_TOO_SMALL;
+ region->flag |= RGN_FLAG_TOO_SMALL;
return;
}
/* Else, we have our previous region on same side. */
@@ -1147,28 +1172,28 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
/* translate or close */
if (ar1) {
if (align1 == RGN_ALIGN_LEFT) {
- if (ar->winrct.xmax + ar1->winx > sa->winx - U.widget_unit) {
- ar->flag |= RGN_FLAG_TOO_SMALL;
+ if (region->winrct.xmax + ar1->winx > area->winx - U.widget_unit) {
+ region->flag |= RGN_FLAG_TOO_SMALL;
return;
}
else {
- BLI_rcti_translate(&ar->winrct, ar1->winx, 0);
+ BLI_rcti_translate(&region->winrct, ar1->winx, 0);
}
}
else if (align1 == RGN_ALIGN_RIGHT) {
- if (ar->winrct.xmin - ar1->winx < U.widget_unit) {
- ar->flag |= RGN_FLAG_TOO_SMALL;
+ if (region->winrct.xmin - ar1->winx < U.widget_unit) {
+ region->flag |= RGN_FLAG_TOO_SMALL;
return;
}
else {
- BLI_rcti_translate(&ar->winrct, -ar1->winx, 0);
+ BLI_rcti_translate(&region->winrct, -ar1->winx, 0);
}
}
}
- /* At this point, 'ar' is in its final position and still open.
+ /* At this point, 'region' is in its final position and still open.
* Make a final check it does not overlap any previous 'other side' region. */
- for (ar1 = ar->prev; ar1; ar1 = ar1->prev) {
+ for (ar1 = region->prev; ar1; ar1 = ar1->prev) {
if (ar1->flag & (RGN_FLAG_HIDDEN)) {
continue;
}
@@ -1177,9 +1202,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
}
if (ar1->overlap && (ar1->alignment & RGN_SPLIT_PREV) == 0) {
- if ((ar1->alignment != align) && BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
+ if ((ar1->alignment != align) && BLI_rcti_isect(&ar1->winrct, &region->winrct, NULL)) {
/* Left overlapping right or vice-versa, forbid this! */
- ar->flag |= RGN_FLAG_TOO_SMALL;
+ region->flag |= RGN_FLAG_TOO_SMALL;
return;
}
}
@@ -1214,36 +1239,36 @@ bool ED_region_is_overlap(int spacetype, int regiontype)
}
static void region_rect_recursive(
- ScrArea *sa, ARegion *ar, rcti *remainder, rcti *overlap_remainder, int quad)
+ ScrArea *area, ARegion *region, rcti *remainder, rcti *overlap_remainder, int quad)
{
rcti *remainder_prev = remainder;
- if (ar == NULL) {
+ if (region == NULL) {
return;
}
- int prev_winx = ar->winx;
- int prev_winy = ar->winy;
+ int prev_winx = region->winx;
+ int prev_winy = region->winy;
/* no returns in function, winrct gets set in the end again */
- BLI_rcti_init(&ar->winrct, 0, 0, 0, 0);
+ BLI_rcti_init(&region->winrct, 0, 0, 0, 0);
/* for test; allow split of previously defined region */
- if (ar->alignment & RGN_SPLIT_PREV) {
- if (ar->prev) {
- remainder = &ar->prev->winrct;
+ if (region->alignment & RGN_SPLIT_PREV) {
+ if (region->prev) {
+ remainder = &region->prev->winrct;
}
}
- int alignment = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment);
+ int alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
/* set here, assuming userpref switching forces to call this again */
- ar->overlap = ED_region_is_overlap(sa->spacetype, ar->regiontype);
+ region->overlap = ED_region_is_overlap(area->spacetype, region->regiontype);
/* clear state flags first */
- ar->flag &= ~(RGN_FLAG_TOO_SMALL | RGN_FLAG_SIZE_CLAMP_X | RGN_FLAG_SIZE_CLAMP_Y);
+ region->flag &= ~(RGN_FLAG_TOO_SMALL | RGN_FLAG_SIZE_CLAMP_X | RGN_FLAG_SIZE_CLAMP_Y);
/* user errors */
- if ((ar->next == NULL) && !ELEM(alignment, RGN_ALIGN_QSPLIT, RGN_ALIGN_FLOAT)) {
+ if ((region->next == NULL) && !ELEM(alignment, RGN_ALIGN_QSPLIT, RGN_ALIGN_FLOAT)) {
alignment = RGN_ALIGN_NONE;
}
@@ -1252,40 +1277,41 @@ static void region_rect_recursive(
* layout to be created despite the RGN_FLAG_TOO_SMALL flag being set. But there may still be
* regions that don't have a separate ARegionType.layout callback. For those, set a default
* prefsize so they can become visible. */
- if ((ar->flag & RGN_FLAG_DYNAMIC_SIZE) && !(ar->type->layout)) {
- if ((ar->sizex == 0) && (ar->type->prefsizex == 0)) {
- ar->type->prefsizex = AREAMINX;
+ if ((region->flag & RGN_FLAG_DYNAMIC_SIZE) && !(region->type->layout)) {
+ if ((region->sizex == 0) && (region->type->prefsizex == 0)) {
+ region->type->prefsizex = AREAMINX;
}
- if ((ar->sizey == 0) && (ar->type->prefsizey == 0)) {
- ar->type->prefsizey = HEADERY;
+ if ((region->sizey == 0) && (region->type->prefsizey == 0)) {
+ region->type->prefsizey = HEADERY;
}
}
/* prefsize, taking into account DPI */
- int prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->type->prefsizex);
+ int prefsizex = UI_DPI_FAC *
+ ((region->sizex > 1) ? region->sizex + 0.5f : region->type->prefsizex);
int prefsizey;
- if (ar->flag & RGN_FLAG_PREFSIZE_OR_HIDDEN) {
- prefsizex = UI_DPI_FAC * ar->type->prefsizex;
- prefsizey = UI_DPI_FAC * ar->type->prefsizey;
+ if (region->flag & RGN_FLAG_PREFSIZE_OR_HIDDEN) {
+ prefsizex = UI_DPI_FAC * region->type->prefsizex;
+ prefsizey = UI_DPI_FAC * region->type->prefsizey;
}
- else if (ar->regiontype == RGN_TYPE_HEADER) {
+ else if (region->regiontype == RGN_TYPE_HEADER) {
prefsizey = ED_area_headersize();
}
- else if (ar->regiontype == RGN_TYPE_TOOL_HEADER) {
+ else if (region->regiontype == RGN_TYPE_TOOL_HEADER) {
prefsizey = ED_area_headersize();
}
- else if (ar->regiontype == RGN_TYPE_FOOTER) {
+ else if (region->regiontype == RGN_TYPE_FOOTER) {
prefsizey = ED_area_footersize();
}
- else if (ED_area_is_global(sa)) {
+ else if (ED_area_is_global(area)) {
prefsizey = ED_region_global_size_y();
}
else {
- prefsizey = UI_DPI_FAC * (ar->sizey > 1 ? ar->sizey + 0.5f : ar->type->prefsizey);
+ prefsizey = UI_DPI_FAC * (region->sizey > 1 ? region->sizey + 0.5f : region->type->prefsizey);
}
- if (ar->flag & RGN_FLAG_HIDDEN) {
+ if (region->flag & RGN_FLAG_HIDDEN) {
/* hidden is user flag */
}
else if (alignment == RGN_ALIGN_FLOAT) {
@@ -1301,47 +1327,47 @@ static void region_rect_recursive(
BLI_rcti_resize(&overlap_remainder_margin,
max_ii(0, BLI_rcti_size_x(overlap_remainder) - UI_UNIT_X / 2),
max_ii(0, BLI_rcti_size_y(overlap_remainder) - UI_UNIT_Y / 2));
- ar->winrct.xmin = overlap_remainder_margin.xmin + ar->runtime.offset_x;
- ar->winrct.ymin = overlap_remainder_margin.ymin + ar->runtime.offset_y;
- ar->winrct.xmax = ar->winrct.xmin + prefsizex - 1;
- ar->winrct.ymax = ar->winrct.ymin + prefsizey - 1;
+ region->winrct.xmin = overlap_remainder_margin.xmin + region->runtime.offset_x;
+ region->winrct.ymin = overlap_remainder_margin.ymin + region->runtime.offset_y;
+ region->winrct.xmax = region->winrct.xmin + prefsizex - 1;
+ region->winrct.ymax = region->winrct.ymin + prefsizey - 1;
- BLI_rcti_isect(&ar->winrct, &overlap_remainder_margin, &ar->winrct);
+ BLI_rcti_isect(&region->winrct, &overlap_remainder_margin, &region->winrct);
- if (BLI_rcti_size_x(&ar->winrct) != prefsizex - 1) {
- ar->flag |= RGN_FLAG_SIZE_CLAMP_X;
+ if (BLI_rcti_size_x(&region->winrct) != prefsizex - 1) {
+ region->flag |= RGN_FLAG_SIZE_CLAMP_X;
}
- if (BLI_rcti_size_y(&ar->winrct) != prefsizey - 1) {
- ar->flag |= RGN_FLAG_SIZE_CLAMP_Y;
+ if (BLI_rcti_size_y(&region->winrct) != prefsizey - 1) {
+ region->flag |= RGN_FLAG_SIZE_CLAMP_Y;
}
/* We need to use a test that wont have been previously clamped. */
rcti winrct_test = {
- .xmin = ar->winrct.xmin,
- .ymin = ar->winrct.ymin,
- .xmax = ar->winrct.xmin + size_min[0],
- .ymax = ar->winrct.ymin + size_min[1],
+ .xmin = region->winrct.xmin,
+ .ymin = region->winrct.ymin,
+ .xmax = region->winrct.xmin + size_min[0],
+ .ymax = region->winrct.ymin + size_min[1],
};
BLI_rcti_isect(&winrct_test, &overlap_remainder_margin, &winrct_test);
if (BLI_rcti_size_x(&winrct_test) < size_min[0] ||
BLI_rcti_size_y(&winrct_test) < size_min[1]) {
- ar->flag |= RGN_FLAG_TOO_SMALL;
+ region->flag |= RGN_FLAG_TOO_SMALL;
}
}
else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) {
/* remainder is too small for any usage */
- ar->flag |= RGN_FLAG_TOO_SMALL;
+ region->flag |= RGN_FLAG_TOO_SMALL;
}
else if (alignment == RGN_ALIGN_NONE) {
/* typically last region */
- ar->winrct = *remainder;
+ region->winrct = *remainder;
BLI_rcti_init(remainder, 0, 0, 0, 0);
}
else if (alignment == RGN_ALIGN_TOP || alignment == RGN_ALIGN_BOTTOM) {
- rcti *winrct = (ar->overlap) ? overlap_remainder : remainder;
+ rcti *winrct = (region->overlap) ? overlap_remainder : remainder;
if ((prefsizey == 0) || (rct_fits(winrct, 'v', prefsizey) < 0)) {
- ar->flag |= RGN_FLAG_TOO_SMALL;
+ region->flag |= RGN_FLAG_TOO_SMALL;
}
else {
int fac = rct_fits(winrct, 'v', prefsizey);
@@ -1350,23 +1376,24 @@ static void region_rect_recursive(
prefsizey += fac;
}
- ar->winrct = *winrct;
+ region->winrct = *winrct;
if (alignment == RGN_ALIGN_TOP) {
- ar->winrct.ymin = ar->winrct.ymax - prefsizey + 1;
- winrct->ymax = ar->winrct.ymin - 1;
+ region->winrct.ymin = region->winrct.ymax - prefsizey + 1;
+ winrct->ymax = region->winrct.ymin - 1;
}
else {
- ar->winrct.ymax = ar->winrct.ymin + prefsizey - 1;
- winrct->ymin = ar->winrct.ymax + 1;
+ region->winrct.ymax = region->winrct.ymin + prefsizey - 1;
+ winrct->ymin = region->winrct.ymax + 1;
}
+ BLI_rcti_sanitize(winrct);
}
}
else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
- rcti *winrct = (ar->overlap) ? overlap_remainder : remainder;
+ rcti *winrct = (region->overlap) ? overlap_remainder : remainder;
if ((prefsizex == 0) || (rct_fits(winrct, 'h', prefsizex) < 0)) {
- ar->flag |= RGN_FLAG_TOO_SMALL;
+ region->flag |= RGN_FLAG_TOO_SMALL;
}
else {
int fac = rct_fits(winrct, 'h', prefsizex);
@@ -1375,26 +1402,27 @@ static void region_rect_recursive(
prefsizex += fac;
}
- ar->winrct = *winrct;
+ region->winrct = *winrct;
if (alignment == RGN_ALIGN_RIGHT) {
- ar->winrct.xmin = ar->winrct.xmax - prefsizex + 1;
- winrct->xmax = ar->winrct.xmin - 1;
+ region->winrct.xmin = region->winrct.xmax - prefsizex + 1;
+ winrct->xmax = region->winrct.xmin - 1;
}
else {
- ar->winrct.xmax = ar->winrct.xmin + prefsizex - 1;
- winrct->xmin = ar->winrct.xmax + 1;
+ region->winrct.xmax = region->winrct.xmin + prefsizex - 1;
+ winrct->xmin = region->winrct.xmax + 1;
}
+ BLI_rcti_sanitize(winrct);
}
}
else if (alignment == RGN_ALIGN_VSPLIT || alignment == RGN_ALIGN_HSPLIT) {
/* percentage subdiv*/
- ar->winrct = *remainder;
+ region->winrct = *remainder;
if (alignment == RGN_ALIGN_HSPLIT) {
if (rct_fits(remainder, 'h', prefsizex) > 4) {
- ar->winrct.xmax = BLI_rcti_cent_x(remainder);
- remainder->xmin = ar->winrct.xmax + 1;
+ region->winrct.xmax = BLI_rcti_cent_x(remainder);
+ remainder->xmin = region->winrct.xmax + 1;
}
else {
BLI_rcti_init(remainder, 0, 0, 0, 0);
@@ -1402,8 +1430,8 @@ static void region_rect_recursive(
}
else {
if (rct_fits(remainder, 'v', prefsizey) > 4) {
- ar->winrct.ymax = BLI_rcti_cent_y(remainder);
- remainder->ymin = ar->winrct.ymax + 1;
+ region->winrct.ymax = BLI_rcti_cent_y(remainder);
+ remainder->ymin = region->winrct.ymax + 1;
}
else {
BLI_rcti_init(remainder, 0, 0, 0, 0);
@@ -1411,11 +1439,11 @@ static void region_rect_recursive(
}
}
else if (alignment == RGN_ALIGN_QSPLIT) {
- ar->winrct = *remainder;
+ region->winrct = *remainder;
/* test if there's still 4 regions left */
if (quad == 0) {
- ARegion *artest = ar->next;
+ ARegion *artest = region->next;
int count = 1;
while (artest) {
@@ -1437,168 +1465,168 @@ static void region_rect_recursive(
}
if (quad) {
if (quad == 1) { /* left bottom */
- ar->winrct.xmax = BLI_rcti_cent_x(remainder);
- ar->winrct.ymax = BLI_rcti_cent_y(remainder);
+ region->winrct.xmax = BLI_rcti_cent_x(remainder);
+ region->winrct.ymax = BLI_rcti_cent_y(remainder);
}
else if (quad == 2) { /* left top */
- ar->winrct.xmax = BLI_rcti_cent_x(remainder);
- ar->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
+ region->winrct.xmax = BLI_rcti_cent_x(remainder);
+ region->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
}
else if (quad == 3) { /* right bottom */
- ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
- ar->winrct.ymax = BLI_rcti_cent_y(remainder);
+ region->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
+ region->winrct.ymax = BLI_rcti_cent_y(remainder);
}
else { /* right top */
- ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
- ar->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
+ region->winrct.xmin = BLI_rcti_cent_x(remainder) + 1;
+ region->winrct.ymin = BLI_rcti_cent_y(remainder) + 1;
BLI_rcti_init(remainder, 0, 0, 0, 0);
}
/* Fix any negative dimensions. This can happen when a quad split 3d view gets to small. (see
* T72200). */
- BLI_rcti_sanitize(&ar->winrct);
+ BLI_rcti_sanitize(&region->winrct);
quad++;
}
}
/* for speedup */
- ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
- ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
+ region->winx = BLI_rcti_size_x(&region->winrct) + 1;
+ region->winy = BLI_rcti_size_y(&region->winrct) + 1;
/* if region opened normally, we store this for hide/reveal usage */
/* prevent rounding errors for UI_DPI_FAC mult and divide */
- if (ar->winx > 1) {
- ar->sizex = (ar->winx + 0.5f) / UI_DPI_FAC;
+ if (region->winx > 1) {
+ region->sizex = (region->winx + 0.5f) / UI_DPI_FAC;
}
- if (ar->winy > 1) {
- ar->sizey = (ar->winy + 0.5f) / UI_DPI_FAC;
+ if (region->winy > 1) {
+ region->sizey = (region->winy + 0.5f) / UI_DPI_FAC;
}
/* exception for multiple overlapping regions on same spot */
- if (ar->overlap && (alignment != RGN_ALIGN_FLOAT)) {
- region_overlap_fix(sa, ar);
+ if (region->overlap && (alignment != RGN_ALIGN_FLOAT)) {
+ region_overlap_fix(area, region);
}
/* set winrect for azones */
- if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
- ar->winrct = (ar->overlap) ? *overlap_remainder : *remainder;
+ if (region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
+ region->winrct = (region->overlap) ? *overlap_remainder : *remainder;
switch (alignment) {
case RGN_ALIGN_TOP:
- ar->winrct.ymin = ar->winrct.ymax;
+ region->winrct.ymin = region->winrct.ymax;
break;
case RGN_ALIGN_BOTTOM:
- ar->winrct.ymax = ar->winrct.ymin;
+ region->winrct.ymax = region->winrct.ymin;
break;
case RGN_ALIGN_RIGHT:
- ar->winrct.xmin = ar->winrct.xmax;
+ region->winrct.xmin = region->winrct.xmax;
break;
case RGN_ALIGN_LEFT:
- ar->winrct.xmax = ar->winrct.xmin;
+ region->winrct.xmax = region->winrct.xmin;
break;
default:
/* prevent winrct to be valid */
- ar->winrct.xmax = ar->winrct.xmin;
+ region->winrct.xmax = region->winrct.xmin;
break;
}
/* Size on one axis is now 0, the other axis may still be invalid (negative) though. */
- BLI_rcti_sanitize(&ar->winrct);
+ BLI_rcti_sanitize(&region->winrct);
}
/* restore prev-split exception */
- if (ar->alignment & RGN_SPLIT_PREV) {
- if (ar->prev) {
+ if (region->alignment & RGN_SPLIT_PREV) {
+ if (region->prev) {
remainder = remainder_prev;
- ar->prev->winx = BLI_rcti_size_x(&ar->prev->winrct) + 1;
- ar->prev->winy = BLI_rcti_size_y(&ar->prev->winrct) + 1;
+ region->prev->winx = BLI_rcti_size_x(&region->prev->winrct) + 1;
+ region->prev->winy = BLI_rcti_size_y(&region->prev->winrct) + 1;
}
}
/* After non-overlapping region, all following overlapping regions
* fit within the remaining space again. */
- if (!ar->overlap) {
+ if (!region->overlap) {
*overlap_remainder = *remainder;
}
- BLI_assert(BLI_rcti_is_valid(&ar->winrct));
+ BLI_assert(BLI_rcti_is_valid(&region->winrct));
- region_rect_recursive(sa, ar->next, remainder, overlap_remainder, quad);
+ region_rect_recursive(area, region->next, remainder, overlap_remainder, quad);
/* Tag for redraw if size changes. */
- if (ar->winx != prev_winx || ar->winy != prev_winy) {
- ED_region_tag_redraw(ar);
+ if (region->winx != prev_winx || region->winy != prev_winy) {
+ ED_region_tag_redraw(region);
}
/* Clear, initialize on demand. */
- memset(&ar->runtime.visible_rect, 0, sizeof(ar->runtime.visible_rect));
+ memset(&region->runtime.visible_rect, 0, sizeof(region->runtime.visible_rect));
}
-static void area_calc_totrct(ScrArea *sa, const rcti *window_rect)
+static void area_calc_totrct(ScrArea *area, const rcti *window_rect)
{
short px = (short)U.pixelsize;
- sa->totrct.xmin = sa->v1->vec.x;
- sa->totrct.xmax = sa->v4->vec.x;
- sa->totrct.ymin = sa->v1->vec.y;
- sa->totrct.ymax = sa->v2->vec.y;
+ area->totrct.xmin = area->v1->vec.x;
+ area->totrct.xmax = area->v4->vec.x;
+ area->totrct.ymin = area->v1->vec.y;
+ area->totrct.ymax = area->v2->vec.y;
/* scale down totrct by 1 pixel on all sides not matching window borders */
- if (sa->totrct.xmin > window_rect->xmin) {
- sa->totrct.xmin += px;
+ if (area->totrct.xmin > window_rect->xmin) {
+ area->totrct.xmin += px;
}
- if (sa->totrct.xmax < (window_rect->xmax - 1)) {
- sa->totrct.xmax -= px;
+ if (area->totrct.xmax < (window_rect->xmax - 1)) {
+ area->totrct.xmax -= px;
}
- if (sa->totrct.ymin > window_rect->ymin) {
- sa->totrct.ymin += px;
+ if (area->totrct.ymin > window_rect->ymin) {
+ area->totrct.ymin += px;
}
- if (sa->totrct.ymax < (window_rect->ymax - 1)) {
- sa->totrct.ymax -= px;
+ if (area->totrct.ymax < (window_rect->ymax - 1)) {
+ area->totrct.ymax -= px;
}
/* Although the following asserts are correct they lead to a very unstable Blender.
* And the asserts would fail even in 2.7x
* (they were added in 2.8x as part of the top-bar commit).
* For more details see T54864. */
#if 0
- BLI_assert(sa->totrct.xmin >= 0);
- BLI_assert(sa->totrct.xmax >= 0);
- BLI_assert(sa->totrct.ymin >= 0);
- BLI_assert(sa->totrct.ymax >= 0);
+ BLI_assert(area->totrct.xmin >= 0);
+ BLI_assert(area->totrct.xmax >= 0);
+ BLI_assert(area->totrct.ymin >= 0);
+ BLI_assert(area->totrct.ymax >= 0);
#endif
/* for speedup */
- sa->winx = BLI_rcti_size_x(&sa->totrct) + 1;
- sa->winy = BLI_rcti_size_y(&sa->totrct) + 1;
+ area->winx = BLI_rcti_size_x(&area->totrct) + 1;
+ area->winy = BLI_rcti_size_y(&area->totrct) + 1;
}
/* used for area initialize below */
-static void region_subwindow(ARegion *ar)
+static void region_subwindow(ARegion *region)
{
- bool hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) != 0;
+ bool hidden = (region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) != 0;
- if ((ar->alignment & RGN_SPLIT_PREV) && ar->prev) {
- hidden = hidden || (ar->prev->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
+ if ((region->alignment & RGN_SPLIT_PREV) && region->prev) {
+ hidden = hidden || (region->prev->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
}
- ar->visible = !hidden;
+ region->visible = !hidden;
}
-static bool event_in_markers_region(const ARegion *ar, const wmEvent *event)
+static bool event_in_markers_region(const ARegion *region, const wmEvent *event)
{
- rcti rect = ar->winrct;
+ rcti rect = region->winrct;
rect.ymax = rect.ymin + UI_MARKER_MARGIN_Y;
return BLI_rcti_isect_pt(&rect, event->x, event->y);
}
/**
- * \param ar: Region, may be NULL when adding handlers for \a sa.
+ * \param region: Region, may be NULL when adding handlers for \a area.
*/
static void ed_default_handlers(
- wmWindowManager *wm, ScrArea *sa, ARegion *ar, ListBase *handlers, int flag)
+ wmWindowManager *wm, ScrArea *area, ARegion *region, ListBase *handlers, int flag)
{
- BLI_assert(ar ? (&ar->handlers == handlers) : (&sa->handlers == handlers));
+ BLI_assert(region ? (&region->handlers == handlers) : (&area->handlers == handlers));
/* note, add-handler checks if it already exists */
@@ -1611,15 +1639,15 @@ static void ed_default_handlers(
UI_region_handlers_add(handlers);
}
if (flag & ED_KEYMAP_GIZMO) {
- BLI_assert(ar && ELEM(ar->type->regionid, RGN_TYPE_WINDOW, RGN_TYPE_PREVIEW));
- if (ar) {
+ BLI_assert(region && ELEM(region->type->regionid, RGN_TYPE_WINDOW, RGN_TYPE_PREVIEW));
+ if (region) {
/* Anything else is confusing, only allow this. */
- BLI_assert(&ar->handlers == handlers);
- if (ar->gizmo_map == NULL) {
- ar->gizmo_map = WM_gizmomap_new_from_type(
- &(const struct wmGizmoMapType_Params){sa->spacetype, ar->type->regionid});
+ BLI_assert(&region->handlers == handlers);
+ if (region->gizmo_map == NULL) {
+ region->gizmo_map = WM_gizmomap_new_from_type(
+ &(const struct wmGizmoMapType_Params){area->spacetype, region->type->regionid});
}
- WM_gizmomap_add_handlers(ar, ar->gizmo_map);
+ WM_gizmomap_add_handlers(region, region->gizmo_map);
}
}
if (flag & ED_KEYMAP_VIEW2D) {
@@ -1644,8 +1672,9 @@ static void ed_default_handlers(
}
if (flag & ED_KEYMAP_TOOL) {
WM_event_add_keymap_handler_dynamic(
- &ar->handlers, WM_event_get_keymap_from_toolsystem_fallback, sa);
- WM_event_add_keymap_handler_dynamic(&ar->handlers, WM_event_get_keymap_from_toolsystem, sa);
+ &region->handlers, WM_event_get_keymap_from_toolsystem_fallback, area);
+ WM_event_add_keymap_handler_dynamic(
+ &region->handlers, WM_event_get_keymap_from_toolsystem, area);
}
if (flag & ED_KEYMAP_FRAMES) {
/* frame changing/jumping (for all spaces) */
@@ -1665,7 +1694,7 @@ static void ed_default_handlers(
if (flag & ED_KEYMAP_NAVBAR) {
/* standard keymap for Navigation bar regions */
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
/* Keep last because of LMB/RMB handling, see: T57527. */
@@ -1700,9 +1729,81 @@ static void ed_default_handlers(
wm->defaultconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_paint_fill);
+ wmKeyMap *keymap_paint_tint = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Paint (Tint)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_paint_tint);
+
wmKeyMap *keymap_sculpt = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt);
+
+ wmKeyMap *keymap_vertex = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Vertex Mode", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_vertex);
+
+ wmKeyMap *keymap_vertex_draw = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Vertex (Draw)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_vertex_draw);
+
+ wmKeyMap *keymap_vertex_blur = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Vertex (Blur)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_vertex_blur);
+
+ wmKeyMap *keymap_vertex_average = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Vertex (Average)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_vertex_average);
+
+ wmKeyMap *keymap_vertex_smear = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Vertex (Smear)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_vertex_smear);
+
+ wmKeyMap *keymap_vertex_replace = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Vertex (Replace)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_vertex_replace);
+
+ wmKeyMap *keymap_sculpt_smooth = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt (Smooth)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt_smooth);
+
+ wmKeyMap *keymap_sculpt_thickness = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt (Thickness)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt_thickness);
+
+ wmKeyMap *keymap_sculpt_strength = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt (Strength)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt_strength);
+
+ wmKeyMap *keymap_sculpt_grab = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt (Grab)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt_grab);
+
+ wmKeyMap *keymap_sculpt_push = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt (Push)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt_push);
+
+ wmKeyMap *keymap_sculpt_twist = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt (Twist)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt_twist);
+
+ wmKeyMap *keymap_sculpt_pinch = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt (Pinch)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt_pinch);
+
+ wmKeyMap *keymap_sculpt_randomize = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt (Randomize)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt_randomize);
+
+ wmKeyMap *keymap_sculpt_clone = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Sculpt (Clone)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_sculpt_clone);
+
+ wmKeyMap *keymap_weight = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Weight Mode", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_weight);
+
+ wmKeyMap *keymap_weight_draw = WM_keymap_ensure(
+ wm->defaultconf, "Grease Pencil Stroke Weight (Draw)", 0, 0);
+ WM_event_add_keymap_handler(handlers, keymap_weight_draw);
}
}
@@ -1727,16 +1828,16 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar
/* Dynamically sized regions may have changed region sizes, so we have to force azone update. */
area_azone_initialize(win, screen, area);
- for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) {
- region_subwindow(ar);
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ region_subwindow(region);
/* region size may have changed, init does necessary adjustments */
- if (ar->type->init) {
- ar->type->init(wm, ar);
+ if (region->type->init) {
+ region->type->init(wm, region);
}
/* Some AZones use View2D data which is only updated in region init, so call that first! */
- region_azones_add(screen, area, ar);
+ region_azones_add(screen, area, region);
}
ED_area_azones_update(area, &win->eventstate->x);
@@ -1744,204 +1845,210 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar
}
/* called in screen_refresh, or screens_init, also area size changes */
-void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
+void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *area)
{
WorkSpace *workspace = WM_window_get_active_workspace(win);
const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
- ARegion *ar;
+ ARegion *region;
rcti rect, overlap_rect;
rcti window_rect;
- if (ED_area_is_global(sa) && (sa->global->flag & GLOBAL_AREA_IS_HIDDEN)) {
+ if (ED_area_is_global(area) && (area->global->flag & GLOBAL_AREA_IS_HIDDEN)) {
return;
}
WM_window_rect_calc(win, &window_rect);
/* set typedefinitions */
- sa->type = BKE_spacetype_from_id(sa->spacetype);
+ area->type = BKE_spacetype_from_id(area->spacetype);
- if (sa->type == NULL) {
- sa->spacetype = SPACE_VIEW3D;
- sa->type = BKE_spacetype_from_id(sa->spacetype);
+ if (area->type == NULL) {
+ area->spacetype = SPACE_VIEW3D;
+ area->type = BKE_spacetype_from_id(area->spacetype);
}
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- ar->type = BKE_regiontype_from_id_or_first(sa->type, ar->regiontype);
+ for (region = area->regionbase.first; region; region = region->next) {
+ region->type = BKE_regiontype_from_id_or_first(area->type, region->regiontype);
}
/* area sizes */
- area_calc_totrct(sa, &window_rect);
+ area_calc_totrct(area, &window_rect);
/* region rect sizes */
- rect = sa->totrct;
+ rect = area->totrct;
overlap_rect = rect;
- region_rect_recursive(sa, sa->regionbase.first, &rect, &overlap_rect, 0);
- sa->flag &= ~AREA_FLAG_REGION_SIZE_UPDATE;
+ region_rect_recursive(area, area->regionbase.first, &rect, &overlap_rect, 0);
+ area->flag &= ~AREA_FLAG_REGION_SIZE_UPDATE;
/* default area handlers */
- ed_default_handlers(wm, sa, NULL, &sa->handlers, sa->type->keymapflag);
+ ed_default_handlers(wm, area, NULL, &area->handlers, area->type->keymapflag);
/* checks spacedata, adds own handlers */
- if (sa->type->init) {
- sa->type->init(wm, sa);
+ if (area->type->init) {
+ area->type->init(wm, area);
}
/* clear all azones, add the area triangle widgets */
- area_azone_initialize(win, screen, sa);
+ area_azone_initialize(win, screen, area);
/* region windows, default and own handlers */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- region_subwindow(ar);
+ for (region = area->regionbase.first; region; region = region->next) {
+ region_subwindow(region);
- if (ar->visible) {
+ if (region->visible) {
/* default region handlers */
- ed_default_handlers(wm, sa, ar, &ar->handlers, ar->type->keymapflag);
+ ed_default_handlers(wm, area, region, &region->handlers, region->type->keymapflag);
/* own handlers */
- if (ar->type->init) {
- ar->type->init(wm, ar);
+ if (region->type->init) {
+ region->type->init(wm, region);
}
}
else {
/* prevent uiblocks to run */
- UI_blocklist_free(NULL, &ar->uiblocks);
+ UI_blocklist_free(NULL, &region->uiblocks);
}
/* Some AZones use View2D data which is only updated in region init, so call that first! */
- region_azones_add(screen, sa, ar);
+ region_azones_add(screen, area, region);
}
/* Avoid re-initializing tools while resizing the window. */
if ((G.moving & G_TRANSFORM_WM) == 0) {
- if ((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) {
- WM_toolsystem_refresh_screen_area(workspace, view_layer, sa);
- sa->flag |= AREA_FLAG_ACTIVE_TOOL_UPDATE;
+ if ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) {
+ WM_toolsystem_refresh_screen_area(workspace, view_layer, area);
+ area->flag |= AREA_FLAG_ACTIVE_TOOL_UPDATE;
}
else {
- sa->runtime.tool = NULL;
- sa->runtime.is_tool_set = true;
+ area->runtime.tool = NULL;
+ area->runtime.is_tool_set = true;
}
}
}
-static void region_update_rect(ARegion *ar)
+static void region_update_rect(ARegion *region)
{
- ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
- ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
+ region->winx = BLI_rcti_size_x(&region->winrct) + 1;
+ region->winy = BLI_rcti_size_y(&region->winrct) + 1;
/* v2d mask is used to subtract scrollbars from a 2d view. Needs initialize here. */
- BLI_rcti_init(&ar->v2d.mask, 0, ar->winx - 1, 0, ar->winy - 1);
+ BLI_rcti_init(&region->v2d.mask, 0, region->winx - 1, 0, region->winy - 1);
}
/**
* Call to move a popup window (keep OpenGL context free!)
*/
-void ED_region_update_rect(ARegion *ar)
+void ED_region_update_rect(ARegion *region)
{
- region_update_rect(ar);
+ region_update_rect(region);
}
/* externally called for floating regions like menus */
-void ED_region_floating_initialize(ARegion *ar)
+void ED_region_floating_initialize(ARegion *region)
{
- BLI_assert(ar->alignment == RGN_ALIGN_FLOAT);
+ BLI_assert(region->alignment == RGN_ALIGN_FLOAT);
/* refresh can be called before window opened */
- region_subwindow(ar);
+ region_subwindow(region);
- region_update_rect(ar);
+ region_update_rect(region);
}
-void ED_region_cursor_set(wmWindow *win, ScrArea *sa, ARegion *ar)
+void ED_region_cursor_set(wmWindow *win, ScrArea *area, ARegion *region)
{
- if (ar && sa && ar->type && ar->type->cursor) {
- ar->type->cursor(win, sa, ar);
- }
- else {
- if (WM_cursor_set_from_tool(win, sa, ar)) {
+ if (region != NULL) {
+ if ((region->gizmo_map != NULL) && WM_gizmomap_cursor_set(region->gizmo_map, win)) {
return;
}
- WM_cursor_set(win, WM_CURSOR_DEFAULT);
+ if (area && region->type && region->type->cursor) {
+ region->type->cursor(win, area, region);
+ return;
+ }
+ }
+
+ if (WM_cursor_set_from_tool(win, area, region)) {
+ return;
}
+
+ WM_cursor_set(win, WM_CURSOR_DEFAULT);
}
/* for use after changing visibility of regions */
-void ED_region_visibility_change_update(bContext *C, ScrArea *sa, ARegion *ar)
+void ED_region_visibility_change_update(bContext *C, ScrArea *area, ARegion *region)
{
- if (ar->flag & RGN_FLAG_HIDDEN) {
- WM_event_remove_handlers(C, &ar->handlers);
+ if (region->flag & RGN_FLAG_HIDDEN) {
+ WM_event_remove_handlers(C, &region->handlers);
}
- ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
- ED_area_tag_redraw(sa);
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), area);
+ ED_area_tag_redraw(area);
}
/* for quick toggle, can skip fades */
-void region_toggle_hidden(bContext *C, ARegion *ar, const bool do_fade)
+void region_toggle_hidden(bContext *C, ARegion *region, const bool do_fade)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- ar->flag ^= RGN_FLAG_HIDDEN;
+ region->flag ^= RGN_FLAG_HIDDEN;
- if (do_fade && ar->overlap) {
+ if (do_fade && region->overlap) {
/* starts a timer, and in end calls the stuff below itself (region_sblend_invoke()) */
- ED_region_visibility_change_update_animated(C, sa, ar);
+ ED_region_visibility_change_update_animated(C, area, region);
}
else {
- ED_region_visibility_change_update(C, sa, ar);
+ ED_region_visibility_change_update(C, area, region);
}
}
/* exported to all editors, uses fading default */
-void ED_region_toggle_hidden(bContext *C, ARegion *ar)
+void ED_region_toggle_hidden(bContext *C, ARegion *region)
{
- region_toggle_hidden(C, ar, true);
+ region_toggle_hidden(C, region, true);
}
/**
* we swap spaces for fullscreen to keep all allocated data area vertices were set
*/
-void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free)
+void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, const bool do_free)
{
SpaceType *st;
- ARegion *ar;
- const char spacetype = sa_dst->spacetype;
+ ARegion *region;
+ const char spacetype = area_dst->spacetype;
const short flag_copy = HEADER_NO_PULLDOWN;
- sa_dst->spacetype = sa_src->spacetype;
- sa_dst->type = sa_src->type;
+ area_dst->spacetype = area_src->spacetype;
+ area_dst->type = area_src->type;
- sa_dst->flag = (sa_dst->flag & ~flag_copy) | (sa_src->flag & flag_copy);
+ area_dst->flag = (area_dst->flag & ~flag_copy) | (area_src->flag & flag_copy);
/* area */
if (do_free) {
- BKE_spacedata_freelist(&sa_dst->spacedata);
+ BKE_spacedata_freelist(&area_dst->spacedata);
}
- BKE_spacedata_copylist(&sa_dst->spacedata, &sa_src->spacedata);
+ BKE_spacedata_copylist(&area_dst->spacedata, &area_src->spacedata);
/* Note; SPACE_EMPTY is possible on new screens */
/* regions */
if (do_free) {
st = BKE_spacetype_from_id(spacetype);
- for (ar = sa_dst->regionbase.first; ar; ar = ar->next) {
- BKE_area_region_free(st, ar);
+ for (region = area_dst->regionbase.first; region; region = region->next) {
+ BKE_area_region_free(st, region);
}
- BLI_freelistN(&sa_dst->regionbase);
+ BLI_freelistN(&area_dst->regionbase);
}
- st = BKE_spacetype_from_id(sa_src->spacetype);
- for (ar = sa_src->regionbase.first; ar; ar = ar->next) {
- ARegion *newar = BKE_area_region_copy(st, ar);
- BLI_addtail(&sa_dst->regionbase, newar);
+ st = BKE_spacetype_from_id(area_src->spacetype);
+ for (region = area_src->regionbase.first; region; region = region->next) {
+ ARegion *newar = BKE_area_region_copy(st, region);
+ BLI_addtail(&area_dst->regionbase, newar);
}
}
-void ED_area_data_swap(ScrArea *sa_dst, ScrArea *sa_src)
+void ED_area_data_swap(ScrArea *area_dst, ScrArea *area_src)
{
- SWAP(char, sa_dst->spacetype, sa_src->spacetype);
- SWAP(SpaceType *, sa_dst->type, sa_src->type);
+ SWAP(char, area_dst->spacetype, area_src->spacetype);
+ SWAP(SpaceType *, area_dst->type, area_src->type);
- SWAP(ListBase, sa_dst->spacedata, sa_src->spacedata);
- SWAP(ListBase, sa_dst->regionbase, sa_src->regionbase);
+ SWAP(ListBase, area_dst->spacedata, area_src->spacedata);
+ SWAP(ListBase, area_dst->regionbase, area_src->regionbase);
}
/* *********** Space switching code *********** */
@@ -1949,6 +2056,7 @@ void ED_area_data_swap(ScrArea *sa_dst, ScrArea *sa_src)
void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
{
ScrArea *tmp = MEM_callocN(sizeof(ScrArea), "addscrarea");
+ wmWindow *win = CTX_wm_window(C);
ED_area_exit(C, sa1);
ED_area_exit(C, sa2);
@@ -1956,14 +2064,14 @@ void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
ED_area_data_copy(tmp, sa1, false);
ED_area_data_copy(sa1, sa2, true);
ED_area_data_copy(sa2, tmp, true);
- ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa1);
- ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa2);
+ ED_area_initialize(CTX_wm_manager(C), win, sa1);
+ ED_area_initialize(CTX_wm_manager(C), win, sa2);
BKE_screen_area_free(tmp);
MEM_freeN(tmp);
/* tell WM to refresh, cursor types etc */
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(win);
ED_area_tag_redraw(sa1);
ED_area_tag_refresh(sa1);
@@ -1972,18 +2080,18 @@ void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
}
/**
- * \param skip_ar_exit: Skip calling area exit callback. Set for opening temp spaces.
+ * \param skip_region_exit: Skip calling area exit callback. Set for opening temp spaces.
*/
-void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exit)
+void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_region_exit)
{
wmWindow *win = CTX_wm_window(C);
- if (sa->spacetype != type) {
+ if (area->spacetype != type) {
SpaceType *st;
- SpaceLink *slold = sa->spacedata.first;
+ SpaceLink *slold = area->spacedata.first;
SpaceLink *sl;
- /* store sa->type->exit callback */
- void *sa_exit = sa->type ? sa->type->exit : NULL;
+ /* store area->type->exit callback */
+ void *area_exit = area->type ? area->type->exit : NULL;
/* When the user switches between space-types from the type-selector,
* changing the header-type is jarring (especially when using Ctrl-MouseWheel).
*
@@ -1994,34 +2102,34 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi
* the space type defaults to in this case instead
* (needed for preferences to have space-type on bottom).
*/
- int header_alignment = ED_area_header_alignment_or_fallback(sa, -1);
+ int header_alignment = ED_area_header_alignment_or_fallback(area, -1);
const bool sync_header_alignment = ((header_alignment != -1) &&
((slold->link_flag & SPACE_FLAG_TYPE_TEMPORARY) == 0));
/* in some cases (opening temp space) we don't want to
* call area exit callback, so we temporarily unset it */
- if (skip_ar_exit && sa->type) {
- sa->type->exit = NULL;
+ if (skip_region_exit && area->type) {
+ area->type->exit = NULL;
}
- ED_area_exit(C, sa);
+ ED_area_exit(C, area);
/* restore old area exit callback */
- if (skip_ar_exit && sa->type) {
- sa->type->exit = sa_exit;
+ if (skip_region_exit && area->type) {
+ area->type->exit = area_exit;
}
st = BKE_spacetype_from_id(type);
- sa->spacetype = type;
- sa->type = st;
+ area->spacetype = type;
+ area->type = st;
/* If st->new may be called, don't use context until then. The
- * sa->type->context() callback has changed but data may be invalid
+ * area->type->context() callback has changed but data may be invalid
* (e.g. with properties editor) until space-data is properly created */
/* check previously stored space */
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ for (sl = area->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == type) {
break;
}
@@ -2030,7 +2138,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi
/* old spacedata... happened during work on 2.50, remove */
if (sl && BLI_listbase_is_empty(&sl->regionbase)) {
st->free(sl);
- BLI_freelinkN(&sa->spacedata, sl);
+ BLI_freelinkN(&area->spacedata, sl);
if (slold == sl) {
slold = NULL;
}
@@ -2039,8 +2147,8 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi
if (sl) {
/* swap regions */
- slold->regionbase = sa->regionbase;
- sa->regionbase = sl->regionbase;
+ slold->regionbase = area->regionbase;
+ area->regionbase = sl->regionbase;
BLI_listbase_clear(&sl->regionbase);
/* SPACE_FLAG_TYPE_WAS_ACTIVE is only used to go back to a previously active space that is
* overlapped by temporary ones. It's now properly activated, so the flag should be cleared
@@ -2048,22 +2156,22 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi
sl->link_flag &= ~SPACE_FLAG_TYPE_WAS_ACTIVE;
/* put in front of list */
- BLI_remlink(&sa->spacedata, sl);
- BLI_addhead(&sa->spacedata, sl);
+ BLI_remlink(&area->spacedata, sl);
+ BLI_addhead(&area->spacedata, sl);
}
else {
/* new space */
if (st) {
/* Don't get scene from context here which may depend on space-data. */
Scene *scene = WM_window_get_active_scene(win);
- sl = st->new (sa, scene);
- BLI_addhead(&sa->spacedata, sl);
+ sl = st->new (area, scene);
+ BLI_addhead(&area->spacedata, sl);
/* swap regions */
if (slold) {
- slold->regionbase = sa->regionbase;
+ slold->regionbase = area->regionbase;
}
- sa->regionbase = sl->regionbase;
+ area->regionbase = sl->regionbase;
BLI_listbase_clear(&sl->regionbase);
}
}
@@ -2072,46 +2180,46 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi
if (sync_header_alignment) {
/* Spaces with footer. */
if (st->spaceid == SPACE_TEXT) {
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
- ar->alignment = header_alignment;
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ region->alignment = header_alignment;
}
- if (ar->regiontype == RGN_TYPE_FOOTER) {
+ if (region->regiontype == RGN_TYPE_FOOTER) {
int footer_alignment = (header_alignment == RGN_ALIGN_BOTTOM) ? RGN_ALIGN_TOP :
RGN_ALIGN_BOTTOM;
- ar->alignment = footer_alignment;
+ region->alignment = footer_alignment;
break;
}
}
}
else {
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
- ar->alignment = header_alignment;
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ region->alignment = header_alignment;
break;
}
}
}
}
- ED_area_initialize(CTX_wm_manager(C), win, sa);
+ ED_area_initialize(CTX_wm_manager(C), win, area);
/* tell WM to refresh, cursor types etc */
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(win);
/* send space change notifier */
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, sa);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, area);
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
/* also redraw when re-used */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
-static SpaceLink *area_get_prevspace(ScrArea *sa)
+static SpaceLink *area_get_prevspace(ScrArea *area)
{
- SpaceLink *sl = sa->spacedata.first;
+ SpaceLink *sl = area->spacedata.first;
/* First toggle to the next temporary space in the list. */
for (SpaceLink *sl_iter = sl->next; sl_iter; sl_iter = sl_iter->next) {
@@ -2131,13 +2239,13 @@ static SpaceLink *area_get_prevspace(ScrArea *sa)
return sl->next;
}
-void ED_area_prevspace(bContext *C, ScrArea *sa)
+void ED_area_prevspace(bContext *C, ScrArea *area)
{
- SpaceLink *sl = sa->spacedata.first;
- SpaceLink *prevspace = sl ? area_get_prevspace(sa) : NULL;
+ SpaceLink *sl = area->spacedata.first;
+ SpaceLink *prevspace = sl ? area_get_prevspace(area) : NULL;
if (prevspace) {
- ED_area_newspace(C, sa, prevspace->spacetype, false);
+ ED_area_newspace(C, area, prevspace->spacetype, false);
/* We've exited the space, so it can't be considered temporary anymore. */
sl->link_flag &= ~SPACE_FLAG_TYPE_TEMPORARY;
}
@@ -2147,23 +2255,23 @@ void ED_area_prevspace(bContext *C, ScrArea *sa)
}
/* If this is a stacked fullscreen, changing to previous area exits it (meaning we're still in a
* fullscreen, but not in a stacked one). */
- sa->flag &= ~AREA_FLAG_STACKED_FULLSCREEN;
+ area->flag &= ~AREA_FLAG_STACKED_FULLSCREEN;
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
/* send space change notifier */
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, sa);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CHANGED, area);
}
/* returns offset for next button in header */
int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
{
- ScrArea *sa = CTX_wm_area(C);
- bScreen *scr = CTX_wm_screen(C);
+ ScrArea *area = CTX_wm_area(C);
+ bScreen *screen = CTX_wm_screen(C);
PointerRNA areaptr;
int xco = 0.4 * U.widget_unit;
- RNA_pointer_create(&(scr->id), &RNA_Area, sa, &areaptr);
+ RNA_pointer_create(&(screen->id), &RNA_Area, area, &areaptr);
uiDefButR(block,
UI_BTYPE_MENU,
@@ -2207,12 +2315,12 @@ static ThemeColorID region_background_color_id(const bContext *C, const ARegion
}
}
-static void region_clear_color(const bContext *C, const ARegion *ar, ThemeColorID colorid)
+static void region_clear_color(const bContext *C, const ARegion *region, ThemeColorID colorid)
{
- if (ar->alignment == RGN_ALIGN_FLOAT) {
+ if (region->alignment == RGN_ALIGN_FLOAT) {
/* handle our own drawing. */
}
- else if (ar->overlap) {
+ else if (region->overlap) {
/* view should be in pixelspace */
UI_view2d_view_restore(C);
@@ -2238,8 +2346,8 @@ BLI_INLINE bool streq_array_any(const char *s, const char *arr[])
}
static void ed_panel_draw(const bContext *C,
- ScrArea *sa,
- ARegion *ar,
+ ScrArea *area,
+ ARegion *region,
ListBase *lb,
PanelType *pt,
Panel *panel,
@@ -2247,13 +2355,13 @@ static void ed_panel_draw(const bContext *C,
int em,
bool vertical)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
/* draw panel */
- uiBlock *block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, region, pt->idname, UI_EMBOSS);
bool open;
- panel = UI_panel_begin(sa, ar, lb, block, pt, panel, &open);
+ panel = UI_panel_begin(area, region, lb, block, pt, panel, &open);
/* bad fixed values */
int xco, yco, h = 0;
@@ -2304,7 +2412,7 @@ static void ed_panel_draw(const bContext *C,
if (pt->flag & PNL_LAYOUT_VERT_BAR) {
panelContext = UI_LAYOUT_VERT_BAR;
}
- else if (ar->regiontype == RGN_TYPE_TOOLS) {
+ else if (region->regiontype == RGN_TYPE_TOOLS) {
panelContext = UI_LAYOUT_TOOLBAR;
}
else {
@@ -2336,17 +2444,17 @@ static void ed_panel_draw(const bContext *C,
/* Draw child panels. */
if (open) {
- for (LinkData *link = pt->children.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &pt->children) {
PanelType *child_pt = link->data;
Panel *child_panel = UI_panel_find_by_type(&panel->children, child_pt);
if (child_pt->draw && (!child_pt->poll || child_pt->poll(C, child_pt))) {
- ed_panel_draw(C, sa, ar, &panel->children, child_pt, child_panel, w, em, vertical);
+ ed_panel_draw(C, area, region, &panel->children, child_pt, child_panel, w, em, vertical);
}
}
}
- UI_panel_end(sa, ar, block, w, h, open);
+ UI_panel_end(area, region, block, w, h, open);
}
/**
@@ -2355,7 +2463,7 @@ static void ed_panel_draw(const bContext *C,
* Can be NULL to skip context checks.
*/
void ED_region_panels_layout_ex(const bContext *C,
- ARegion *ar,
+ ARegion *region,
ListBase *paneltypes,
const char *contexts[],
int contextnr,
@@ -2393,23 +2501,25 @@ void ED_region_panels_layout_ex(const bContext *C,
}
}
- ar->runtime.category = NULL;
+ region->runtime.category = NULL;
- ScrArea *sa = CTX_wm_area(C);
- View2D *v2d = &ar->v2d;
+ ScrArea *area = CTX_wm_area(C);
+ View2D *v2d = &region->v2d;
int x, y, w, em;
/* XXX, should use some better check? */
/* For now also has hardcoded check for clip editor until it supports actual toolbar. */
bool use_category_tabs = (category_override == NULL) &&
- ((((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
- (ar->regiontype == RGN_TYPE_TOOLS && sa->spacetype == SPACE_CLIP)));
+ ((((1 << region->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
+ (region->regiontype == RGN_TYPE_TOOLS &&
+ area->spacetype == SPACE_CLIP)));
/* offset panels for small vertical tab area */
const char *category = NULL;
const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH;
int margin_x = 0;
- const bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE;
+ const bool region_layout_based = region->flag & RGN_FLAG_DYNAMIC_SIZE;
const bool is_context_new = (contextnr != -1) ? UI_view2d_tab_set(v2d, contextnr) : false;
+ bool update_tot_size = true;
/* before setting the view */
if (vertical) {
@@ -2427,51 +2537,50 @@ void ED_region_panels_layout_ex(const bContext *C,
v2d->scroll |= (V2D_SCROLL_BOTTOM);
v2d->scroll &= ~(V2D_SCROLL_RIGHT);
}
- const int scroll = v2d->scroll;
/* collect categories */
if (use_category_tabs) {
- UI_panel_category_clear_all(ar);
+ UI_panel_category_clear_all(region);
/* gather unique categories */
for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
PanelType *pt = pt_link->link;
if (pt->category[0]) {
- if (!UI_panel_category_find(ar, pt->category)) {
- UI_panel_category_add(ar, pt->category);
+ if (!UI_panel_category_find(region, pt->category)) {
+ UI_panel_category_add(region, pt->category);
}
}
}
- if (!UI_panel_category_is_visible(ar)) {
+ if (!UI_panel_category_is_visible(region)) {
use_category_tabs = false;
}
else {
- category = UI_panel_category_active_get(ar, true);
+ category = UI_panel_category_active_get(region, true);
margin_x = category_tabs_width;
}
}
if (vertical) {
w = BLI_rctf_size_x(&v2d->cur);
- em = (ar->type->prefsizex) ? 10 : 20; /* works out to 10*UI_UNIT_X or 20*UI_UNIT_X */
+ em = (region->type->prefsizex) ? 10 : 20; /* works out to 10*UI_UNIT_X or 20*UI_UNIT_X */
}
else {
w = UI_PANEL_WIDTH;
- em = (ar->type->prefsizex) ? 10 : 20;
+ em = (region->type->prefsizex) ? 10 : 20;
}
w -= margin_x;
/* create panels */
- UI_panels_begin(C, ar);
+ UI_panels_begin(C, region);
/* set view2d view matrix - UI_block_begin() stores it */
UI_view2d_view_ortho(v2d);
for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
PanelType *pt = pt_link->link;
- Panel *panel = UI_panel_find_by_type(&ar->panels, pt);
+ Panel *panel = UI_panel_find_by_type(&region->panels, pt);
if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
@@ -2479,30 +2588,35 @@ void ED_region_panels_layout_ex(const bContext *C,
}
}
- ed_panel_draw(C, sa, ar, &ar->panels, pt, panel, w, em, vertical);
+ if (panel && UI_panel_is_dragging(panel)) {
+ /* Prevent View2d.tot rectangle size changes while dragging panels. */
+ update_tot_size = false;
+ }
+
+ ed_panel_draw(C, area, region, &region->panels, pt, panel, w, em, vertical);
}
/* align panels and return size */
- UI_panels_end(C, ar, &x, &y);
+ UI_panels_end(C, region, &x, &y);
/* before setting the view */
if (region_layout_based) {
/* XXX, only single panel support atm.
* Can't use x/y values calculated above because they're not using the real height of panels,
* instead they calculate offsets for the next panel to start drawing. */
- Panel *panel = ar->panels.last;
+ Panel *panel = region->panels.last;
if (panel != NULL) {
const int size_dyn[2] = {
UI_UNIT_X * ((panel->flag & PNL_CLOSED) ? 8 : 14) / UI_DPI_FAC,
UI_panel_size_y(panel) / UI_DPI_FAC,
};
/* region size is layout based and needs to be updated */
- if ((ar->sizex != size_dyn[0]) || (ar->sizey != size_dyn[1])) {
- ar->sizex = size_dyn[0];
- ar->sizey = size_dyn[1];
- sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ if ((region->sizex != size_dyn[0]) || (region->sizey != size_dyn[1])) {
+ region->sizex = size_dyn[0];
+ region->sizey = size_dyn[1];
+ area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
}
- y = ABS(ar->sizey * UI_DPI_FAC - 1);
+ y = fabsf(region->sizey * UI_DPI_FAC - 1);
}
}
else if (vertical) {
@@ -2534,37 +2648,29 @@ void ED_region_panels_layout_ex(const bContext *C,
y = -y;
}
- /* this also changes the 'cur' */
- UI_view2d_totRect_set(v2d, x, y);
-
- if (scroll != v2d->scroll) {
- /* Note: this code scales fine, but because of rounding differences, positions of elements
- * flip +1 or -1 pixel compared to redoing the entire layout again.
- * Leaving in commented code for future tests */
-#if 0
- UI_panels_scale(ar, BLI_rctf_size_x(&v2d->cur));
- break;
-#endif
+ if (update_tot_size) {
+ /* this also changes the 'cur' */
+ UI_view2d_totRect_set(v2d, x, y);
}
if (use_category_tabs) {
- ar->runtime.category = category;
+ region->runtime.category = category;
}
}
-void ED_region_panels_layout(const bContext *C, ARegion *ar)
+void ED_region_panels_layout(const bContext *C, ARegion *region)
{
bool vertical = true;
- ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, NULL, -1, vertical, NULL);
+ ED_region_panels_layout_ex(C, region, &region->type->paneltypes, NULL, -1, vertical, NULL);
}
-void ED_region_panels_draw(const bContext *C, ARegion *ar)
+void ED_region_panels_draw(const bContext *C, ARegion *region)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
- if (ar->alignment != RGN_ALIGN_FLOAT) {
+ if (region->alignment != RGN_ALIGN_FLOAT) {
region_clear_color(
- C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
+ C, region, (region->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
}
/* reset line width for drawing tabs */
@@ -2574,23 +2680,24 @@ void ED_region_panels_draw(const bContext *C, ARegion *ar)
UI_view2d_view_ortho(v2d);
/* View2D matrix might have changed due to dynamic sized regions. */
- UI_blocklist_update_window_matrix(C, &ar->uiblocks);
+ UI_blocklist_update_window_matrix(C, &region->uiblocks);
/* draw panels */
- UI_panels_draw(C, ar);
+ UI_panels_draw(C, region);
/* restore view matrix */
UI_view2d_view_restore(C);
/* Set in layout. */
- if (ar->runtime.category) {
- UI_panel_category_draw_all(ar, ar->runtime.category);
+ if (region->runtime.category) {
+ UI_panel_category_draw_all(region, region->runtime.category);
}
/* scrollers */
const rcti *mask = NULL;
rcti mask_buf;
- if (ar->runtime.category && (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_RIGHT)) {
+ if (region->runtime.category &&
+ (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_RIGHT)) {
UI_view2d_mask_from_win(v2d, &mask_buf);
mask_buf.xmax -= UI_PANEL_CATEGORY_MARGIN_WIDTH;
mask = &mask_buf;
@@ -2601,46 +2708,47 @@ void ED_region_panels_draw(const bContext *C, ARegion *ar)
}
void ED_region_panels_ex(
- const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical)
+ const bContext *C, ARegion *region, const char *contexts[], int contextnr, const bool vertical)
{
/* TODO: remove? */
- ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts, contextnr, vertical, NULL);
- ED_region_panels_draw(C, ar);
+ ED_region_panels_layout_ex(
+ C, region, &region->type->paneltypes, contexts, contextnr, vertical, NULL);
+ ED_region_panels_draw(C, region);
}
-void ED_region_panels(const bContext *C, ARegion *ar)
+void ED_region_panels(const bContext *C, ARegion *region)
{
/* TODO: remove? */
- ED_region_panels_layout(C, ar);
- ED_region_panels_draw(C, ar);
+ ED_region_panels_layout(C, region);
+ ED_region_panels_draw(C, region);
}
-void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
+void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_PANELS_UI, region->winx, region->winy);
keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-void ED_region_header_layout(const bContext *C, ARegion *ar)
+void ED_region_header_layout(const bContext *C, ARegion *region)
{
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
uiBlock *block;
uiLayout *layout;
HeaderType *ht;
Header header = {NULL};
- bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE;
+ bool region_layout_based = region->flag & RGN_FLAG_DYNAMIC_SIZE;
/* Height of buttons and scaling needed to achieve it. */
- const int buttony = min_ii(UI_UNIT_Y, ar->winy - 2 * UI_DPI_FAC);
+ const int buttony = min_ii(UI_UNIT_Y, region->winy - 2 * UI_DPI_FAC);
const float buttony_scale = buttony / (float)UI_UNIT_Y;
/* Vertically center buttons. */
int xco = UI_HEADER_OFFSET;
- int yco = buttony + (ar->winy - buttony) / 2;
+ int yco = buttony + (region->winy - buttony) / 2;
int maxco = xco;
/* XXX workaround for 1 px alignment issue. Not sure what causes it...
@@ -2650,15 +2758,15 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
}
/* set view2d view matrix for scrolling (without scrollers) */
- UI_view2d_view_ortho(&ar->v2d);
+ UI_view2d_view_ortho(&region->v2d);
/* draw all headers types */
- for (ht = ar->type->headertypes.first; ht; ht = ht->next) {
+ for (ht = region->type->headertypes.first; ht; ht = ht->next) {
if (ht->poll && !ht->poll(C, ht)) {
continue;
}
- block = UI_block_begin(C, ar, ht->idname, UI_EMBOSS);
+ block = UI_block_begin(C, region, ht->idname, UI_EMBOSS);
layout = UI_block_layout(
block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, buttony, 1, 0, style);
@@ -2690,12 +2798,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_DPI_FAC;
- if (region_layout_based && (ar->sizex != new_sizex)) {
+ if (region_layout_based && (region->sizex != new_sizex)) {
/* region size is layout based and needs to be updated */
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- ar->sizex = new_sizex;
- sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ region->sizex = new_sizex;
+ area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
}
UI_block_end(C, block);
@@ -2706,39 +2814,39 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
}
/* always as last */
- UI_view2d_totRect_set(&ar->v2d, maxco, ar->winy);
+ UI_view2d_totRect_set(&region->v2d, maxco, region->winy);
/* restore view matrix */
UI_view2d_view_restore(C);
}
-void ED_region_header_draw(const bContext *C, ARegion *ar)
+void ED_region_header_draw(const bContext *C, ARegion *region)
{
/* clear */
- region_clear_color(C, ar, region_background_color_id(C, ar));
+ region_clear_color(C, region, region_background_color_id(C, region));
- UI_view2d_view_ortho(&ar->v2d);
+ UI_view2d_view_ortho(&region->v2d);
/* View2D matrix might have changed due to dynamic sized regions. */
- UI_blocklist_update_window_matrix(C, &ar->uiblocks);
+ UI_blocklist_update_window_matrix(C, &region->uiblocks);
/* draw blocks */
- UI_blocklist_draw(C, &ar->uiblocks);
+ UI_blocklist_draw(C, &region->uiblocks);
/* restore view matrix */
UI_view2d_view_restore(C);
}
-void ED_region_header(const bContext *C, ARegion *ar)
+void ED_region_header(const bContext *C, ARegion *region)
{
/* TODO: remove? */
- ED_region_header_layout(C, ar);
- ED_region_header_draw(C, ar);
+ ED_region_header_layout(C, region);
+ ED_region_header_draw(C, region);
}
-void ED_region_header_init(ARegion *ar)
+void ED_region_header_init(ARegion *region)
{
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_HEADER, region->winx, region->winy);
}
int ED_area_headersize(void)
@@ -2749,9 +2857,9 @@ int ED_area_headersize(void)
int ED_area_header_alignment_or_fallback(const ScrArea *area, int fallback)
{
- for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_HEADER) {
- return ar->alignment;
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->regiontype == RGN_TYPE_HEADER) {
+ return region->alignment;
}
}
return fallback;
@@ -2770,9 +2878,9 @@ int ED_area_footersize(void)
int ED_area_footer_alignment_or_fallback(const ScrArea *area, int fallback)
{
- for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_FOOTER) {
- return ar->alignment;
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->regiontype == RGN_TYPE_FOOTER) {
+ return region->alignment;
}
}
return fallback;
@@ -2847,19 +2955,19 @@ int ED_region_global_size_y(void)
return ED_area_headersize(); /* same size as header */
}
-void ED_region_info_draw_multiline(ARegion *ar,
+void ED_region_info_draw_multiline(ARegion *region,
const char *text_array[],
float fill_color[4],
const bool full_redraw)
{
const int header_height = UI_UNIT_Y;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
int fontid = style->widget.uifont_id;
int scissor[4];
int num_lines = 0;
/* background box */
- rcti rect = *ED_region_visible_rect(ar);
+ rcti rect = *ED_region_visible_rect(region);
/* Box fill entire width or just around text. */
if (!full_redraw) {
@@ -2922,12 +3030,13 @@ void ED_region_info_draw_multiline(ARegion *ar,
GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
-void ED_region_info_draw(ARegion *ar,
+void ED_region_info_draw(ARegion *region,
const char *text,
float fill_color[4],
const bool full_redraw)
{
- ED_region_info_draw_multiline(ar, (const char *[2]){text, NULL}, fill_color, full_redraw);
+ const char *text_array[2] = {text, NULL};
+ ED_region_info_draw_multiline(region, text_array, fill_color, full_redraw);
}
#define MAX_METADATA_STR 1024
@@ -3067,7 +3176,6 @@ static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const
ctx.fontid = fontid;
ctx.xmin = xmin;
ctx.ymin = ymin;
- ctx.vertical_offset = vertical_offset;
ctx.current_y = ofs_y;
ctx.vertical_offset = vertical_offset;
IMB_metadata_foreach(ibuf, metadata_custom_draw_fields, &ctx);
@@ -3158,7 +3266,7 @@ void ED_region_image_metadata_draw(
{
float box_y;
rctf rect;
- uiStyle *style = UI_style_get_dpi();
+ const uiStyle *style = UI_style_get_dpi();
if (!ibuf->metadata) {
return;
@@ -3244,15 +3352,15 @@ void ED_region_image_metadata_panel_draw(ImBuf *ibuf, uiLayout *layout)
IMB_metadata_foreach(ibuf, metadata_panel_draw_field, &ctx);
}
-void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy, float x0, float y0)
+void ED_region_grid_draw(ARegion *region, float zoomx, float zoomy, float x0, float y0)
{
float gridsize, gridstep = 1.0f / 32.0f;
float fac, blendfac;
int x1, y1, x2, y2;
/* the image is located inside (x0, y0), (x0+1, y0+1) as set by view2d */
- UI_view2d_view_to_region(&ar->v2d, x0, y0, &x1, &y1);
- UI_view2d_view_to_region(&ar->v2d, x0 + 1.0f, y0 + 1.0f, &x2, &y2);
+ UI_view2d_view_to_region(&region->v2d, x0, y0, &x1, &y1);
+ UI_view2d_view_to_region(&region->v2d, x0 + 1.0f, y0 + 1.0f, &x2, &y2);
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -3290,7 +3398,7 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy, float x0, float
if (count_fine > 0) {
GPU_vertformat_clear(format);
pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- unsigned color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GPU_PRIM_LINES, 4 * count_fine + 4 * count_large);
@@ -3335,42 +3443,42 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy, float x0, float
}
}
-/* If the area has overlapping regions, it returns visible rect for Region *ar */
+/* If the area has overlapping regions, it returns visible rect for Region *region */
/* rect gets returned in local region coordinates */
-static void region_visible_rect_calc(ARegion *ar, rcti *rect)
+static void region_visible_rect_calc(ARegion *region, rcti *rect)
{
- ARegion *arn = ar;
+ ARegion *arn = region;
/* allow function to be called without area */
while (arn->prev) {
arn = arn->prev;
}
- *rect = ar->winrct;
+ *rect = region->winrct;
/* check if a region overlaps with the current one */
for (; arn; arn = arn->next) {
- if (ar != arn && arn->overlap) {
+ if (region != arn && arn->overlap) {
if (BLI_rcti_isect(rect, &arn->winrct, NULL)) {
int alignment = RGN_ALIGN_ENUM_FROM_MASK(arn->alignment);
if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
/* Overlap left, also check 1 pixel offset (2 regions on one side). */
- if (ABS(rect->xmin - arn->winrct.xmin) < 2) {
+ if (abs(rect->xmin - arn->winrct.xmin) < 2) {
rect->xmin = arn->winrct.xmax;
}
/* Overlap right. */
- if (ABS(rect->xmax - arn->winrct.xmax) < 2) {
+ if (abs(rect->xmax - arn->winrct.xmax) < 2) {
rect->xmax = arn->winrct.xmin;
}
}
else if (ELEM(alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
/* Same logic as above for vertical regions. */
- if (ABS(rect->ymin - arn->winrct.ymin) < 2) {
+ if (abs(rect->ymin - arn->winrct.ymin) < 2) {
rect->ymin = arn->winrct.ymax;
}
- if (ABS(rect->ymax - arn->winrct.ymax) < 2) {
+ if (abs(rect->ymax - arn->winrct.ymax) < 2) {
rect->ymax = arn->winrct.ymin;
}
}
@@ -3383,37 +3491,37 @@ static void region_visible_rect_calc(ARegion *ar, rcti *rect)
}
}
}
- BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
+ BLI_rcti_translate(rect, -region->winrct.xmin, -region->winrct.ymin);
}
-const rcti *ED_region_visible_rect(ARegion *ar)
+const rcti *ED_region_visible_rect(ARegion *region)
{
- rcti *rect = &ar->runtime.visible_rect;
+ rcti *rect = &region->runtime.visible_rect;
if (rect->xmin == 0 && rect->ymin == 0 && rect->xmax == 0 && rect->ymax == 0) {
- region_visible_rect_calc(ar, rect);
+ region_visible_rect_calc(region, rect);
}
return rect;
}
/* Cache display helpers */
-void ED_region_cache_draw_background(ARegion *ar)
+void ED_region_cache_draw_background(ARegion *region)
{
/* Local coordinate visible rect inside region, to accommodate overlapping ui. */
- const rcti *rect_visible = ED_region_visible_rect(ar);
+ const rcti *rect_visible = ED_region_visible_rect(region);
const int region_bottom = rect_visible->ymin;
uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ub(128, 128, 255, 64);
- immRecti(pos, 0, region_bottom, ar->winx, region_bottom + 8 * UI_DPI_FAC);
+ immRecti(pos, 0, region_bottom, region->winx, region_bottom + 8 * UI_DPI_FAC);
immUnbindProgram();
}
void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y)
{
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
int fontid = style->widget.uifont_id;
char numstr[32];
float font_dims[2] = {0.0f, 0.0f};
@@ -3437,11 +3545,11 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f
}
void ED_region_cache_draw_cached_segments(
- ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra)
+ ARegion *region, const int num_segments, const int *points, const int sfra, const int efra)
{
if (num_segments) {
/* Local coordinate visible rect inside region, to accommodate overlapping ui. */
- const rcti *rect_visible = ED_region_visible_rect(ar);
+ const rcti *rect_visible = ED_region_visible_rect(region);
const int region_bottom = rect_visible->ymin;
uint pos = GPU_vertformat_attr_add(
@@ -3450,8 +3558,8 @@ void ED_region_cache_draw_cached_segments(
immUniformColor4ub(128, 128, 255, 128);
for (int a = 0; a < num_segments; a++) {
- float x1 = (float)(points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx;
- float x2 = (float)(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx;
+ float x1 = (float)(points[a * 2] - sfra) / (efra - sfra + 1) * region->winx;
+ float x2 = (float)(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * region->winx;
immRecti(pos, x1, region_bottom, x2, region_bottom + 8 * UI_DPI_FAC);
/* TODO(merwin): use primitive restart to draw multiple rects more efficiently */
@@ -3468,49 +3576,53 @@ void ED_region_message_subscribe(bContext *C,
struct WorkSpace *workspace,
struct Scene *scene,
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
- if (ar->gizmo_map != NULL) {
- WM_gizmomap_message_subscribe(C, ar->gizmo_map, ar, mbus);
+ if (region->gizmo_map != NULL) {
+ WM_gizmomap_message_subscribe(C, region->gizmo_map, region, mbus);
}
- if (!BLI_listbase_is_empty(&ar->uiblocks)) {
- UI_region_message_subscribe(ar, mbus);
+ if (!BLI_listbase_is_empty(&region->uiblocks)) {
+ UI_region_message_subscribe(region, mbus);
}
- if (ar->type->message_subscribe != NULL) {
- ar->type->message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
+ if (region->type->message_subscribe != NULL) {
+ region->type->message_subscribe(C, workspace, scene, screen, area, region, mbus);
}
}
-int ED_region_snap_size_test(const ARegion *ar)
+int ED_region_snap_size_test(const ARegion *region)
{
/* Use a larger value because toggling scrollbars can jump in size. */
const int snap_match_threshold = 16;
- if (ar->type->snap_size != NULL) {
- return ((((ar->sizex - ar->type->snap_size(ar, ar->sizex, 0)) <= snap_match_threshold) << 0) |
- (((ar->sizey - ar->type->snap_size(ar, ar->sizey, 1)) <= snap_match_threshold) << 1));
+ if (region->type->snap_size != NULL) {
+ return ((((region->sizex - region->type->snap_size(region, region->sizex, 0)) <=
+ snap_match_threshold)
+ << 0) |
+ (((region->sizey - region->type->snap_size(region, region->sizey, 1)) <=
+ snap_match_threshold)
+ << 1));
}
return 0;
}
-bool ED_region_snap_size_apply(ARegion *ar, int snap_flag)
+bool ED_region_snap_size_apply(ARegion *region, int snap_flag)
{
bool changed = false;
- if (ar->type->snap_size != NULL) {
+ if (region->type->snap_size != NULL) {
if (snap_flag & (1 << 0)) {
- short snap_size = ar->type->snap_size(ar, ar->sizex, 0);
- if (snap_size != ar->sizex) {
- ar->sizex = snap_size;
+ short snap_size = region->type->snap_size(region, region->sizex, 0);
+ if (snap_size != region->sizex) {
+ region->sizex = snap_size;
changed = true;
}
}
if (snap_flag & (1 << 1)) {
- short snap_size = ar->type->snap_size(ar, ar->sizey, 1);
- if (snap_size != ar->sizey) {
- ar->sizey = snap_size;
+ short snap_size = region->type->snap_size(region, region->sizey, 1);
+ if (snap_size != region->sizey) {
+ region->sizey = snap_size;
changed = true;
}
}
diff --git a/source/blender/editors/screen/area_query.c b/source/blender/editors/screen/area_query.c
index 942050aaffd..d569e56e11b 100644
--- a/source/blender/editors/screen/area_query.c
+++ b/source/blender/editors/screen/area_query.c
@@ -23,8 +23,8 @@
#include "DNA_userdef_types.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math_base.h"
+#include "BLI_utildefines.h"
#include "RNA_types.h"
@@ -33,47 +33,59 @@
#include "UI_interface.h"
#include "UI_view2d.h"
-bool ED_region_overlap_isect_x(const ARegion *ar, const int event_x)
+bool ED_region_overlap_isect_x(const ARegion *region, const int event_x)
{
- BLI_assert(ar->overlap);
+ BLI_assert(region->overlap);
/* No contents, skip it. */
- if (ar->v2d.mask.xmin == ar->v2d.mask.xmax) {
+ if (region->v2d.mask.xmin == region->v2d.mask.xmax) {
return false;
}
- return BLI_rctf_isect_x(&ar->v2d.tot,
- UI_view2d_region_to_view_x(&ar->v2d, event_x - ar->winrct.xmin));
+ return BLI_rctf_isect_x(&region->v2d.tot,
+ UI_view2d_region_to_view_x(&region->v2d, event_x - region->winrct.xmin));
}
-bool ED_region_overlap_isect_y(const ARegion *ar, const int event_y)
+bool ED_region_overlap_isect_y(const ARegion *region, const int event_y)
{
- BLI_assert(ar->overlap);
+ BLI_assert(region->overlap);
/* No contents, skip it. */
- if (ar->v2d.mask.ymin == ar->v2d.mask.ymax) {
+ if (region->v2d.mask.ymin == region->v2d.mask.ymax) {
return false;
}
- return BLI_rctf_isect_y(&ar->v2d.tot,
- UI_view2d_region_to_view_y(&ar->v2d, event_y - ar->winrct.ymin));
+ return BLI_rctf_isect_y(&region->v2d.tot,
+ UI_view2d_region_to_view_y(&region->v2d, event_y - region->winrct.ymin));
+}
+
+bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2])
+{
+ return (ED_region_overlap_isect_x(region, event_xy[0]) &&
+ ED_region_overlap_isect_y(region, event_xy[1]));
}
-bool ED_region_overlap_isect_xy(const ARegion *ar, const int event_xy[2])
+bool ED_region_overlap_isect_any_xy(const ScrArea *area, const int event_xy[2])
{
- return (ED_region_overlap_isect_x(ar, event_xy[0]) &&
- ED_region_overlap_isect_y(ar, event_xy[1]));
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (ED_region_is_overlap(area->spacetype, region->regiontype)) {
+ if (ED_region_overlap_isect_xy(region, event_xy)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
-bool ED_region_panel_category_gutter_calc_rect(const ARegion *ar, rcti *r_ar_gutter)
+bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_region_gutter)
{
- *r_ar_gutter = ar->winrct;
- if (UI_panel_category_is_visible(ar)) {
- const int category_tabs_width = round_fl_to_int(UI_view2d_scale_get_x(&ar->v2d) *
+ *r_region_gutter = region->winrct;
+ if (UI_panel_category_is_visible(region)) {
+ const int category_tabs_width = round_fl_to_int(UI_view2d_scale_get_x(&region->v2d) *
UI_PANEL_CATEGORY_MARGIN_WIDTH);
- const int alignment = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment);
+ const int alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
if (alignment == RGN_ALIGN_LEFT) {
- r_ar_gutter->xmax = r_ar_gutter->xmin + category_tabs_width;
+ r_region_gutter->xmax = r_region_gutter->xmin + category_tabs_width;
}
else if (alignment == RGN_ALIGN_RIGHT) {
- r_ar_gutter->xmin = r_ar_gutter->xmax - category_tabs_width;
+ r_region_gutter->xmin = r_region_gutter->xmax - category_tabs_width;
}
else {
BLI_assert(!"Unsupported alignment");
@@ -83,86 +95,90 @@ bool ED_region_panel_category_gutter_calc_rect(const ARegion *ar, rcti *r_ar_gut
return false;
}
-bool ED_region_panel_category_gutter_isect_xy(const ARegion *ar, const int event_xy[2])
+bool ED_region_panel_category_gutter_isect_xy(const ARegion *region, const int event_xy[2])
{
- rcti ar_gutter;
- if (ED_region_panel_category_gutter_calc_rect(ar, &ar_gutter)) {
- return BLI_rcti_isect_pt_v(&ar_gutter, event_xy);
+ rcti region_gutter;
+ if (ED_region_panel_category_gutter_calc_rect(region, &region_gutter)) {
+ return BLI_rcti_isect_pt_v(&region_gutter, event_xy);
}
return false;
}
-bool ED_region_overlap_isect_x_with_margin(const ARegion *ar, const int event_x, const int margin)
+bool ED_region_overlap_isect_x_with_margin(const ARegion *region,
+ const int event_x,
+ const int margin)
{
- BLI_assert(ar->overlap);
+ BLI_assert(region->overlap);
/* No contents, skip it. */
- if (ar->v2d.mask.xmin == ar->v2d.mask.xmax) {
+ if (region->v2d.mask.xmin == region->v2d.mask.xmax) {
return false;
}
- int region_x = event_x - ar->winrct.xmin;
- return ((ar->v2d.tot.xmin <= UI_view2d_region_to_view_x(&ar->v2d, region_x + margin)) &&
- (ar->v2d.tot.xmax >= UI_view2d_region_to_view_x(&ar->v2d, region_x - margin)));
+ int region_x = event_x - region->winrct.xmin;
+ return ((region->v2d.tot.xmin <= UI_view2d_region_to_view_x(&region->v2d, region_x + margin)) &&
+ (region->v2d.tot.xmax >= UI_view2d_region_to_view_x(&region->v2d, region_x - margin)));
}
-bool ED_region_overlap_isect_y_with_margin(const ARegion *ar, const int event_y, const int margin)
+bool ED_region_overlap_isect_y_with_margin(const ARegion *region,
+ const int event_y,
+ const int margin)
{
- BLI_assert(ar->overlap);
+ BLI_assert(region->overlap);
/* No contents, skip it. */
- if (ar->v2d.mask.ymin == ar->v2d.mask.ymax) {
+ if (region->v2d.mask.ymin == region->v2d.mask.ymax) {
return false;
}
- int region_y = event_y - ar->winrct.ymin;
- return ((ar->v2d.tot.ymin <= UI_view2d_region_to_view_y(&ar->v2d, region_y + margin)) &&
- (ar->v2d.tot.ymax >= UI_view2d_region_to_view_y(&ar->v2d, region_y - margin)));
+ int region_y = event_y - region->winrct.ymin;
+ return ((region->v2d.tot.ymin <= UI_view2d_region_to_view_y(&region->v2d, region_y + margin)) &&
+ (region->v2d.tot.ymax >= UI_view2d_region_to_view_y(&region->v2d, region_y - margin)));
}
-bool ED_region_overlap_isect_xy_with_margin(const ARegion *ar,
+bool ED_region_overlap_isect_xy_with_margin(const ARegion *region,
const int event_xy[2],
const int margin)
{
- return (ED_region_overlap_isect_x_with_margin(ar, event_xy[0], margin) &&
- ED_region_overlap_isect_y_with_margin(ar, event_xy[1], margin));
+ return (ED_region_overlap_isect_x_with_margin(region, event_xy[0], margin) &&
+ ED_region_overlap_isect_y_with_margin(region, event_xy[1], margin));
}
-bool ED_region_contains_xy(const ARegion *ar, const int event_xy[2])
+bool ED_region_contains_xy(const ARegion *region, const int event_xy[2])
{
/* Only use the margin when inside the region. */
- if (BLI_rcti_isect_pt_v(&ar->winrct, event_xy)) {
- if (ar->overlap) {
+ if (BLI_rcti_isect_pt_v(&region->winrct, event_xy)) {
+ if (region->overlap) {
const int overlap_margin = UI_REGION_OVERLAP_MARGIN;
/* Note the View2D.tot isn't reliable for headers with spacers otherwise
* we'd check #ED_region_overlap_isect_xy_with_margin for both bases. */
- if (ar->v2d.keeptot == V2D_KEEPTOT_STRICT) {
+ if (region->v2d.keeptot == V2D_KEEPTOT_STRICT) {
/* Header. */
rcti rect;
BLI_rcti_init_pt_radius(&rect, event_xy, overlap_margin);
- if (UI_region_but_find_rect_over(ar, &rect) == NULL) {
+ if (UI_region_but_find_rect_over(region, &rect) == NULL) {
return false;
}
}
else {
/* Side-bar & any other kind of overlapping region. */
- const int alignment = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment);
+ const int alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
/* Check alignment to avoid region tabs being clipped out
* by only clipping a single axis for aligned regions. */
if (ELEM(alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
- if (!ED_region_overlap_isect_x_with_margin(ar, event_xy[0], overlap_margin)) {
+ if (!ED_region_overlap_isect_x_with_margin(region, event_xy[0], overlap_margin)) {
return false;
}
}
else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
- if (ED_region_panel_category_gutter_isect_xy(ar, event_xy)) {
+ if (ED_region_panel_category_gutter_isect_xy(region, event_xy)) {
/* pass */
}
- else if (!ED_region_overlap_isect_y_with_margin(ar, event_xy[1], overlap_margin)) {
+ else if (!ED_region_overlap_isect_y_with_margin(region, event_xy[1], overlap_margin)) {
return false;
}
}
else {
/* No panel categories for horizontal regions currently. */
- if (!ED_region_overlap_isect_xy_with_margin(ar, event_xy, overlap_margin)) {
+ if (!ED_region_overlap_isect_xy_with_margin(region, event_xy, overlap_margin)) {
return false;
}
}
diff --git a/source/blender/editors/screen/area_utils.c b/source/blender/editors/screen/area_utils.c
index 12de1ddb795..075759f1120 100644
--- a/source/blender/editors/screen/area_utils.c
+++ b/source/blender/editors/screen/area_utils.c
@@ -46,13 +46,13 @@ void ED_region_generic_tools_region_message_subscribe(const struct bContext *UNU
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
- struct ScrArea *UNUSED(sa),
- struct ARegion *ar,
+ struct ScrArea *UNUSED(area),
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
@@ -61,11 +61,12 @@ void ED_region_generic_tools_region_message_subscribe(const struct bContext *UNU
/**
* Callback for #ARegionType.snap_size
*/
-int ED_region_generic_tools_region_snap_size(const ARegion *ar, int size, int axis)
+int ED_region_generic_tools_region_snap_size(const ARegion *region, int size, int axis)
{
if (axis == 0) {
/* Using Y axis avoids slight feedback loop when adjusting X. */
- const float aspect = BLI_rctf_size_y(&ar->v2d.cur) / (BLI_rcti_size_y(&ar->v2d.mask) + 1);
+ const float aspect = BLI_rctf_size_y(&region->v2d.cur) /
+ (BLI_rcti_size_y(&region->v2d.mask) + 1);
const float icon_size = ICON_DEFAULT_HEIGHT_TOOLBAR / aspect;
const float column = 1.25f * icon_size;
const float margin = 0.5f * icon_size;
@@ -80,7 +81,7 @@ int ED_region_generic_tools_region_snap_size(const ARegion *ar, int size, int ax
if (size <= snap_units[ARRAY_SIZE(snap_units) - 1]) {
for (uint i = 0; i < ARRAY_SIZE(snap_units); i += 1) {
const int test_size = snap_units[i];
- const int test_diff = ABS(test_size - size);
+ const int test_diff = abs(test_size - size);
if (test_diff < best_diff) {
best_size = test_size;
best_diff = test_diff;
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index dc435efd86b..ddb345ab65e 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -27,8 +27,8 @@
#include "DNA_userdef_types.h"
#include "DNA_vec_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -132,7 +132,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
float yzoom,
float color[4])
{
- unsigned char *uc_rect = (unsigned char *)rect;
+ uchar *uc_rect = (uchar *)rect;
const float *f_rect = (float *)rect;
int subpart_x, subpart_y, tex_w, tex_h;
int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
@@ -185,7 +185,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL);
}
- unsigned int pos = state->pos, texco = state->texco;
+ uint pos = state->pos, texco = state->texco;
/* optional */
/* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since
@@ -577,7 +577,7 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf,
if (ibuf->rect_float) {
if (ibuf->float_colorspace) {
ok = IMB_colormanagement_setup_glsl_draw_from_space(
- view_settings, display_settings, ibuf->float_colorspace, ibuf->dither, true);
+ view_settings, display_settings, ibuf->float_colorspace, ibuf->dither, true, false);
}
else {
ok = IMB_colormanagement_setup_glsl_draw(
@@ -586,7 +586,7 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf,
}
else {
ok = IMB_colormanagement_setup_glsl_draw_from_space(
- view_settings, display_settings, ibuf->rect_colorspace, ibuf->dither, false);
+ view_settings, display_settings, ibuf->rect_colorspace, ibuf->dither, false, false);
}
if (ok) {
@@ -650,7 +650,7 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf,
/* In case GLSL failed or not usable, fallback to glaDrawPixelsAuto */
if (need_fallback) {
- unsigned char *display_buffer;
+ uchar *display_buffer;
void *cache_handle;
display_buffer = IMB_display_buffer_acquire(
@@ -758,7 +758,7 @@ int ED_draw_imbuf_method(ImBuf *ibuf)
/* don't move to GPU_immediate_util.h because this uses user-prefs
* and isn't very low level */
-void immDrawBorderCorners(unsigned int pos, const rcti *border, float zoomx, float zoomy)
+void immDrawBorderCorners(uint pos, const rcti *border, float zoomx, float zoomy)
{
float delta_x = 4.0f * UI_DPI_FAC / zoomx;
float delta_y = 4.0f * UI_DPI_FAC / zoomy;
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index a840d199823..b383930ddda 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -27,33 +27,35 @@
#include "MEM_guardedalloc.h"
-#include "DNA_object_types.h"
+#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_gpencil_types.h"
-#include "DNA_sequence_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BKE_context.h"
-#include "BKE_object.h"
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_context.h"
#include "BKE_gpencil.h"
#include "BKE_layer.h"
+#include "BKE_object.h"
#include "BKE_sequencer.h"
#include "RNA_access.h"
+#include "ED_anim_api.h"
#include "ED_armature.h"
#include "ED_gpencil.h"
-#include "ED_anim_api.h"
-#include "WM_api.h"
#include "UI_interface.h"
+#include "WM_api.h"
#include "screen_intern.h"
@@ -88,6 +90,7 @@ const char *screen_context_dir[] = {
"sequences",
"selected_sequences",
"selected_editable_sequences", /* sequencer */
+ "selected_nla_strips", /* nla editor */
"gpencil_data",
"gpencil_data_owner", /* grease pencil data */
"annotation_data",
@@ -111,8 +114,8 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C); /* This may be NULL in a lot of cases. */
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area = CTX_wm_area(C);
Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
Object *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
@@ -127,7 +130,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "visible_objects")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (BASE_VISIBLE(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
@@ -136,7 +139,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selectable_objects")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (BASE_SELECTABLE(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
@@ -145,7 +148,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selected_objects")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (BASE_SELECTED(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
@@ -154,7 +157,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selected_editable_objects")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (BASE_SELECTED_EDITABLE(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
@@ -164,7 +167,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "editable_objects")) {
/* Visible + Editable, but not necessarily selected */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (BASE_EDITABLE(v3d, base)) {
CTX_data_id_list_add(result, &base->object->id);
}
@@ -503,13 +506,38 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
}
+ else if (CTX_data_equals(member, "selected_nla_strips")) {
+ bAnimContext ac;
+ if (ANIM_animdata_get_context(C, &ac) != 0) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+
+ ANIM_animdata_filter(&ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac.data, ac.datatype);
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ if (ale->datatype != ALE_NLASTRIP) {
+ continue;
+ }
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ CTX_data_list_add(result, &scene->id, &RNA_NlaStrip, strip);
+ }
+ }
+ }
+ ANIM_animdata_freelist(&anim_data);
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ }
else if (CTX_data_equals(member, "gpencil_data")) {
/* FIXME: for some reason, CTX_data_active_object(C) returns NULL when called from these
* situations (as outlined above - see Campbell's #ifdefs).
* That causes the get_active function to fail when called from context.
* For that reason, we end up using an alternative where we pass everything in!
*/
- bGPdata *gpd = ED_gpencil_data_get_active_direct(sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
CTX_data_id_pointer_set(result, &gpd->id);
@@ -523,7 +551,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
PointerRNA ptr;
/* get pointer to Grease Pencil Data */
- gpd_ptr = ED_gpencil_data_get_pointers_direct(sa, obact, &ptr);
+ gpd_ptr = ED_gpencil_data_get_pointers_direct(area, obact, &ptr);
if (gpd_ptr) {
CTX_data_pointer_set(result, ptr.owner_id, ptr.type, ptr.data);
@@ -531,7 +559,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
}
else if (CTX_data_equals(member, "annotation_data")) {
- bGPdata *gpd = ED_annotation_data_get_active_direct((ID *)sc, sa, scene);
+ bGPdata *gpd = ED_annotation_data_get_active_direct((ID *)screen, area, scene);
if (gpd) {
CTX_data_id_pointer_set(result, &gpd->id);
@@ -544,7 +572,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
PointerRNA ptr;
/* Get pointer to Grease Pencil Data. */
- gpd_ptr = ED_annotation_data_get_pointers_direct((ID *)sc, sa, scene, &ptr);
+ gpd_ptr = ED_annotation_data_get_pointers_direct((ID *)screen, area, scene, &ptr);
if (gpd_ptr) {
CTX_data_pointer_set(result, ptr.owner_id, ptr.type, ptr.data);
@@ -552,10 +580,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
}
else if (CTX_data_equals(member, "active_gpencil_layer")) {
- bGPdata *gpd = ED_gpencil_data_get_active_direct(sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
@@ -564,10 +592,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
}
else if (CTX_data_equals(member, "active_annotation_layer")) {
- bGPdata *gpd = ED_annotation_data_get_active_direct((ID *)sc, sa, scene);
+ bGPdata *gpd = ED_annotation_data_get_active_direct((ID *)screen, area, scene);
if (gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
@@ -576,10 +604,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
}
else if (CTX_data_equals(member, "active_gpencil_frame")) {
- bGPdata *gpd = ED_gpencil_data_get_active_direct(sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe);
@@ -588,7 +616,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
}
else if (CTX_data_equals(member, "visible_gpencil_layers")) {
- bGPdata *gpd = ED_gpencil_data_get_active_direct(sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
bGPDlayer *gpl;
@@ -603,13 +631,13 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
}
else if (CTX_data_equals(member, "editable_gpencil_layers")) {
- bGPdata *gpd = ED_gpencil_data_get_active_direct(sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
if (gpd) {
bGPDlayer *gpl;
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpencil_layer_is_editable(gpl)) {
+ if (BKE_gpencil_layer_is_editable(gpl)) {
CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
}
}
@@ -618,14 +646,14 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
}
else if (CTX_data_equals(member, "editable_gpencil_strokes")) {
- bGPdata *gpd = ED_gpencil_data_get_active_direct(sa, obact);
+ bGPdata *gpd = ED_gpencil_data_get_active_direct(area, obact);
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
if (gpd) {
bGPDlayer *gpl;
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe)) {
bGPDframe *gpf;
bGPDstroke *gps;
bGPDframe *init_gpf = gpl->actframe;
@@ -636,7 +664,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
for (gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
for (gps = gpf->strokes.first; gps; gps = gps->next) {
- if (ED_gpencil_stroke_can_use_direct(sa, gps)) {
+ if (ED_gpencil_stroke_can_use_direct(area, gps)) {
/* check if the color is editable */
if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
continue;
@@ -701,7 +729,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
+ LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
CTX_data_list_add(result, ale->fcurve_owner_id, &RNA_FCurve, ale->data);
}
@@ -724,7 +752,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
+ LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
CTX_data_pointer_set(result, ale->fcurve_owner_id, &RNA_FCurve, ale->data);
break;
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index a6b8bba73e3..2452302561b 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -21,10 +21,10 @@
#include "ED_screen.h"
#include "GPU_batch_presets.h"
-#include "GPU_platform.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_platform.h"
#include "GPU_state.h"
#include "BLI_listbase.h"
@@ -41,10 +41,10 @@
* Draw horizontal shape visualizing future joining
* (left as well right direction of future joining).
*/
-static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
+static void draw_horizontal_join_shape(ScrArea *area, char dir, uint pos)
{
- const float width = screen_geom_area_width(sa) - 1;
- const float height = screen_geom_area_height(sa) - 1;
+ const float width = screen_geom_area_width(area) - 1;
+ const float height = screen_geom_area_height(area) - 1;
vec2f points[10];
short i;
float w, h;
@@ -58,43 +58,43 @@ static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
w = width / 4;
}
- points[0].x = sa->v1->vec.x;
- points[0].y = sa->v1->vec.y + height / 2;
+ points[0].x = area->v1->vec.x;
+ points[0].y = area->v1->vec.y + height / 2;
- points[1].x = sa->v1->vec.x;
- points[1].y = sa->v1->vec.y;
+ points[1].x = area->v1->vec.x;
+ points[1].y = area->v1->vec.y;
- points[2].x = sa->v4->vec.x - w;
- points[2].y = sa->v4->vec.y;
+ points[2].x = area->v4->vec.x - w;
+ points[2].y = area->v4->vec.y;
- points[3].x = sa->v4->vec.x - w;
- points[3].y = sa->v4->vec.y + height / 2 - 2 * h;
+ points[3].x = area->v4->vec.x - w;
+ points[3].y = area->v4->vec.y + height / 2 - 2 * h;
- points[4].x = sa->v4->vec.x - 2 * w;
- points[4].y = sa->v4->vec.y + height / 2;
+ points[4].x = area->v4->vec.x - 2 * w;
+ points[4].y = area->v4->vec.y + height / 2;
- points[5].x = sa->v4->vec.x - w;
- points[5].y = sa->v4->vec.y + height / 2 + 2 * h;
+ points[5].x = area->v4->vec.x - w;
+ points[5].y = area->v4->vec.y + height / 2 + 2 * h;
- points[6].x = sa->v3->vec.x - w;
- points[6].y = sa->v3->vec.y;
+ points[6].x = area->v3->vec.x - w;
+ points[6].y = area->v3->vec.y;
- points[7].x = sa->v2->vec.x;
- points[7].y = sa->v2->vec.y;
+ points[7].x = area->v2->vec.x;
+ points[7].y = area->v2->vec.y;
- points[8].x = sa->v4->vec.x;
- points[8].y = sa->v4->vec.y + height / 2 - h;
+ points[8].x = area->v4->vec.x;
+ points[8].y = area->v4->vec.y + height / 2 - h;
- points[9].x = sa->v4->vec.x;
- points[9].y = sa->v4->vec.y + height / 2 + h;
+ points[9].x = area->v4->vec.x;
+ points[9].y = area->v4->vec.y + height / 2 + h;
if (dir == 'l') {
/* when direction is left, then we flip direction of arrow */
- float cx = sa->v1->vec.x + width;
+ float cx = area->v1->vec.x + width;
for (i = 0; i < 10; i++) {
points[i].x -= cx;
points[i].x = -points[i].x;
- points[i].x += sa->v1->vec.x;
+ points[i].x += area->v1->vec.x;
}
}
@@ -122,10 +122,10 @@ static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
/**
* Draw vertical shape visualizing future joining (up/down direction).
*/
-static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
+static void draw_vertical_join_shape(ScrArea *area, char dir, uint pos)
{
- const float width = screen_geom_area_width(sa) - 1;
- const float height = screen_geom_area_height(sa) - 1;
+ const float width = screen_geom_area_width(area) - 1;
+ const float height = screen_geom_area_height(area) - 1;
vec2f points[10];
short i;
float w, h;
@@ -139,43 +139,43 @@ static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
w = width / 8;
}
- points[0].x = sa->v1->vec.x + width / 2;
- points[0].y = sa->v3->vec.y;
+ points[0].x = area->v1->vec.x + width / 2;
+ points[0].y = area->v3->vec.y;
- points[1].x = sa->v2->vec.x;
- points[1].y = sa->v2->vec.y;
+ points[1].x = area->v2->vec.x;
+ points[1].y = area->v2->vec.y;
- points[2].x = sa->v1->vec.x;
- points[2].y = sa->v1->vec.y + h;
+ points[2].x = area->v1->vec.x;
+ points[2].y = area->v1->vec.y + h;
- points[3].x = sa->v1->vec.x + width / 2 - 2 * w;
- points[3].y = sa->v1->vec.y + h;
+ points[3].x = area->v1->vec.x + width / 2 - 2 * w;
+ points[3].y = area->v1->vec.y + h;
- points[4].x = sa->v1->vec.x + width / 2;
- points[4].y = sa->v1->vec.y + 2 * h;
+ points[4].x = area->v1->vec.x + width / 2;
+ points[4].y = area->v1->vec.y + 2 * h;
- points[5].x = sa->v1->vec.x + width / 2 + 2 * w;
- points[5].y = sa->v1->vec.y + h;
+ points[5].x = area->v1->vec.x + width / 2 + 2 * w;
+ points[5].y = area->v1->vec.y + h;
- points[6].x = sa->v4->vec.x;
- points[6].y = sa->v4->vec.y + h;
+ points[6].x = area->v4->vec.x;
+ points[6].y = area->v4->vec.y + h;
- points[7].x = sa->v3->vec.x;
- points[7].y = sa->v3->vec.y;
+ points[7].x = area->v3->vec.x;
+ points[7].y = area->v3->vec.y;
- points[8].x = sa->v1->vec.x + width / 2 - w;
- points[8].y = sa->v1->vec.y;
+ points[8].x = area->v1->vec.x + width / 2 - w;
+ points[8].y = area->v1->vec.y;
- points[9].x = sa->v1->vec.x + width / 2 + w;
- points[9].y = sa->v1->vec.y;
+ points[9].x = area->v1->vec.x + width / 2 + w;
+ points[9].y = area->v1->vec.y;
if (dir == 'u') {
/* when direction is up, then we flip direction of arrow */
- float cy = sa->v1->vec.y + height;
+ float cy = area->v1->vec.y + height;
for (i = 0; i < 10; i++) {
points[i].y -= cy;
points[i].y = -points[i].y;
- points[i].y += sa->v1->vec.y;
+ points[i].y += area->v1->vec.y;
}
}
@@ -203,13 +203,13 @@ static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
/**
* Draw join shape due to direction of joining.
*/
-static void draw_join_shape(ScrArea *sa, char dir, unsigned int pos)
+static void draw_join_shape(ScrArea *area, char dir, uint pos)
{
if (dir == 'u' || dir == 'd') {
- draw_vertical_join_shape(sa, dir, pos);
+ draw_vertical_join_shape(area, dir, pos);
}
else {
- draw_horizontal_join_shape(sa, dir, pos);
+ draw_horizontal_join_shape(area, dir, pos);
}
}
@@ -294,26 +294,26 @@ static GPUBatch *batch_screen_edges_get(int *corner_len)
/**
* Draw screen area darker with arrow (visualization of future joining).
*/
-static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos)
+static void scrarea_draw_shape_dark(ScrArea *area, char dir, uint pos)
{
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
immUniformColor4ub(0, 0, 0, 50);
- draw_join_shape(sa, dir, pos);
+ draw_join_shape(area, dir, pos);
}
/**
* Draw screen area lighter with arrow shape ("eraser" of previous dark shape).
*/
-static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir), unsigned int pos)
+static void scrarea_draw_shape_light(ScrArea *area, char UNUSED(dir), uint pos)
{
GPU_blend_set_func(GPU_DST_COLOR, GPU_SRC_ALPHA);
/* value 181 was hardly computed: 181~105 */
immUniformColor4ub(255, 255, 255, 50);
- /* draw_join_shape(sa, dir); */
+ /* draw_join_shape(area, dir); */
- immRectf(pos, sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
+ immRectf(pos, area->v1->vec.x, area->v1->vec.y, area->v3->vec.x, area->v3->vec.y);
}
static void drawscredge_area_draw(
@@ -350,12 +350,12 @@ static void drawscredge_area_draw(
/**
* \brief Screen edges drawing.
*/
-static void drawscredge_area(ScrArea *sa, int sizex, int sizey, float edge_thickness)
+static void drawscredge_area(ScrArea *area, int sizex, int sizey, float edge_thickness)
{
- short x1 = sa->v1->vec.x;
- short y1 = sa->v1->vec.y;
- short x2 = sa->v3->vec.x;
- short y2 = sa->v3->vec.y;
+ short x1 = area->v1->vec.x;
+ short y1 = area->v1->vec.y;
+ short x2 = area->v3->vec.x;
+ short y2 = area->v3->vec.y;
drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, edge_thickness);
}
@@ -381,13 +381,13 @@ void ED_screen_draw_edges(wmWindow *win)
float col[4], corner_scale, edge_thickness;
int verts_per_corner = 0;
- ScrArea *sa;
+ ScrArea *area;
rcti scissor_rect;
BLI_rcti_init_minmax(&scissor_rect);
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){sa->v1->vec.x, sa->v1->vec.y});
- BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){sa->v3->vec.x, sa->v3->vec.y});
+ for (area = screen->areabase.first; area; area = area->next) {
+ BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){area->v1->vec.x, area->v1->vec.y});
+ BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){area->v3->vec.x, area->v3->vec.y});
}
if (GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
@@ -422,8 +422,8 @@ void ED_screen_draw_edges(wmWindow *win)
GPU_batch_uniform_1f(batch, "scale", corner_scale);
GPU_batch_uniform_4fv(batch, "color", col);
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- drawscredge_area(sa, winsize_x, winsize_y, edge_thickness);
+ for (area = screen->areabase.first; area; area = area->next) {
+ drawscredge_area(area, winsize_x, winsize_y, edge_thickness);
}
GPU_blend(false);
@@ -480,7 +480,7 @@ void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2)
immUnbindProgram();
}
-void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
+void ED_screen_draw_split_preview(ScrArea *area, const int dir, const float fac)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -495,10 +495,10 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
immBegin(GPU_PRIM_LINES, 2);
if (dir == 'h') {
- const float y = (1 - fac) * sa->totrct.ymin + fac * sa->totrct.ymax;
+ const float y = (1 - fac) * area->totrct.ymin + fac * area->totrct.ymax;
- immVertex2f(pos, sa->totrct.xmin, y);
- immVertex2f(pos, sa->totrct.xmax, y);
+ immVertex2f(pos, area->totrct.xmin, y);
+ immVertex2f(pos, area->totrct.xmax, y);
immEnd();
@@ -506,17 +506,17 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, sa->totrct.xmin, y + 1);
- immVertex2f(pos, sa->totrct.xmax, y + 1);
+ immVertex2f(pos, area->totrct.xmin, y + 1);
+ immVertex2f(pos, area->totrct.xmax, y + 1);
immEnd();
}
else {
BLI_assert(dir == 'v');
- const float x = (1 - fac) * sa->totrct.xmin + fac * sa->totrct.xmax;
+ const float x = (1 - fac) * area->totrct.xmin + fac * area->totrct.xmax;
- immVertex2f(pos, x, sa->totrct.ymin);
- immVertex2f(pos, x, sa->totrct.ymax);
+ immVertex2f(pos, x, area->totrct.ymin);
+ immVertex2f(pos, x, area->totrct.ymax);
immEnd();
@@ -524,8 +524,8 @@ void ED_screen_draw_split_preview(ScrArea *sa, const int dir, const float fac)
immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, x + 1, sa->totrct.ymin);
- immVertex2f(pos, x + 1, sa->totrct.ymax);
+ immVertex2f(pos, x + 1, area->totrct.ymin);
+ immVertex2f(pos, x + 1, area->totrct.ymax);
immEnd();
}
@@ -547,9 +547,9 @@ static void screen_preview_scale_get(
{
float max_x = 0, max_y = 0;
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- max_x = MAX2(max_x, sa->totrct.xmax);
- max_y = MAX2(max_y, sa->totrct.ymax);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ max_x = MAX2(max_x, area->totrct.xmax);
+ max_y = MAX2(max_y, area->totrct.ymax);
}
r_scale[0] = (size_x * asp[0]) / max_x;
r_scale[1] = (size_y * asp[1]) / max_y;
@@ -566,12 +566,12 @@ static void screen_preview_draw_areas(const bScreen *screen,
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(col);
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
rctf rect = {
- .xmin = sa->totrct.xmin * scale[0] + ofs_h,
- .xmax = sa->totrct.xmax * scale[0] - ofs_h,
- .ymin = sa->totrct.ymin * scale[1] + ofs_h,
- .ymax = sa->totrct.ymax * scale[1] - ofs_h,
+ .xmin = area->totrct.xmin * scale[0] + ofs_h,
+ .xmax = area->totrct.xmax * scale[0] - ofs_h,
+ .ymin = area->totrct.ymin * scale[1] + ofs_h,
+ .ymax = area->totrct.ymax * scale[1] - ofs_h,
};
immBegin(GPU_PRIM_TRI_FAN, 4);
@@ -608,7 +608,7 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
/**
* Render the preview for a screen layout in \a screen.
*/
-void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, unsigned int *r_rect)
+void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, uint *r_rect)
{
char err_out[256] = "unknown";
GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, true, false, err_out);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 501c36286d0..00afbf452dd 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -21,15 +21,15 @@
* \ingroup edscr
*/
-#include <string.h>
#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_workspace_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -39,20 +39,20 @@
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
-#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "BKE_sound.h"
#include "BKE_workspace.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_screen.h"
-#include "ED_screen_types.h"
#include "ED_clip.h"
#include "ED_node.h"
+#include "ED_screen.h"
+#include "ED_screen_types.h"
#include "UI_interface.h"
@@ -70,19 +70,19 @@ static ScrArea *screen_addarea_ex(ScrAreaMap *area_map,
ScrVert *bottom_right,
short spacetype)
{
- ScrArea *sa = MEM_callocN(sizeof(ScrArea), "addscrarea");
+ ScrArea *area = MEM_callocN(sizeof(ScrArea), "addscrarea");
- sa->v1 = bottom_left;
- sa->v2 = top_left;
- sa->v3 = top_right;
- sa->v4 = bottom_right;
- sa->spacetype = spacetype;
+ area->v1 = bottom_left;
+ area->v2 = top_left;
+ area->v3 = top_right;
+ area->v4 = bottom_right;
+ area->spacetype = spacetype;
- BLI_addtail(&area_map->areabase, sa);
+ BLI_addtail(&area_map->areabase, area);
- return sa;
+ return area;
}
-static ScrArea *screen_addarea(bScreen *sc,
+static ScrArea *screen_addarea(bScreen *screen,
ScrVert *left_bottom,
ScrVert *left_top,
ScrVert *right_top,
@@ -90,34 +90,35 @@ static ScrArea *screen_addarea(bScreen *sc,
short spacetype)
{
return screen_addarea_ex(
- AREAMAP_FROM_SCREEN(sc), left_bottom, left_top, right_top, right_bottom, spacetype);
+ AREAMAP_FROM_SCREEN(screen), left_bottom, left_top, right_top, right_bottom, spacetype);
}
-static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa)
+static void screen_delarea(bContext *C, bScreen *screen, ScrArea *area)
{
- ED_area_exit(C, sa);
+ ED_area_exit(C, area);
- BKE_screen_area_free(sa);
+ BKE_screen_area_free(area);
- BLI_remlink(&sc->areabase, sa);
- MEM_freeN(sa);
+ BLI_remlink(&screen->areabase, area);
+ MEM_freeN(area);
}
-ScrArea *area_split(const wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
+ScrArea *area_split(
+ const wmWindow *win, bScreen *screen, ScrArea *area, char dir, float fac, int merge)
{
ScrArea *newa = NULL;
ScrVert *sv1, *sv2;
short split;
rcti window_rect;
- if (sa == NULL) {
+ if (area == NULL) {
return NULL;
}
WM_window_rect_calc(win, &window_rect);
- split = screen_geom_find_area_split_point(sa, &window_rect, dir, fac);
+ split = screen_geom_find_area_split_point(area, &window_rect, dir, fac);
if (split == 0) {
return NULL;
}
@@ -128,73 +129,73 @@ ScrArea *area_split(const wmWindow *win, bScreen *sc, ScrArea *sa, char dir, flo
if (dir == 'h') {
/* new vertices */
- sv1 = screen_geom_vertex_add(sc, sa->v1->vec.x, split);
- sv2 = screen_geom_vertex_add(sc, sa->v4->vec.x, split);
+ sv1 = screen_geom_vertex_add(screen, area->v1->vec.x, split);
+ sv2 = screen_geom_vertex_add(screen, area->v4->vec.x, split);
/* new edges */
- screen_geom_edge_add(sc, sa->v1, sv1);
- screen_geom_edge_add(sc, sv1, sa->v2);
- screen_geom_edge_add(sc, sa->v3, sv2);
- screen_geom_edge_add(sc, sv2, sa->v4);
- screen_geom_edge_add(sc, sv1, sv2);
+ screen_geom_edge_add(screen, area->v1, sv1);
+ screen_geom_edge_add(screen, sv1, area->v2);
+ screen_geom_edge_add(screen, area->v3, sv2);
+ screen_geom_edge_add(screen, sv2, area->v4);
+ screen_geom_edge_add(screen, sv1, sv2);
if (fac > 0.5f) {
/* new areas: top */
- newa = screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->spacetype);
+ newa = screen_addarea(screen, sv1, area->v2, area->v3, sv2, area->spacetype);
/* area below */
- sa->v2 = sv1;
- sa->v3 = sv2;
+ area->v2 = sv1;
+ area->v3 = sv2;
}
else {
/* new areas: bottom */
- newa = screen_addarea(sc, sa->v1, sv1, sv2, sa->v4, sa->spacetype);
+ newa = screen_addarea(screen, area->v1, sv1, sv2, area->v4, area->spacetype);
/* area above */
- sa->v1 = sv1;
- sa->v4 = sv2;
+ area->v1 = sv1;
+ area->v4 = sv2;
}
- ED_area_data_copy(newa, sa, true);
+ ED_area_data_copy(newa, area, true);
}
else {
/* new vertices */
- sv1 = screen_geom_vertex_add(sc, split, sa->v1->vec.y);
- sv2 = screen_geom_vertex_add(sc, split, sa->v2->vec.y);
+ sv1 = screen_geom_vertex_add(screen, split, area->v1->vec.y);
+ sv2 = screen_geom_vertex_add(screen, split, area->v2->vec.y);
/* new edges */
- screen_geom_edge_add(sc, sa->v1, sv1);
- screen_geom_edge_add(sc, sv1, sa->v4);
- screen_geom_edge_add(sc, sa->v2, sv2);
- screen_geom_edge_add(sc, sv2, sa->v3);
- screen_geom_edge_add(sc, sv1, sv2);
+ screen_geom_edge_add(screen, area->v1, sv1);
+ screen_geom_edge_add(screen, sv1, area->v4);
+ screen_geom_edge_add(screen, area->v2, sv2);
+ screen_geom_edge_add(screen, sv2, area->v3);
+ screen_geom_edge_add(screen, sv1, sv2);
if (fac > 0.5f) {
/* new areas: right */
- newa = screen_addarea(sc, sv1, sv2, sa->v3, sa->v4, sa->spacetype);
+ newa = screen_addarea(screen, sv1, sv2, area->v3, area->v4, area->spacetype);
/* area left */
- sa->v3 = sv2;
- sa->v4 = sv1;
+ area->v3 = sv2;
+ area->v4 = sv1;
}
else {
/* new areas: left */
- newa = screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->spacetype);
+ newa = screen_addarea(screen, area->v1, area->v2, sv2, sv1, area->spacetype);
/* area right */
- sa->v1 = sv1;
- sa->v2 = sv2;
+ area->v1 = sv1;
+ area->v2 = sv2;
}
- ED_area_data_copy(newa, sa, true);
+ ED_area_data_copy(newa, area, true);
}
/* remove double vertices en edges */
if (merge) {
- BKE_screen_remove_double_scrverts(sc);
+ BKE_screen_remove_double_scrverts(screen);
}
- BKE_screen_remove_double_scredges(sc);
- BKE_screen_remove_unused_scredges(sc);
+ BKE_screen_remove_double_scredges(screen);
+ BKE_screen_remove_unused_scredges(screen);
return newa;
}
@@ -204,34 +205,34 @@ ScrArea *area_split(const wmWindow *win, bScreen *sc, ScrArea *sa, char dir, flo
*/
bScreen *screen_add(Main *bmain, const char *name, const rcti *rect)
{
- bScreen *sc;
+ bScreen *screen;
ScrVert *sv1, *sv2, *sv3, *sv4;
- sc = BKE_libblock_alloc(bmain, ID_SCR, name, 0);
- sc->do_refresh = true;
- sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN;
+ screen = BKE_libblock_alloc(bmain, ID_SCR, name, 0);
+ screen->do_refresh = true;
+ screen->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN;
- sv1 = screen_geom_vertex_add(sc, rect->xmin, rect->ymin);
- sv2 = screen_geom_vertex_add(sc, rect->xmin, rect->ymax - 1);
- sv3 = screen_geom_vertex_add(sc, rect->xmax - 1, rect->ymax - 1);
- sv4 = screen_geom_vertex_add(sc, rect->xmax - 1, rect->ymin);
+ sv1 = screen_geom_vertex_add(screen, rect->xmin, rect->ymin);
+ sv2 = screen_geom_vertex_add(screen, rect->xmin, rect->ymax - 1);
+ sv3 = screen_geom_vertex_add(screen, rect->xmax - 1, rect->ymax - 1);
+ sv4 = screen_geom_vertex_add(screen, rect->xmax - 1, rect->ymin);
- screen_geom_edge_add(sc, sv1, sv2);
- screen_geom_edge_add(sc, sv2, sv3);
- screen_geom_edge_add(sc, sv3, sv4);
- screen_geom_edge_add(sc, sv4, sv1);
+ screen_geom_edge_add(screen, sv1, sv2);
+ screen_geom_edge_add(screen, sv2, sv3);
+ screen_geom_edge_add(screen, sv3, sv4);
+ screen_geom_edge_add(screen, sv4, sv1);
/* dummy type, no spacedata */
- screen_addarea(sc, sv1, sv2, sv3, sv4, SPACE_EMPTY);
+ screen_addarea(screen, sv1, sv2, sv3, sv4, SPACE_EMPTY);
- return sc;
+ return screen;
}
void screen_data_copy(bScreen *to, bScreen *from)
{
ScrVert *s1, *s2;
ScrEdge *se;
- ScrArea *sa, *saf;
+ ScrArea *area, *saf;
/* free contents of 'to', is from blenkernel screen.c */
BKE_screen_free(to);
@@ -255,18 +256,18 @@ void screen_data_copy(bScreen *to, bScreen *from)
}
saf = from->areabase.first;
- for (sa = to->areabase.first; sa; sa = sa->next, saf = saf->next) {
- sa->v1 = sa->v1->newv;
- sa->v2 = sa->v2->newv;
- sa->v3 = sa->v3->newv;
- sa->v4 = sa->v4->newv;
+ for (area = to->areabase.first; area; area = area->next, saf = saf->next) {
+ area->v1 = area->v1->newv;
+ area->v2 = area->v2->newv;
+ area->v3 = area->v3->newv;
+ area->v4 = area->v4->newv;
- BLI_listbase_clear(&sa->spacedata);
- BLI_listbase_clear(&sa->regionbase);
- BLI_listbase_clear(&sa->actionzones);
- BLI_listbase_clear(&sa->handlers);
+ BLI_listbase_clear(&area->spacedata);
+ BLI_listbase_clear(&area->regionbase);
+ BLI_listbase_clear(&area->actionzones);
+ BLI_listbase_clear(&area->handlers);
- ED_area_data_copy(sa, saf, true);
+ ED_area_data_copy(area, saf, true);
}
/* put at zero (needed?) */
@@ -285,19 +286,19 @@ void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new)
screen_new->do_draw = true;
}
-/* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
+/* with area as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
/* -1 = not valid check */
/* used with join operator */
-int area_getorientation(ScrArea *sa, ScrArea *sb)
+int area_getorientation(ScrArea *area, ScrArea *sb)
{
- if (sa == NULL || sb == NULL) {
+ if (area == NULL || sb == NULL) {
return -1;
}
- ScrVert *saBL = sa->v1;
- ScrVert *saTL = sa->v2;
- ScrVert *saTR = sa->v3;
- ScrVert *saBR = sa->v4;
+ ScrVert *saBL = area->v1;
+ ScrVert *saTL = area->v2;
+ ScrVert *saTR = area->v3;
+ ScrVert *saBR = area->v4;
ScrVert *sbBL = sb->v1;
ScrVert *sbTL = sb->v2;
@@ -306,27 +307,28 @@ int area_getorientation(ScrArea *sa, ScrArea *sb)
int tolerance = U.pixelsize * 4;
- if (saBL->vec.x == sbBR->vec.x && saTL->vec.x == sbTR->vec.x) { /* sa to right of sb = W */
- if ((ABS(saBL->vec.y - sbBR->vec.y) <= tolerance) &&
- (ABS(saTL->vec.y - sbTR->vec.y) <= tolerance)) {
+ if (saBL->vec.x == sbBR->vec.x && saTL->vec.x == sbTR->vec.x) { /* area to right of sb = W */
+ if ((abs(saBL->vec.y - sbBR->vec.y) <= tolerance) &&
+ (abs(saTL->vec.y - sbTR->vec.y) <= tolerance)) {
return 0;
}
}
- else if (saTL->vec.y == sbBL->vec.y && saTR->vec.y == sbBR->vec.y) { /* sa to bottom of sb = N */
- if ((ABS(saTL->vec.x - sbBL->vec.x) <= tolerance) &&
- (ABS(saTR->vec.x - sbBR->vec.x) <= tolerance)) {
+ else if (saTL->vec.y == sbBL->vec.y &&
+ saTR->vec.y == sbBR->vec.y) { /* area to bottom of sb = N */
+ if ((abs(saTL->vec.x - sbBL->vec.x) <= tolerance) &&
+ (abs(saTR->vec.x - sbBR->vec.x) <= tolerance)) {
return 1;
}
}
- else if (saTR->vec.x == sbTL->vec.x && saBR->vec.x == sbBL->vec.x) { /* sa to left of sb = E */
- if ((ABS(saTR->vec.y - sbTL->vec.y) <= tolerance) &&
- (ABS(saBR->vec.y - sbBL->vec.y) <= tolerance)) {
+ else if (saTR->vec.x == sbTL->vec.x && saBR->vec.x == sbBL->vec.x) { /* area to left of sb = E */
+ if ((abs(saTR->vec.y - sbTL->vec.y) <= tolerance) &&
+ (abs(saBR->vec.y - sbBL->vec.y) <= tolerance)) {
return 2;
}
}
- else if (saBL->vec.y == sbTL->vec.y && saBR->vec.y == sbTR->vec.y) { /* sa on top of sb = S*/
- if ((ABS(saBL->vec.x - sbTL->vec.x) <= tolerance) &&
- (ABS(saBR->vec.x - sbTR->vec.x) <= tolerance)) {
+ else if (saBL->vec.y == sbTL->vec.y && saBR->vec.y == sbTR->vec.y) { /* area on top of sb = S*/
+ if ((abs(saBL->vec.x - sbTL->vec.x) <= tolerance) &&
+ (abs(saBR->vec.x - sbTR->vec.x) <= tolerance)) {
return 3;
}
}
@@ -337,7 +339,7 @@ int area_getorientation(ScrArea *sa, ScrArea *sb)
/* Helper function to join 2 areas, it has a return value, 0=failed 1=success
* used by the split, join operators
*/
-int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
+int screen_area_join(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2)
{
int dir = area_getorientation(sa1, sa2);
@@ -365,32 +367,32 @@ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
if (dir == 0) { /* sa1 to right of sa2 = W */
sa1->v1 = sa2->v1; /* BL */
sa1->v2 = sa2->v2; /* TL */
- screen_geom_edge_add(scr, sa1->v2, sa1->v3);
- screen_geom_edge_add(scr, sa1->v1, sa1->v4);
+ screen_geom_edge_add(screen, sa1->v2, sa1->v3);
+ screen_geom_edge_add(screen, sa1->v1, sa1->v4);
}
else if (dir == 1) { /* sa1 to bottom of sa2 = N */
sa1->v2 = sa2->v2; /* TL */
sa1->v3 = sa2->v3; /* TR */
- screen_geom_edge_add(scr, sa1->v1, sa1->v2);
- screen_geom_edge_add(scr, sa1->v3, sa1->v4);
+ screen_geom_edge_add(screen, sa1->v1, sa1->v2);
+ screen_geom_edge_add(screen, sa1->v3, sa1->v4);
}
else if (dir == 2) { /* sa1 to left of sa2 = E */
sa1->v3 = sa2->v3; /* TR */
sa1->v4 = sa2->v4; /* BR */
- screen_geom_edge_add(scr, sa1->v2, sa1->v3);
- screen_geom_edge_add(scr, sa1->v1, sa1->v4);
+ screen_geom_edge_add(screen, sa1->v2, sa1->v3);
+ screen_geom_edge_add(screen, sa1->v1, sa1->v4);
}
else if (dir == 3) { /* sa1 on top of sa2 = S */
sa1->v1 = sa2->v1; /* BL */
sa1->v4 = sa2->v4; /* BR */
- screen_geom_edge_add(scr, sa1->v1, sa1->v2);
- screen_geom_edge_add(scr, sa1->v3, sa1->v4);
+ screen_geom_edge_add(screen, sa1->v1, sa1->v2);
+ screen_geom_edge_add(screen, sa1->v3, sa1->v4);
}
- screen_delarea(C, scr, sa2);
- BKE_screen_remove_double_scrverts(scr);
+ screen_delarea(C, screen, sa2);
+ BKE_screen_remove_double_scrverts(screen);
/* Update preview thumbnail */
- BKE_icon_changed(scr->id.icon_id);
+ BKE_icon_changed(screen->id.icon_id);
return 1;
}
@@ -398,22 +400,23 @@ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
/* ****************** EXPORTED API TO OTHER MODULES *************************** */
/* screen sets cursor based on active region */
+static void region_cursor_set_ex(wmWindow *win, ScrArea *area, ARegion *region, bool swin_changed)
+{
+ BLI_assert(WM_window_get_active_screen(win)->active_region == region);
+ if (win->tag_cursor_refresh || swin_changed || (region->type && region->type->event_cursor)) {
+ win->tag_cursor_refresh = false;
+ ED_region_cursor_set(win, area, region);
+ }
+}
+
static void region_cursor_set(wmWindow *win, bool swin_changed)
{
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) {
- if (ar == screen->active_region) {
- if (swin_changed || (ar->type && ar->type->event_cursor)) {
- if (ar->gizmo_map != NULL) {
- if (WM_gizmomap_cursor_set(ar->gizmo_map, win)) {
- return;
- }
- }
- ED_region_cursor_set(win, sa, ar);
- }
+ ED_screen_areas_iter (win, screen, area) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region == screen->active_region) {
+ region_cursor_set_ex(win, area, region, swin_changed);
return;
}
}
@@ -463,8 +466,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
screen_geom_vertices_scale(win, screen);
- ED_screen_areas_iter(win, screen, area)
- {
+ ED_screen_areas_iter (win, screen, area) {
/* set spacetype and region callbacks, calls init() */
/* sets subwindows for regions, adds handlers */
ED_area_initialize(wm, win, area);
@@ -520,65 +522,65 @@ void ED_screen_ensure_updated(wmWindowManager *wm, wmWindow *win, bScreen *scree
* Utility to exit and free an area-region. Screen level regions (menus/popups) need to be treated
* slightly differently, see #ui_region_temp_remove().
*/
-void ED_region_remove(bContext *C, ScrArea *sa, ARegion *ar)
+void ED_region_remove(bContext *C, ScrArea *area, ARegion *region)
{
- ED_region_exit(C, ar);
- BKE_area_region_free(sa->type, ar);
- BLI_freelinkN(&sa->regionbase, ar);
+ ED_region_exit(C, region);
+ BKE_area_region_free(area->type, region);
+ BLI_freelinkN(&area->regionbase, region);
}
/* *********** exit calls are for closing running stuff ******** */
-void ED_region_exit(bContext *C, ARegion *ar)
+void ED_region_exit(bContext *C, ARegion *region)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
ARegion *prevar = CTX_wm_region(C);
- if (ar->type && ar->type->exit) {
- ar->type->exit(wm, ar);
+ if (region->type && region->type->exit) {
+ region->type->exit(wm, region);
}
- CTX_wm_region_set(C, ar);
+ CTX_wm_region_set(C, region);
- WM_event_remove_handlers(C, &ar->handlers);
- WM_event_modal_handler_region_replace(win, ar, NULL);
- WM_draw_region_free(ar);
+ WM_event_remove_handlers(C, &region->handlers);
+ WM_event_modal_handler_region_replace(win, region, NULL);
+ WM_draw_region_free(region, true);
- if (ar->headerstr) {
- MEM_freeN(ar->headerstr);
- ar->headerstr = NULL;
+ if (region->headerstr) {
+ MEM_freeN(region->headerstr);
+ region->headerstr = NULL;
}
- if (ar->regiontimer) {
- WM_event_remove_timer(wm, win, ar->regiontimer);
- ar->regiontimer = NULL;
+ if (region->regiontimer) {
+ WM_event_remove_timer(wm, win, region->regiontimer);
+ region->regiontimer = NULL;
}
- WM_msgbus_clear_by_owner(wm->message_bus, ar);
+ WM_msgbus_clear_by_owner(wm->message_bus, region);
CTX_wm_region_set(C, prevar);
}
-void ED_area_exit(bContext *C, ScrArea *sa)
+void ED_area_exit(bContext *C, ScrArea *area)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
ScrArea *prevsa = CTX_wm_area(C);
- ARegion *ar;
+ ARegion *region;
- if (sa->type && sa->type->exit) {
- sa->type->exit(wm, sa);
+ if (area->type && area->type->exit) {
+ area->type->exit(wm, area);
}
- CTX_wm_area_set(C, sa);
+ CTX_wm_area_set(C, area);
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- ED_region_exit(C, ar);
+ for (region = area->regionbase.first; region; region = region->next) {
+ ED_region_exit(C, region);
}
- WM_event_remove_handlers(C, &sa->handlers);
- WM_event_modal_handler_area_replace(win, sa, NULL);
+ WM_event_remove_handlers(C, &area->handlers);
+ WM_event_modal_handler_area_replace(win, area, NULL);
CTX_wm_area_set(C, prevsa);
}
@@ -603,15 +605,15 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
screen->active_region = NULL;
- for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
- ED_region_exit(C, ar);
+ LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
+ ED_region_exit(C, region);
}
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- ED_area_exit(C, sa);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ ED_area_exit(C, area);
}
/* Don't use ED_screen_areas_iter here, it skips hidden areas. */
- for (ScrArea *sa = window->global_areas.areabase.first; sa; sa = sa->next) {
- ED_area_exit(C, sa);
+ LISTBASE_FOREACH (ScrArea *, area, &window->global_areas.areabase) {
+ ED_area_exit(C, area);
}
/* mark it available for use for other windows */
@@ -634,15 +636,15 @@ static void screen_cursor_set(wmWindow *win, const int xy[2])
{
const bScreen *screen = WM_window_get_active_screen(win);
AZone *az = NULL;
- ScrArea *sa;
+ ScrArea *area;
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- if ((az = ED_area_actionzone_find_xy(sa, xy))) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ if ((az = ED_area_actionzone_find_xy(area, xy))) {
break;
}
}
- if (sa) {
+ if (area) {
if (az->type == AZONE_AREA) {
WM_cursor_set(win, WM_CURSOR_EDIT);
}
@@ -672,97 +674,96 @@ static void screen_cursor_set(wmWindow *win, const int xy[2])
}
}
-/* called in wm_event_system.c. sets state vars in screen, cursors */
-/* event type is mouse move */
+/**
+ * Called in wm_event_system.c. sets state vars in screen, cursors.
+ * event type is mouse move.
+ */
void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2])
{
- bScreen *scr = WM_window_get_active_screen(win);
-
- if (scr) {
- ScrArea *sa = NULL;
- ARegion *ar;
- ARegion *old_ar = scr->active_region;
-
- ED_screen_areas_iter(win, scr, area_iter)
- {
- if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) {
- if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) {
- if (ED_area_azones_update(area_iter, xy) == NULL) {
- sa = area_iter;
- break;
- }
- }
- }
- }
- if (sa) {
- /* make overlap active when mouse over */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ED_region_contains_xy(ar, xy)) {
- scr->active_region = ar;
+ bScreen *screen = WM_window_get_active_screen(win);
+ if (screen == NULL) {
+ return;
+ }
+
+ ScrArea *area = NULL;
+ ARegion *region;
+ ARegion *region_prev = screen->active_region;
+
+ ED_screen_areas_iter (win, screen, area_iter) {
+ if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) {
+ if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) {
+ if (ED_area_azones_update(area_iter, xy) == NULL) {
+ area = area_iter;
break;
}
}
}
- else {
- scr->active_region = NULL;
+ }
+ if (area) {
+ /* Make overlap active when mouse over. */
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (ED_region_contains_xy(region, xy)) {
+ screen->active_region = region;
+ break;
+ }
}
+ }
+ else {
+ screen->active_region = NULL;
+ }
- /* check for redraw headers */
- if (old_ar != scr->active_region) {
+ /* Check for redraw headers. */
+ if (region_prev != screen->active_region) {
- ED_screen_areas_iter(win, scr, area_iter)
- {
- bool do_draw = false;
+ ED_screen_areas_iter (win, screen, area_iter) {
+ bool do_draw = false;
- for (ar = area_iter->regionbase.first; ar; ar = ar->next) {
+ for (region = area_iter->regionbase.first; region; region = region->next) {
- /* call old area's deactivate if assigned */
- if (ar == old_ar && area_iter->type->deactivate) {
- area_iter->type->deactivate(area_iter);
- }
+ /* Call old area's deactivate if assigned. */
+ if (region == region_prev && area_iter->type->deactivate) {
+ area_iter->type->deactivate(area_iter);
+ }
- if (ar == old_ar && ar != scr->active_region) {
- wmGizmoMap *gzmap = old_ar->gizmo_map;
- if (gzmap) {
- if (WM_gizmo_highlight_set(gzmap, NULL)) {
- ED_region_tag_redraw_no_rebuild(old_ar);
- }
+ if (region == region_prev && region != screen->active_region) {
+ wmGizmoMap *gzmap = region_prev->gizmo_map;
+ if (gzmap) {
+ if (WM_gizmo_highlight_set(gzmap, NULL)) {
+ ED_region_tag_redraw_no_rebuild(region_prev);
}
}
+ }
- if (ar == old_ar || ar == scr->active_region) {
- do_draw = true;
- }
+ if (region == region_prev || region == screen->active_region) {
+ do_draw = true;
}
+ }
- if (do_draw) {
- for (ar = area_iter->regionbase.first; ar; ar = ar->next) {
- if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
- ED_region_tag_redraw_no_rebuild(ar);
- }
+ if (do_draw) {
+ for (region = area_iter->regionbase.first; region; region = region->next) {
+ if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ ED_region_tag_redraw_no_rebuild(region);
}
}
}
}
+ }
- /* cursors, for time being set always on edges, otherwise aregion doesn't switch */
- if (scr->active_region == NULL) {
- screen_cursor_set(win, xy);
- }
- else {
- /* notifier invokes freeing the buttons... causing a bit too much redraws */
- if (old_ar != scr->active_region) {
- region_cursor_set(win, true);
-
- /* this used to be a notifier, but needs to be done immediate
- * because it can undo setting the right button as active due
- * to delayed notifier handling */
- if (C) {
- UI_screen_free_active_but(C, scr);
- }
- }
- else {
- region_cursor_set(win, false);
+ /* Cursors, for time being set always on edges,
+ * otherwise the active region doesn't switch. */
+ if (screen->active_region == NULL) {
+ screen_cursor_set(win, xy);
+ }
+ else {
+ /* Notifier invokes freeing the buttons... causing a bit too much redraws. */
+ region_cursor_set_ex(win, area, screen->active_region, region_prev != screen->active_region);
+
+ if (region_prev != screen->active_region) {
+ /* This used to be a notifier, but needs to be done immediate
+ * because it can undo setting the right button as active due
+ * to delayed notifier handling. */
+ if (C) {
+ UI_screen_free_active_but(C, screen);
}
}
}
@@ -771,19 +772,19 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2])
int ED_screen_area_active(const bContext *C)
{
wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area = CTX_wm_area(C);
- if (win && sc && sa) {
- AZone *az = ED_area_actionzone_find_xy(sa, &win->eventstate->x);
- ARegion *ar;
+ if (win && screen && area) {
+ AZone *az = ED_area_actionzone_find_xy(area, &win->eventstate->x);
+ ARegion *region;
if (az && az->type == AZONE_REGION) {
return 1;
}
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar == sc->active_region) {
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region == screen->active_region) {
return 1;
}
}
@@ -812,16 +813,16 @@ static ScrArea *screen_area_create_with_geometry(ScrAreaMap *area_map,
return screen_addarea_ex(area_map, bottom_left, top_left, top_right, bottom_right, spacetype);
}
-static void screen_area_set_geometry_rect(ScrArea *sa, const rcti *rect)
+static void screen_area_set_geometry_rect(ScrArea *area, const rcti *rect)
{
- sa->v1->vec.x = rect->xmin;
- sa->v1->vec.y = rect->ymin;
- sa->v2->vec.x = rect->xmin;
- sa->v2->vec.y = rect->ymax;
- sa->v3->vec.x = rect->xmax;
- sa->v3->vec.y = rect->ymax;
- sa->v4->vec.x = rect->xmax;
- sa->v4->vec.y = rect->ymin;
+ area->v1->vec.x = rect->xmin;
+ area->v1->vec.y = rect->ymin;
+ area->v2->vec.x = rect->xmin;
+ area->v2->vec.y = rect->ymax;
+ area->v3->vec.x = rect->xmax;
+ area->v3->vec.y = rect->ymax;
+ area->v4->vec.x = rect->xmax;
+ area->v4->vec.y = rect->ymin;
}
static void screen_global_area_refresh(wmWindow *win,
@@ -907,7 +908,7 @@ void ED_screen_global_areas_sync(wmWindow *win)
screen->flag &= ~SCREEN_COLLAPSE_STATUSBAR;
- for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) {
if (area->global->cur_fixed_height == area->global->size_min) {
if (area->spacetype == SPACE_STATUSBAR) {
screen->flag |= SCREEN_COLLAPSE_STATUSBAR;
@@ -940,8 +941,8 @@ static bScreen *screen_fullscreen_find_associated_normal_screen(const Main *bmai
for (bScreen *screen_iter = bmain->screens.first; screen_iter;
screen_iter = screen_iter->id.next) {
if ((screen_iter != screen) && ELEM(screen_iter->state, SCREENMAXIMIZED, SCREENFULL)) {
- ScrArea *sa = screen_iter->areabase.first;
- if (sa && sa->full == screen) {
+ ScrArea *area = screen_iter->areabase.first;
+ if (area && area->full == screen) {
return screen_iter;
}
}
@@ -973,8 +974,8 @@ bScreen *screen_change_prepare(
wmTimer *wt = screen_old->animtimer;
/* remove handlers referencing areas in old screen */
- for (ScrArea *sa = screen_old->areabase.first; sa; sa = sa->next) {
- WM_event_remove_area_handler(&win->modalhandlers, sa);
+ LISTBASE_FOREACH (ScrArea *, area, &screen_old->areabase) {
+ WM_event_remove_area_handler(&win->modalhandlers, area);
}
/* we put timer to sleep, so screen_exit has to think there's no timer */
@@ -995,22 +996,22 @@ bScreen *screen_change_prepare(
return NULL;
}
-void screen_change_update(bContext *C, wmWindow *win, bScreen *sc)
+void screen_change_update(bContext *C, wmWindow *win, bScreen *screen)
{
Scene *scene = WM_window_get_active_scene(win);
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
- WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
+ WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, screen);
CTX_wm_window_set(C, win); /* stores C->wm.screen... hrmf */
ED_screen_refresh(CTX_wm_manager(C), win);
- BKE_screen_view3d_scene_sync(sc, scene); /* sync new screen with scene data */
+ BKE_screen_view3d_scene_sync(screen, scene); /* sync new screen with scene data */
WM_event_add_notifier(C, NC_WINDOW, NULL);
WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTSET, layout);
/* makes button hilites work */
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(win);
}
/**
@@ -1021,16 +1022,16 @@ void screen_change_update(bContext *C, wmWindow *win, bScreen *sc)
* \warning Do NOT call in area/region queues!
* \returns if screen changing was successful.
*/
-bool ED_screen_change(bContext *C, bScreen *sc)
+bool ED_screen_change(bContext *C, bScreen *screen)
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
bScreen *screen_old = CTX_wm_screen(C);
- bScreen *screen_new = screen_change_prepare(screen_old, sc, bmain, C, win);
+ bScreen *screen_new = screen_change_prepare(screen_old, screen, bmain, C, win);
if (screen_new) {
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
- WM_window_set_active_screen(win, workspace, sc);
+ WM_window_set_active_screen(win, workspace, screen);
screen_change_update(C, win, screen_new);
return true;
@@ -1039,29 +1040,32 @@ bool ED_screen_change(bContext *C, bScreen *sc)
return false;
}
-static void screen_set_3dview_camera(Scene *scene, ViewLayer *view_layer, ScrArea *sa, View3D *v3d)
+static void screen_set_3dview_camera(Scene *scene,
+ ViewLayer *view_layer,
+ ScrArea *area,
+ View3D *v3d)
{
/* fix any cameras that are used in the 3d view but not in the scene */
BKE_screen_view3d_sync(v3d, scene);
if (!v3d->camera || !BKE_view_layer_base_find(view_layer, v3d->camera)) {
v3d->camera = BKE_view_layer_camera_find(view_layer);
- // XXX if (sc == curscreen) handle_view3d_lock();
+ // XXX if (screen == curscreen) handle_view3d_lock();
if (!v3d->camera) {
- ARegion *ar;
+ ARegion *region;
ListBase *regionbase;
/* regionbase is in different place depending if space is active */
- if (v3d == sa->spacedata.first) {
- regionbase = &sa->regionbase;
+ if (v3d == area->spacedata.first) {
+ regionbase = &area->regionbase;
}
else {
regionbase = &v3d->regionbase;
}
- for (ar = regionbase->first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
+ for (region = regionbase->first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
if (rv3d->persp == RV3D_CAMOB) {
rv3d->persp = RV3D_PERSP;
}
@@ -1101,28 +1105,28 @@ void ED_screen_scene_change(bContext *C, wmWindow *win, Scene *scene)
/* Update 3D view cameras. */
const bScreen *screen = WM_window_get_active_screen(win);
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
- screen_set_3dview_camera(scene, view_layer, sa, v3d);
+ screen_set_3dview_camera(scene, view_layer, area, v3d);
}
}
}
}
-ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
+ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *area, int type)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *newsa = NULL;
SpaceLink *newsl;
- if (!sa || sa->full == NULL) {
- newsa = ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
+ if (!area || area->full == NULL) {
+ newsa = ED_screen_state_toggle(C, win, area, SCREENMAXIMIZED);
}
if (!newsa) {
- newsa = sa;
+ newsa = area;
}
BLI_assert(newsa);
@@ -1141,40 +1145,40 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
/**
* \a was_prev_temp for the case previous space was a temporary fullscreen as well
*/
-void ED_screen_full_prevspace(bContext *C, ScrArea *sa)
+void ED_screen_full_prevspace(bContext *C, ScrArea *area)
{
- BLI_assert(sa->full);
+ BLI_assert(area->full);
- if (sa->flag & AREA_FLAG_STACKED_FULLSCREEN) {
+ if (area->flag & AREA_FLAG_STACKED_FULLSCREEN) {
/* stacked fullscreen -> only go back to previous area and don't toggle out of fullscreen */
- ED_area_prevspace(C, sa);
+ ED_area_prevspace(C, area);
}
else {
- ED_screen_restore_temp_type(C, sa);
+ ED_screen_restore_temp_type(C, area);
}
}
-void ED_screen_restore_temp_type(bContext *C, ScrArea *sa)
+void ED_screen_restore_temp_type(bContext *C, ScrArea *area)
{
- SpaceLink *sl = sa->spacedata.first;
+ SpaceLink *sl = area->spacedata.first;
/* In case nether functions below run. */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
if (sl->link_flag & SPACE_FLAG_TYPE_TEMPORARY) {
- ED_area_prevspace(C, sa);
+ ED_area_prevspace(C, area);
}
- if (sa->full) {
- ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
+ if (area->full) {
+ ED_screen_state_toggle(C, CTX_wm_window(C), area, SCREENMAXIMIZED);
}
}
/* restore a screen / area back to default operation, after temp fullscreen modes */
-void ED_screen_full_restore(bContext *C, ScrArea *sa)
+void ED_screen_full_restore(bContext *C, ScrArea *area)
{
wmWindow *win = CTX_wm_window(C);
- SpaceLink *sl = sa->spacedata.first;
+ SpaceLink *sl = area->spacedata.first;
bScreen *screen = CTX_wm_screen(C);
short state = (screen ? screen->state : SCREENMAXIMIZED);
@@ -1183,65 +1187,65 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa)
if (sl->next) {
if (sl->link_flag & SPACE_FLAG_TYPE_TEMPORARY) {
- ED_screen_full_prevspace(C, sa);
+ ED_screen_full_prevspace(C, area);
}
else {
- ED_screen_state_toggle(C, win, sa, state);
+ ED_screen_state_toggle(C, win, area, state);
}
- /* warning: 'sa' may be freed */
+ /* warning: 'area' may be freed */
}
/* otherwise just tile the area again */
else {
- ED_screen_state_toggle(C, win, sa, state);
+ ED_screen_state_toggle(C, win, area, state);
}
}
/**
* this function toggles: if area is maximized/full then the parent will be restored
*
- * \warning \a sa may be freed.
+ * \warning \a area may be freed.
*/
-ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const short state)
+ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const short state)
{
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
WorkSpace *workspace = WM_window_get_active_workspace(win);
- bScreen *sc, *oldscreen;
- ARegion *ar;
+ bScreen *screen, *oldscreen;
+ ARegion *region;
- if (sa) {
+ if (area) {
/* ensure we don't have a button active anymore, can crash when
* switching screens with tooltip open because region and tooltip
* are no longer in the same screen */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- UI_blocklist_free(C, &ar->uiblocks);
+ for (region = area->regionbase.first; region; region = region->next) {
+ UI_blocklist_free(C, &region->uiblocks);
- if (ar->regiontimer) {
- WM_event_remove_timer(wm, NULL, ar->regiontimer);
- ar->regiontimer = NULL;
+ if (region->regiontimer) {
+ WM_event_remove_timer(wm, NULL, region->regiontimer);
+ region->regiontimer = NULL;
}
}
/* prevent hanging status prints */
- ED_area_status_text(sa, NULL);
+ ED_area_status_text(area, NULL);
ED_workspace_status_text(C, NULL);
}
- if (sa && sa->full) {
+ if (area && area->full) {
WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
/* restoring back to SCREENNORMAL */
- sc = sa->full; /* the old screen to restore */
+ screen = area->full; /* the old screen to restore */
oldscreen = WM_window_get_active_screen(win); /* the one disappearing */
- BLI_assert(BKE_workspace_layout_screen_get(layout_old) != sc);
+ BLI_assert(BKE_workspace_layout_screen_get(layout_old) != screen);
BLI_assert(BKE_workspace_layout_screen_get(layout_old)->state != SCREENNORMAL);
- sc->state = SCREENNORMAL;
- sc->flag = oldscreen->flag;
+ screen->state = SCREENNORMAL;
+ screen->flag = oldscreen->flag;
/* find old area to restore from */
ScrArea *fullsa = NULL;
- for (ScrArea *old = sc->areabase.first; old; old = old->next) {
+ LISTBASE_FOREACH (ScrArea *, old, &screen->areabase) {
/* area to restore from is always first */
if (old->full && !fullsa) {
fullsa = old;
@@ -1251,7 +1255,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
old->full = NULL;
}
- sa->full = NULL;
+ area->full = NULL;
if (fullsa == NULL) {
if (G.debug & G_DEBUG) {
@@ -1262,23 +1266,22 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
if (state == SCREENFULL) {
/* unhide global areas */
- for (ScrArea *glob_area = win->global_areas.areabase.first; glob_area;
- glob_area = glob_area->next) {
+ LISTBASE_FOREACH (ScrArea *, glob_area, &win->global_areas.areabase) {
glob_area->global->flag &= ~GLOBAL_AREA_IS_HIDDEN;
}
/* restore the old side panels/header visibility */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- ar->flag = ar->flagfullscreen;
+ for (region = area->regionbase.first; region; region = region->next) {
+ region->flag = region->flagfullscreen;
}
}
- ED_area_data_swap(fullsa, sa);
+ ED_area_data_swap(fullsa, area);
/* animtimer back */
- sc->animtimer = oldscreen->animtimer;
+ screen->animtimer = oldscreen->animtimer;
oldscreen->animtimer = NULL;
- ED_screen_change(C, sc);
+ ED_screen_change(C, screen);
BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old);
@@ -1286,7 +1289,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
* screen handling as it uses the area coords which aren't updated yet.
* Without doing so, the screen handling gets wrong area coords,
* which in worst case can lead to crashes (see T43139) */
- sc->skip_handling = true;
+ screen->skip_handling = true;
}
else {
/* change from SCREENNORMAL to new state */
@@ -1303,39 +1306,38 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
layout_new = ED_workspace_layout_add(bmain, workspace, win, newname);
- sc = BKE_workspace_layout_screen_get(layout_new);
- sc->state = state;
- sc->redraws_flag = oldscreen->redraws_flag;
- sc->temp = oldscreen->temp;
- sc->flag = oldscreen->flag;
+ screen = BKE_workspace_layout_screen_get(layout_new);
+ screen->state = state;
+ screen->redraws_flag = oldscreen->redraws_flag;
+ screen->temp = oldscreen->temp;
+ screen->flag = oldscreen->flag;
/* timer */
- sc->animtimer = oldscreen->animtimer;
+ screen->animtimer = oldscreen->animtimer;
oldscreen->animtimer = NULL;
/* use random area when we have no active one, e.g. when the
* mouse is outside of the window and we open a file browser */
- if (!sa || sa->global) {
- sa = oldscreen->areabase.first;
+ if (!area || area->global) {
+ area = oldscreen->areabase.first;
}
- newa = (ScrArea *)sc->areabase.first;
+ newa = (ScrArea *)screen->areabase.first;
/* copy area */
- ED_area_data_swap(newa, sa);
- newa->flag = sa->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */
+ ED_area_data_swap(newa, area);
+ newa->flag = area->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */
if (state == SCREENFULL) {
/* temporarily hide global areas */
- for (ScrArea *glob_area = win->global_areas.areabase.first; glob_area;
- glob_area = glob_area->next) {
+ LISTBASE_FOREACH (ScrArea *, glob_area, &win->global_areas.areabase) {
glob_area->global->flag |= GLOBAL_AREA_IS_HIDDEN;
}
/* temporarily hide the side panels/header */
- for (ar = newa->regionbase.first; ar; ar = ar->next) {
- ar->flagfullscreen = ar->flag;
+ for (region = newa->regionbase.first; region; region = region->next) {
+ region->flagfullscreen = region->flag;
- if (ELEM(ar->regiontype,
+ if (ELEM(region->regiontype,
RGN_TYPE_UI,
RGN_TYPE_HEADER,
RGN_TYPE_TOOL_HEADER,
@@ -1343,21 +1345,21 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
RGN_TYPE_TOOLS,
RGN_TYPE_NAV_BAR,
RGN_TYPE_EXECUTE)) {
- ar->flag |= RGN_FLAG_HIDDEN;
+ region->flag |= RGN_FLAG_HIDDEN;
}
}
}
- sa->full = oldscreen;
+ area->full = oldscreen;
newa->full = oldscreen;
- ED_screen_change(C, sc);
+ ED_screen_change(C, screen);
}
/* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */
- CTX_wm_area_set(C, sc->areabase.first);
+ CTX_wm_area_set(C, screen->areabase.first);
- return sc->areabase.first;
+ return screen->areabase.first;
}
/**
@@ -1378,35 +1380,35 @@ ScrArea *ED_screen_temp_space_open(bContext *C,
int display_type,
bool dialog)
{
- ScrArea *sa = NULL;
+ ScrArea *area = NULL;
switch (display_type) {
case USER_TEMP_SPACE_DISPLAY_WINDOW:
if (WM_window_open_temp(C, title, x, y, sizex, sizey, (int)space_type, dialog)) {
- sa = CTX_wm_area(C);
+ area = CTX_wm_area(C);
}
break;
case USER_TEMP_SPACE_DISPLAY_FULLSCREEN: {
- ScrArea *ctx_sa = CTX_wm_area(C);
+ ScrArea *ctx_area = CTX_wm_area(C);
- if (ctx_sa != NULL && ctx_sa->full) {
- sa = ctx_sa;
- ED_area_newspace(C, ctx_sa, space_type, true);
- sa->flag |= AREA_FLAG_STACKED_FULLSCREEN;
- ((SpaceLink *)sa->spacedata.first)->link_flag |= SPACE_FLAG_TYPE_TEMPORARY;
+ if (ctx_area != NULL && ctx_area->full) {
+ area = ctx_area;
+ ED_area_newspace(C, ctx_area, space_type, true);
+ area->flag |= AREA_FLAG_STACKED_FULLSCREEN;
+ ((SpaceLink *)area->spacedata.first)->link_flag |= SPACE_FLAG_TYPE_TEMPORARY;
}
- else if (ctx_sa != NULL && ctx_sa->spacetype == space_type) {
- sa = ED_screen_state_toggle(C, CTX_wm_window(C), ctx_sa, SCREENMAXIMIZED);
+ else if (ctx_area != NULL && ctx_area->spacetype == space_type) {
+ area = ED_screen_state_toggle(C, CTX_wm_window(C), ctx_area, SCREENMAXIMIZED);
}
else {
- sa = ED_screen_full_newspace(C, ctx_sa, (int)space_type);
- ((SpaceLink *)sa->spacedata.first)->link_flag |= SPACE_FLAG_TYPE_TEMPORARY;
+ area = ED_screen_full_newspace(C, ctx_area, (int)space_type);
+ ((SpaceLink *)area->spacedata.first)->link_flag |= SPACE_FLAG_TYPE_TEMPORARY;
}
break;
}
}
- return sa;
+ return area;
}
/* update frame rate info for viewport drawing */
@@ -1441,7 +1443,7 @@ void ED_refresh_viewport_fps(bContext *C)
/* redraws: uses defines from stime->redraws
* enable: 1 - forward on, -1 - backwards on, 0 - off
*/
-void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, int enable)
+void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable)
{
bScreen *screen = CTX_wm_screen(C);
wmWindowManager *wm = CTX_wm_manager(C);
@@ -1459,7 +1461,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync,
screen->animtimer = WM_event_add_timer(wm, win, TIMER0, (1.0 / FPS));
- sad->ar = CTX_wm_region(C);
+ sad->region = CTX_wm_region(C);
/* if startframe is larger than current frame, we put currentframe on startframe.
* note: first frame then is not drawn! (ton) */
if (PRVRANGEON) {
@@ -1481,16 +1483,15 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync,
}
}
sad->redraws = redraws;
- sad->refresh = refresh;
sad->flag |= (enable < 0) ? ANIMPLAY_FLAG_REVERSE : 0;
sad->flag |= (sync == 0) ? ANIMPLAY_FLAG_NO_SYNC : (sync == 1) ? ANIMPLAY_FLAG_SYNC : 0;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
char spacetype = -1;
- if (sa) {
- spacetype = sa->spacetype;
+ if (area) {
+ spacetype = area->spacetype;
}
sad->from_anim_edit = (ELEM(spacetype, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA));
@@ -1506,17 +1507,17 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync,
static ARegion *time_top_left_3dwindow(bScreen *screen)
{
ARegion *aret = NULL;
- ScrArea *sa;
+ ScrArea *area;
int min = 10000;
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- if (ar->winrct.xmin - ar->winrct.ymin < min) {
- aret = ar;
- min = ar->winrct.xmin - ar->winrct.ymin;
+ for (area = screen->areabase.first; area; area = area->next) {
+ if (area->spacetype == SPACE_VIEW3D) {
+ ARegion *region;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ if (region->winrct.xmin - region->winrct.ymin < min) {
+ aret = region;
+ min = region->winrct.xmin - region->winrct.ymin;
}
}
}
@@ -1526,17 +1527,16 @@ static ARegion *time_top_left_3dwindow(bScreen *screen)
return aret;
}
-void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh)
+void ED_screen_animation_timer_update(bScreen *screen, int redraws)
{
if (screen && screen->animtimer) {
wmTimer *wt = screen->animtimer;
ScreenAnimData *sad = wt->customdata;
sad->redraws = redraws;
- sad->refresh = refresh;
- sad->ar = NULL;
+ sad->region = NULL;
if (redraws & TIME_REGION) {
- sad->ar = time_top_left_3dwindow(screen);
+ sad->region = time_top_left_3dwindow(screen);
}
}
}
@@ -1551,11 +1551,11 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
#ifdef DURIAN_CAMERA_SWITCH
void *camera = BKE_scene_camera_switch_find(scene);
if (camera && scene->camera != camera) {
- bScreen *sc;
+ bScreen *screen;
scene->camera = camera;
/* are there cameras in the views that are not in the scene? */
- for (sc = bmain->screens.first; sc; sc = sc->id.next) {
- BKE_screen_view3d_scene_sync(sc, scene);
+ for (screen = bmain->screens.first; screen; screen = screen->id.next) {
+ BKE_screen_view3d_scene_sync(screen, scene);
}
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
}
@@ -1572,11 +1572,11 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
*/
bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
{
- ScrArea *sa;
+ ScrArea *area;
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- switch (sa->spacetype) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ switch (area->spacetype) {
case SPACE_VIEW3D: {
View3D *v3d;
@@ -1584,12 +1584,12 @@ bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
continue;
}
- v3d = sa->spacedata.first;
+ v3d = area->spacedata.first;
if (v3d->camera && v3d->stereo3d_camera == STEREO_3D_ID) {
- ARegion *ar;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiondata && region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
if (rv3d->persp == RV3D_CAMOB) {
return true;
}
@@ -1603,7 +1603,7 @@ bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
/* images should always show in stereo, even if
* the file doesn't have views enabled */
- sima = sa->spacedata.first;
+ sima = area->spacedata.first;
if (sima->image && BKE_image_is_stereo(sima->image) &&
(sima->iuser.flag & IMA_SHOW_STEREO)) {
return true;
@@ -1617,7 +1617,7 @@ bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
continue;
}
- snode = sa->spacedata.first;
+ snode = area->spacedata.first;
if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
return true;
}
@@ -1630,7 +1630,7 @@ bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
continue;
}
- sseq = sa->spacedata.first;
+ sseq = area->spacedata.first;
if (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW)) {
return true;
}
@@ -1656,7 +1656,7 @@ Scene *ED_screen_scene_find_with_window(const bScreen *screen,
const wmWindowManager *wm,
struct wmWindow **r_window)
{
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
if (WM_window_get_active_screen(win) == screen) {
if (r_window) {
*r_window = win;
@@ -1665,7 +1665,7 @@ Scene *ED_screen_scene_find_with_window(const bScreen *screen,
}
}
- BLI_assert(0);
+ /* Can by NULL when accessing a screen that isn't active. */
return NULL;
}
@@ -1674,16 +1674,16 @@ ScrArea *ED_screen_area_find_with_spacedata(const bScreen *screen,
const bool only_visible)
{
if (only_visible) {
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacedata.first == sl) {
- return sa;
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area->spacedata.first == sl) {
+ return area;
}
}
}
else {
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (BLI_findindex(&sa->spacedata, sl) != -1) {
- return sa;
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (BLI_findindex(&area->spacedata, sl) != -1) {
+ return area;
}
}
}
@@ -1697,7 +1697,7 @@ Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm)
wmWindow *ED_screen_window_find(const bScreen *screen, const wmWindowManager *wm)
{
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
if (WM_window_get_active_screen(win) == screen) {
return win;
}
diff --git a/source/blender/editors/screen/screen_geometry.c b/source/blender/editors/screen/screen_geometry.c
index 25855382307..4069795657e 100644
--- a/source/blender/editors/screen/screen_geometry.c
+++ b/source/blender/editors/screen/screen_geometry.c
@@ -57,9 +57,9 @@ ScrVert *screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y)
BLI_addtail(&area_map->vertbase, sv);
return sv;
}
-ScrVert *screen_geom_vertex_add(bScreen *sc, short x, short y)
+ScrVert *screen_geom_vertex_add(bScreen *screen, short x, short y)
{
- return screen_geom_vertex_add_ex(AREAMAP_FROM_SCREEN(sc), x, y);
+ return screen_geom_vertex_add_ex(AREAMAP_FROM_SCREEN(screen), x, y);
}
ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2)
@@ -73,9 +73,9 @@ ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2)
BLI_addtail(&area_map->edgebase, se);
return se;
}
-ScrEdge *screen_geom_edge_add(bScreen *sc, ScrVert *v1, ScrVert *v2)
+ScrEdge *screen_geom_edge_add(bScreen *screen, ScrVert *v1, ScrVert *v2)
{
- return screen_geom_edge_add_ex(AREAMAP_FROM_SCREEN(sc), v1, v2);
+ return screen_geom_edge_add_ex(AREAMAP_FROM_SCREEN(screen), v1, v2);
}
bool screen_geom_edge_is_horizontal(ScrEdge *se)
@@ -96,7 +96,7 @@ ScrEdge *screen_geom_area_map_find_active_scredge(const ScrAreaMap *area_map,
CLAMP_MIN(safety, 2);
- for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) {
+ LISTBASE_FOREACH (ScrEdge *, se, &area_map->edgebase) {
if (screen_geom_edge_is_horizontal(se)) {
if ((se->v1->vec.y > bounds_rect->ymin) && (se->v1->vec.y < (bounds_rect->ymax - 1))) {
short min, max;
@@ -153,7 +153,7 @@ ScrEdge *screen_geom_find_active_scredge(const wmWindow *win,
* * Ensure areas have a minimum height.
* * Correctly set global areas to their fixed height.
*/
-void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
+void screen_geom_vertices_scale(const wmWindow *win, bScreen *screen)
{
rcti window_rect, screen_rect;
@@ -163,7 +163,6 @@ void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
const int screen_size_x = BLI_rcti_size_x(&screen_rect);
const int screen_size_y = BLI_rcti_size_y(&screen_rect);
ScrVert *sv = NULL;
- ScrArea *sa;
int screen_size_x_prev, screen_size_y_prev;
float min[2], max[2];
@@ -171,7 +170,7 @@ void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
min[0] = min[1] = 20000.0f;
max[0] = max[1] = 0.0f;
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ for (sv = screen->vertbase.first; sv; sv = sv->next) {
const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y};
minmax_v2v2_v2(min, max, fv);
}
@@ -184,7 +183,7 @@ void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
const float facy = ((float)screen_size_y - 1) / ((float)screen_size_y_prev - 1);
/* make sure it fits! */
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ for (sv = screen->vertbase.first; sv; sv = sv->next) {
sv->vec.x = screen_rect.xmin + round_fl_to_short((sv->vec.x - min[0]) * facx);
CLAMP(sv->vec.x, screen_rect.xmin, screen_rect.xmax - 1);
@@ -199,19 +198,19 @@ void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
if (facy > 1) {
/* Keep timeline small in video edit workspace. */
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_ACTION && sa->v1->vec.y == screen_rect.ymin &&
- screen_geom_area_height(sa) <= headery * facy + 1) {
- ScrEdge *se = BKE_screen_find_edge(sc, sa->v2, sa->v3);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area->spacetype == SPACE_ACTION && area->v1->vec.y == screen_rect.ymin &&
+ screen_geom_area_height(area) <= headery * facy + 1) {
+ ScrEdge *se = BKE_screen_find_edge(screen, area->v2, area->v3);
if (se) {
- const int yval = sa->v1->vec.y + headery - 1;
+ const int yval = area->v1->vec.y + headery - 1;
screen_geom_select_connected_edge(win, se);
/* all selected vertices get the right offset */
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ for (sv = screen->vertbase.first; sv; sv = sv->next) {
/* if is a collapsed area */
- if (sv != sa->v1 && sv != sa->v4) {
+ if (sv != area->v1 && sv != area->v4) {
if (sv->flag) {
sv->vec.y = yval;
}
@@ -223,19 +222,19 @@ void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
}
if (facy < 1) {
/* make each window at least ED_area_headersize() high */
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (screen_geom_area_height(sa) < headery) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (screen_geom_area_height(area) < headery) {
/* lower edge */
- ScrEdge *se = BKE_screen_find_edge(sc, sa->v4, sa->v1);
- if (se && sa->v1 != sa->v2) {
- const int yval = sa->v2->vec.y - headery + 1;
+ ScrEdge *se = BKE_screen_find_edge(screen, area->v4, area->v1);
+ if (se && area->v1 != area->v2) {
+ const int yval = area->v2->vec.y - headery + 1;
screen_geom_select_connected_edge(win, se);
/* all selected vertices get the right offset */
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ for (sv = screen->vertbase.first; sv; sv = sv->next) {
/* if is not a collapsed area */
- if (sv != sa->v2 && sv != sa->v3) {
+ if (sv != area->v2 && sv != area->v3) {
if (sv->flag) {
sv->vec.y = yval;
}
@@ -249,7 +248,7 @@ void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
/* Global areas have a fixed size that only changes with the DPI.
* Here we ensure that exactly this size is set. */
- for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) {
if (area->global->flag & GLOBAL_AREA_IS_HIDDEN) {
continue;
}
@@ -284,14 +283,14 @@ void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc)
/**
* \return 0 if no split is possible, otherwise the screen-coordinate at which to split.
*/
-short screen_geom_find_area_split_point(const ScrArea *sa,
+short screen_geom_find_area_split_point(const ScrArea *area,
const rcti *window_rect,
char dir,
float fac)
{
short x, y;
- const int cur_area_width = screen_geom_area_width(sa);
- const int cur_area_height = screen_geom_area_height(sa);
+ const int cur_area_width = screen_geom_area_width(area);
+ const int cur_area_height = screen_geom_area_height(area);
const short area_min_x = AREAMINX;
const short area_min_y = ED_area_headersize();
int area_min;
@@ -308,43 +307,43 @@ short screen_geom_find_area_split_point(const ScrArea *sa,
CLAMP(fac, 0.0f, 1.0f);
if (dir == 'h') {
- y = sa->v1->vec.y + round_fl_to_short(fac * cur_area_height);
+ y = area->v1->vec.y + round_fl_to_short(fac * cur_area_height);
area_min = area_min_y;
- if (sa->v1->vec.y > window_rect->ymin) {
+ if (area->v1->vec.y > window_rect->ymin) {
area_min += U.pixelsize;
}
- if (sa->v2->vec.y < (window_rect->ymax - 1)) {
+ if (area->v2->vec.y < (window_rect->ymax - 1)) {
area_min += U.pixelsize;
}
- if (y - sa->v1->vec.y < area_min) {
- y = sa->v1->vec.y + area_min;
+ if (y - area->v1->vec.y < area_min) {
+ y = area->v1->vec.y + area_min;
}
- else if (sa->v2->vec.y - y < area_min) {
- y = sa->v2->vec.y - area_min;
+ else if (area->v2->vec.y - y < area_min) {
+ y = area->v2->vec.y - area_min;
}
return y;
}
else {
- x = sa->v1->vec.x + round_fl_to_short(fac * cur_area_width);
+ x = area->v1->vec.x + round_fl_to_short(fac * cur_area_width);
area_min = area_min_x;
- if (sa->v1->vec.x > window_rect->xmin) {
+ if (area->v1->vec.x > window_rect->xmin) {
area_min += U.pixelsize;
}
- if (sa->v4->vec.x < (window_rect->xmax - 1)) {
+ if (area->v4->vec.x < (window_rect->xmax - 1)) {
area_min += U.pixelsize;
}
- if (x - sa->v1->vec.x < area_min) {
- x = sa->v1->vec.x + area_min;
+ if (x - area->v1->vec.x < area_min) {
+ x = area->v1->vec.x + area_min;
}
- else if (sa->v4->vec.x - x < area_min) {
- x = sa->v4->vec.x - area_min;
+ else if (area->v4->vec.x - x < area_min) {
+ x = area->v4->vec.x - area_min;
}
return x;
@@ -356,7 +355,7 @@ short screen_geom_find_area_split_point(const ScrArea *sa,
*/
void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge)
{
- bScreen *sc = WM_window_get_active_screen(win);
+ bScreen *screen = WM_window_get_active_screen(win);
bool oneselected = true;
char dir;
@@ -370,7 +369,7 @@ void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge)
dir = 'h';
}
- ED_screen_verts_iter(win, sc, sv)
+ ED_screen_verts_iter(win, screen, sv)
{
sv->flag = 0;
}
@@ -380,7 +379,7 @@ void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge)
while (oneselected) {
oneselected = false;
- for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
+ LISTBASE_FOREACH (ScrEdge *, se, &screen->edgebase) {
if (se->v1->flag + se->v2->flag == 1) {
if (dir == 'h') {
if (se->v1->vec.y == se->v2->vec.y) {
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index 4971b310eff..3dfc147bc73 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -36,33 +36,34 @@ struct bContextDataResult;
#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */
/* area.c */
-void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free);
+void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, const bool do_free);
void ED_area_data_swap(ScrArea *sa1, ScrArea *sa2);
-void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_fade);
+void region_toggle_hidden(struct bContext *C, ARegion *region, const bool do_fade);
/* screen_edit.c */
bScreen *screen_add(struct Main *bmain, const char *name, const rcti *rect);
void screen_data_copy(bScreen *to, bScreen *from);
void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new);
-void screen_change_update(struct bContext *C, wmWindow *win, bScreen *sc);
+void screen_change_update(struct bContext *C, wmWindow *win, bScreen *screen);
bScreen *screen_change_prepare(bScreen *screen_old,
bScreen *screen_new,
struct Main *bmain,
struct bContext *C,
wmWindow *win);
-ScrArea *area_split(const wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac, int merge);
-int screen_area_join(struct bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2);
-int area_getorientation(ScrArea *sa, ScrArea *sb);
+ScrArea *area_split(
+ const wmWindow *win, bScreen *screen, ScrArea *area, char dir, float fac, int merge);
+int screen_area_join(struct bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2);
+int area_getorientation(ScrArea *area, ScrArea *sb);
-struct AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]);
+struct AZone *ED_area_actionzone_find_xy(ScrArea *area, const int xy[2]);
/* screen_geometry.c */
int screen_geom_area_height(const ScrArea *area);
int screen_geom_area_width(const ScrArea *area);
ScrVert *screen_geom_vertex_add_ex(ScrAreaMap *area_map, short x, short y);
-ScrVert *screen_geom_vertex_add(bScreen *sc, short x, short y);
+ScrVert *screen_geom_vertex_add(bScreen *screen, short x, short y);
ScrEdge *screen_geom_edge_add_ex(ScrAreaMap *area_map, ScrVert *v1, ScrVert *v2);
-ScrEdge *screen_geom_edge_add(bScreen *sc, ScrVert *v1, ScrVert *v2);
+ScrEdge *screen_geom_edge_add(bScreen *screen, ScrVert *v1, ScrVert *v2);
bool screen_geom_edge_is_horizontal(ScrEdge *se);
ScrEdge *screen_geom_area_map_find_active_scredge(const struct ScrAreaMap *area_map,
const rcti *bounds_rect,
@@ -72,8 +73,8 @@ ScrEdge *screen_geom_find_active_scredge(const wmWindow *win,
const bScreen *screen,
const int mx,
const int my);
-void screen_geom_vertices_scale(const wmWindow *win, bScreen *sc);
-short screen_geom_find_area_split_point(const ScrArea *sa,
+void screen_geom_vertices_scale(const wmWindow *win, bScreen *screen);
+short screen_geom_find_area_split_point(const ScrArea *area,
const rcti *window_rect,
char dir,
float fac);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 14ea3aca623..5b808206935 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -26,32 +26,32 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_dlrbTree.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_object_types.h"
#include "DNA_curve_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_meta_types.h"
-#include "DNA_mesh_types.h"
+#include "DNA_lattice_types.h"
#include "DNA_mask_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
#include "DNA_node_types.h"
-#include "DNA_workspace_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_workspace_types.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_icons.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_object.h"
@@ -77,8 +77,8 @@
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "ED_sequencer.h"
-#include "ED_util.h"
#include "ED_undo.h"
+#include "ED_util.h"
#include "ED_view3d.h"
#include "RNA_access.h"
@@ -590,20 +590,20 @@ bool ED_operator_editmball(bContext *C)
bool ED_operator_mask(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacedata.first) {
- switch (sa->spacetype) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area && area->spacedata.first) {
+ switch (area->spacetype) {
case SPACE_CLIP: {
- SpaceClip *sc = sa->spacedata.first;
- return ED_space_clip_check_show_maskedit(sc);
+ SpaceClip *screen = area->spacedata.first;
+ return ED_space_clip_check_show_maskedit(screen);
}
case SPACE_SEQ: {
- SpaceSeq *sseq = sa->spacedata.first;
+ SpaceSeq *sseq = area->spacedata.first;
Scene *scene = CTX_data_scene(C);
return ED_space_sequencer_check_show_maskedit(sseq, scene);
}
case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
ViewLayer *view_layer = CTX_data_view_layer(C);
return ED_space_image_check_show_maskedit(sima, view_layer);
}
@@ -681,8 +681,8 @@ static bool actionzone_area_poll(bContext *C)
const int *xy = &win->eventstate->x;
AZone *az;
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- for (az = sa->actionzones.first; az; az = az->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ for (az = area->actionzones.first; az; az = az->next) {
if (BLI_rcti_isect_pt_v(&az->rect, xy)) {
return 1;
}
@@ -701,23 +701,25 @@ static void fullscreen_click_rcti_init(
static bool azone_clipped_rect_calc(const AZone *az, rcti *r_rect_clip)
{
- const ARegion *ar = az->ar;
+ const ARegion *region = az->region;
*r_rect_clip = az->rect;
if (az->type == AZONE_REGION) {
- if (ar->overlap && (ar->v2d.keeptot != V2D_KEEPTOT_STRICT) &&
+ if (region->overlap && (region->v2d.keeptot != V2D_KEEPTOT_STRICT) &&
/* Only when this isn't hidden (where it's displayed as an button that expands). */
- ((az->ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) == 0)) {
+ ((az->region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) == 0)) {
/* A floating region to be resized, clip by the visible region. */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
case AE_BOTTOM_TO_TOPLEFT: {
r_rect_clip->xmin = max_ii(
r_rect_clip->xmin,
- (ar->winrct.xmin + UI_view2d_view_to_region_x(&ar->v2d, ar->v2d.tot.xmin)) -
+ (region->winrct.xmin +
+ UI_view2d_view_to_region_x(&region->v2d, region->v2d.tot.xmin)) -
UI_REGION_OVERLAP_MARGIN);
r_rect_clip->xmax = min_ii(
r_rect_clip->xmax,
- (ar->winrct.xmin + UI_view2d_view_to_region_x(&ar->v2d, ar->v2d.tot.xmax)) +
+ (region->winrct.xmin +
+ UI_view2d_view_to_region_x(&region->v2d, region->v2d.tot.xmax)) +
UI_REGION_OVERLAP_MARGIN);
return true;
}
@@ -725,11 +727,13 @@ static bool azone_clipped_rect_calc(const AZone *az, rcti *r_rect_clip)
case AE_RIGHT_TO_TOPLEFT: {
r_rect_clip->ymin = max_ii(
r_rect_clip->ymin,
- (ar->winrct.ymin + UI_view2d_view_to_region_y(&ar->v2d, ar->v2d.tot.ymin)) -
+ (region->winrct.ymin +
+ UI_view2d_view_to_region_y(&region->v2d, region->v2d.tot.ymin)) -
UI_REGION_OVERLAP_MARGIN);
r_rect_clip->ymax = min_ii(
r_rect_clip->ymax,
- (ar->winrct.ymin + UI_view2d_view_to_region_y(&ar->v2d, ar->v2d.tot.ymax)) +
+ (region->winrct.ymin +
+ UI_view2d_view_to_region_y(&region->v2d, region->v2d.tot.ymax)) +
UI_REGION_OVERLAP_MARGIN);
return true;
}
@@ -739,11 +743,11 @@ static bool azone_clipped_rect_calc(const AZone *az, rcti *r_rect_clip)
return false;
}
-static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const bool test_only)
+static AZone *area_actionzone_refresh_xy(ScrArea *area, const int xy[2], const bool test_only)
{
AZone *az = NULL;
- for (az = sa->actionzones.first; az; az = az->next) {
+ for (az = area->actionzones.first; az; az = az->next) {
rcti az_rect_clip;
if (BLI_rcti_isect_pt_v(&az->rect, xy) &&
/* Check clipping if this is clipped */
@@ -770,10 +774,10 @@ static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const boo
az->alpha = 1.0f;
}
else {
- const int mouse_sq = SQUARE(xy[0] - az->x2) + SQUARE(xy[1] - az->y2);
- const int spot_sq = SQUARE(AZONESPOTW);
- const int fadein_sq = SQUARE(AZONEFADEIN);
- const int fadeout_sq = SQUARE(AZONEFADEOUT);
+ const int mouse_sq = square_i(xy[0] - az->x2) + square_i(xy[1] - az->y2);
+ const int spot_sq = square_i(AZONESPOTW);
+ const int fadein_sq = square_i(AZONEFADEIN);
+ const int fadeout_sq = square_i(AZONEFADEOUT);
if (mouse_sq < spot_sq) {
az->alpha = 1.0f;
@@ -794,16 +798,16 @@ static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const boo
}
/* XXX force redraw to show/hide the action zone */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
}
else if (az->type == AZONE_REGION_SCROLL) {
- ARegion *ar = az->ar;
- View2D *v2d = &ar->v2d;
+ ARegion *region = az->region;
+ View2D *v2d = &region->v2d;
int scroll_flag = 0;
const int isect_value = UI_view2d_mouse_in_scrollers_ex(
- ar, v2d, xy[0], xy[1], &scroll_flag);
+ region, v2d, xy[0], xy[1], &scroll_flag);
/* Check if we even have scroll bars. */
if (((az->direction == AZ_SCROLL_HOR) && !(scroll_flag & V2D_SCROLL_HORIZONTAL)) ||
@@ -833,7 +837,7 @@ static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const boo
}
}
else {
- const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin};
+ const int local_xy[2] = {xy[0] - region->winrct.xmin, xy[1] - region->winrct.ymin};
float dist_fac = 0.0f, alpha = 0.0f;
if (az->direction == AZ_SCROLL_HOR) {
@@ -855,7 +859,7 @@ static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const boo
}
if (redraw) {
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
/* Don't return! */
}
@@ -864,19 +868,19 @@ static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const boo
else if (!test_only && !IS_EQF(az->alpha, 0.0f)) {
if (az->type == AZONE_FULLSCREEN) {
az->alpha = 0.0f;
- sa->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE;
- ED_area_tag_redraw_no_rebuild(sa);
+ area->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE;
+ ED_area_tag_redraw_no_rebuild(area);
}
else if (az->type == AZONE_REGION_SCROLL) {
if (az->direction == AZ_SCROLL_VERT) {
- az->alpha = az->ar->v2d.alpha_vert = 0;
- sa->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE;
- ED_region_tag_redraw_no_rebuild(az->ar);
+ az->alpha = az->region->v2d.alpha_vert = 0;
+ area->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE;
+ ED_region_tag_redraw_no_rebuild(az->region);
}
else if (az->direction == AZ_SCROLL_HOR) {
- az->alpha = az->ar->v2d.alpha_hor = 0;
- sa->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE;
- ED_region_tag_redraw_no_rebuild(az->ar);
+ az->alpha = az->region->v2d.alpha_hor = 0;
+ area->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE;
+ ED_region_tag_redraw_no_rebuild(az->region);
}
else {
BLI_assert(0);
@@ -889,10 +893,10 @@ static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const boo
}
/* Finds an action-zone by position in entire screen so azones can overlap. */
-static AZone *screen_actionzone_find_xy(bScreen *sc, const int xy[2])
+static AZone *screen_actionzone_find_xy(bScreen *screen, const int xy[2])
{
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- AZone *az = area_actionzone_refresh_xy(sa, xy, true);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ AZone *az = area_actionzone_refresh_xy(area, xy, true);
if (az != NULL) {
return az;
}
@@ -901,10 +905,10 @@ static AZone *screen_actionzone_find_xy(bScreen *sc, const int xy[2])
}
/* Returns the area that the azone belongs to */
-static ScrArea *screen_actionzone_area(bScreen *sc, const AZone *az)
+static ScrArea *screen_actionzone_area(bScreen *screen, const AZone *az)
{
- for (ScrArea *area = sc->areabase.first; area; area = area->next) {
- for (AZone *zone = area->actionzones.first; zone; zone = zone->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (AZone *, zone, &area->actionzones) {
if (zone == az) {
return area;
}
@@ -913,14 +917,14 @@ static ScrArea *screen_actionzone_area(bScreen *sc, const AZone *az)
return NULL;
}
-AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2])
+AZone *ED_area_actionzone_find_xy(ScrArea *area, const int xy[2])
{
- return area_actionzone_refresh_xy(sa, xy, true);
+ return area_actionzone_refresh_xy(area, xy, true);
}
-AZone *ED_area_azones_update(ScrArea *sa, const int xy[2])
+AZone *ED_area_azones_update(ScrArea *area, const int xy[2])
{
- return area_actionzone_refresh_xy(sa, xy, false);
+ return area_actionzone_refresh_xy(area, xy, false);
}
static void actionzone_exit(wmOperator *op)
@@ -964,8 +968,8 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type)
static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bScreen *sc = CTX_wm_screen(C);
- AZone *az = screen_actionzone_find_xy(sc, &event->x);
+ bScreen *screen = CTX_wm_screen(C);
+ AZone *az = screen_actionzone_find_xy(screen, &event->x);
sActionzoneData *sad;
/* Quick escape - Scroll azones only hide/unhide the scroll-bars,
@@ -976,7 +980,7 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* ok we do the action-zone */
sad = op->customdata = MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
- sad->sa1 = screen_actionzone_area(sc, az);
+ sad->sa1 = screen_actionzone_area(screen, az);
sad->az = az;
sad->x = event->x;
sad->y = event->y;
@@ -999,7 +1003,7 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
sActionzoneData *sad = op->customdata;
switch (event->type) {
@@ -1010,7 +1014,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
const int delta_y = (event->y - sad->y);
/* Movement in dominant direction. */
- const int delta_max = max_ii(ABS(delta_x), ABS(delta_y));
+ const int delta_max = max_ii(abs(delta_x), abs(delta_y));
/* Movement in dominant direction before action taken. */
const int join_threshold = (0.6 * U.widget_unit);
@@ -1018,13 +1022,13 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
const int area_threshold = (0.1 * U.widget_unit);
/* Calculate gesture cardinal direction. */
- if (delta_y > ABS(delta_x)) {
+ if (delta_y > abs(delta_x)) {
sad->gesture_dir = 'n';
}
- else if (delta_x >= ABS(delta_y)) {
+ else if (delta_x >= abs(delta_y)) {
sad->gesture_dir = 'e';
}
- else if (delta_y < -ABS(delta_x)) {
+ else if (delta_y < -abs(delta_x)) {
sad->gesture_dir = 's';
}
else {
@@ -1040,9 +1044,9 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Have we dragged off the zone and are not on an edge? */
if ((ED_area_actionzone_find_xy(sad->sa1, &event->x) != sad->az) &&
(screen_geom_area_map_find_active_scredge(
- AREAMAP_FROM_SCREEN(sc), &screen_rect, event->x, event->y) == NULL)) {
+ AREAMAP_FROM_SCREEN(screen), &screen_rect, event->x, event->y) == NULL)) {
/* Are we still in same area? */
- if (BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y) == sad->sa1) {
+ if (BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y) == sad->sa1) {
/* Same area, so possible split. */
WM_cursor_set(
win, (ELEM(sad->gesture_dir, 'n', 's')) ? WM_CURSOR_H_SPLIT : WM_CURSOR_V_SPLIT);
@@ -1077,7 +1081,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* gesture is large enough? */
if (is_gesture) {
/* second area, for join when (sa1 != sa2) */
- sad->sa2 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y);
+ sad->sa2 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y);
/* apply sends event */
actionzone_apply(C, op, sad->az->type);
actionzone_exit(op);
@@ -1086,7 +1090,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
break;
}
- case ESCKEY:
+ case EVT_ESCKEY:
actionzone_exit(op);
return OPERATOR_CANCELLED;
case LEFTMOUSE:
@@ -1132,12 +1136,12 @@ static ScrEdge *screen_area_edge_from_cursor(const bContext *C,
ScrArea **r_sa2)
{
wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
ScrEdge *actedge;
rcti window_rect;
WM_window_rect_calc(win, &window_rect);
actedge = screen_geom_area_map_find_active_scredge(
- AREAMAP_FROM_SCREEN(sc), &window_rect, cursor[0], cursor[1]);
+ AREAMAP_FROM_SCREEN(screen), &window_rect, cursor[0], cursor[1]);
*r_sa1 = NULL;
*r_sa2 = NULL;
if (actedge == NULL) {
@@ -1146,12 +1150,12 @@ static ScrEdge *screen_area_edge_from_cursor(const bContext *C,
int borderwidth = (4 * UI_DPI_FAC);
ScrArea *sa1, *sa2;
if (screen_geom_edge_is_horizontal(actedge)) {
- sa1 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0], cursor[1] + borderwidth);
- sa2 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0], cursor[1] - borderwidth);
+ sa1 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, cursor[0], cursor[1] + borderwidth);
+ sa2 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, cursor[0], cursor[1] - borderwidth);
}
else {
- sa1 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0] + borderwidth, cursor[1]);
- sa2 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0] - borderwidth, cursor[1]);
+ sa1 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, cursor[0] + borderwidth, cursor[1]);
+ sa2 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, cursor[0] - borderwidth, cursor[1]);
}
bool isGlobal = ((sa1 && ED_area_is_global(sa1)) || (sa2 && ED_area_is_global(sa2)));
if (!isGlobal) {
@@ -1266,7 +1270,7 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
break;
- case ESCKEY:
+ case EVT_ESCKEY:
area_swap_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -1323,12 +1327,12 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
WorkSpaceLayout *layout_new;
bScreen *newsc;
- ScrArea *sa;
+ ScrArea *area;
rcti rect;
win = CTX_wm_window(C);
scene = CTX_data_scene(C);
- sa = CTX_wm_area(C);
+ area = CTX_wm_area(C);
/* XXX hrmf! */
if (event->type == EVT_ACTIONZONE_AREA) {
@@ -1338,11 +1342,11 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_PASS_THROUGH;
}
- sa = sad->sa1;
+ area = sad->sa1;
}
/* adds window to WM */
- rect = sa->totrct;
+ rect = area->totrct;
BLI_rcti_translate(&rect, win->posx, win->posy);
rect.xmax = rect.xmin + BLI_rcti_size_x(&rect) / U.pixelsize;
rect.ymax = rect.ymin + BLI_rcti_size_y(&rect) / U.pixelsize;
@@ -1367,7 +1371,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
WM_window_set_active_layout(newwin, workspace, layout_new);
/* copy area to new screen */
- ED_area_data_copy((ScrArea *)newsc->areabase.first, sa, true);
+ ED_area_data_copy((ScrArea *)newsc->areabase.first, area, true);
ED_area_tag_redraw((ScrArea *)newsc->areabase.first);
@@ -1450,8 +1454,12 @@ typedef struct sAreaMoveData {
/* helper call to move area-edge, sets limits
* need window bounds in order to get correct limits */
-static void area_move_set_limits(
- wmWindow *win, bScreen *sc, int dir, int *bigger, int *smaller, bool *use_bigger_smaller_snap)
+static void area_move_set_limits(wmWindow *win,
+ bScreen *screen,
+ int dir,
+ int *bigger,
+ int *smaller,
+ bool *use_bigger_smaller_snap)
{
rcti window_rect;
int areaminy = ED_area_headersize();
@@ -1462,7 +1470,7 @@ static void area_move_set_limits(
if (use_bigger_smaller_snap != NULL) {
*use_bigger_smaller_snap = false;
- for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) {
int size_min = ED_area_global_min_size_y(area) - 1;
int size_max = ED_area_global_max_size_y(area) - 1;
@@ -1503,25 +1511,25 @@ static void area_move_set_limits(
WM_window_rect_calc(win, &window_rect);
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (dir == 'h') {
int y1;
areamin = areaminy;
- if (sa->v1->vec.y > window_rect.ymin) {
+ if (area->v1->vec.y > window_rect.ymin) {
areamin += U.pixelsize;
}
- if (sa->v2->vec.y < (window_rect.ymax - 1)) {
+ if (area->v2->vec.y < (window_rect.ymax - 1)) {
areamin += U.pixelsize;
}
- y1 = screen_geom_area_height(sa) - areamin;
+ y1 = screen_geom_area_height(area) - areamin;
/* if top or down edge selected, test height */
- if (sa->v1->editflag && sa->v4->editflag) {
+ if (area->v1->editflag && area->v4->editflag) {
*bigger = min_ii(*bigger, y1);
}
- else if (sa->v2->editflag && sa->v3->editflag) {
+ else if (area->v2->editflag && area->v3->editflag) {
*smaller = min_ii(*smaller, y1);
}
}
@@ -1529,20 +1537,20 @@ static void area_move_set_limits(
int x1;
areamin = AREAMINX;
- if (sa->v1->vec.x > window_rect.xmin) {
+ if (area->v1->vec.x > window_rect.xmin) {
areamin += U.pixelsize;
}
- if (sa->v4->vec.x < (window_rect.xmax - 1)) {
+ if (area->v4->vec.x < (window_rect.xmax - 1)) {
areamin += U.pixelsize;
}
- x1 = screen_geom_area_width(sa) - areamin;
+ x1 = screen_geom_area_width(area) - areamin;
/* if left or right edge selected, test width */
- if (sa->v1->editflag && sa->v2->editflag) {
+ if (area->v1->editflag && area->v2->editflag) {
*bigger = min_ii(*bigger, x1);
}
- else if (sa->v3->editflag && sa->v4->editflag) {
+ else if (area->v3->editflag && area->v4->editflag) {
*smaller = min_ii(*smaller, x1);
}
}
@@ -1553,7 +1561,7 @@ static void area_move_set_limits(
/* return 0: init failed */
static int area_move_init(bContext *C, wmOperator *op)
{
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
wmWindow *win = CTX_wm_window(C);
ScrEdge *actedge;
sAreaMoveData *md;
@@ -1564,7 +1572,7 @@ static int area_move_init(bContext *C, wmOperator *op)
y = RNA_int_get(op->ptr, "y");
/* setup */
- actedge = screen_geom_find_active_scredge(win, sc, x, y);
+ actedge = screen_geom_find_active_scredge(win, screen, x, y);
if (actedge == NULL) {
return 0;
}
@@ -1582,20 +1590,20 @@ static int area_move_init(bContext *C, wmOperator *op)
screen_geom_select_connected_edge(win, actedge);
/* now all vertices with 'flag == 1' are the ones that can be moved. Move this to editflag */
- ED_screen_verts_iter(win, sc, v1)
+ ED_screen_verts_iter(win, screen, v1)
{
v1->editflag = v1->flag;
}
bool use_bigger_smaller_snap = false;
- area_move_set_limits(win, sc, md->dir, &md->bigger, &md->smaller, &use_bigger_smaller_snap);
+ area_move_set_limits(win, screen, md->dir, &md->bigger, &md->smaller, &use_bigger_smaller_snap);
md->snap_type = use_bigger_smaller_snap ? SNAP_BIGGER_SMALLER_ONLY : SNAP_AREAGRID;
return 1;
}
-static int area_snap_calc_location(const bScreen *sc,
+static int area_snap_calc_location(const bScreen *screen,
const enum AreaMoveSnapType snap_type,
const int delta,
const int origval,
@@ -1653,13 +1661,13 @@ static int area_snap_calc_location(const bScreen *sc,
}
}
- for (const ScrVert *v1 = sc->vertbase.first; v1; v1 = v1->next) {
+ LISTBASE_FOREACH (const ScrVert *, v1, &screen->vertbase) {
if (!v1->editflag) {
continue;
}
const int v_loc = (&v1->vec.x)[!axis];
- for (const ScrVert *v2 = sc->vertbase.first; v2; v2 = v2->next) {
+ LISTBASE_FOREACH (const ScrVert *, v2, &screen->vertbase) {
if (v2->editflag) {
continue;
}
@@ -1698,7 +1706,7 @@ static void area_move_apply_do(const bContext *C,
const enum AreaMoveSnapType snap_type)
{
wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
short final_loc = -1;
bool doredraw = false;
@@ -1710,13 +1718,13 @@ static void area_move_apply_do(const bContext *C,
final_loc = origval + delta;
}
else {
- final_loc = area_snap_calc_location(sc, snap_type, delta, origval, dir, bigger, smaller);
+ final_loc = area_snap_calc_location(screen, snap_type, delta, origval, dir, bigger, smaller);
}
BLI_assert(final_loc != -1);
short axis = (dir == 'v') ? 0 : 1;
- ED_screen_verts_iter(win, sc, v1)
+ ED_screen_verts_iter(win, screen, v1)
{
if (v1->editflag) {
short oldval = (&v1->vec.x)[axis];
@@ -1733,29 +1741,27 @@ static void area_move_apply_do(const bContext *C,
/* only redraw if we actually moved a screen vert, for AREAGRID */
if (doredraw) {
bool redraw_all = false;
- ED_screen_areas_iter(win, sc, sa)
- {
- if (sa->v1->editflag || sa->v2->editflag || sa->v3->editflag || sa->v4->editflag) {
- if (ED_area_is_global(sa)) {
+ ED_screen_areas_iter (win, screen, area) {
+ if (area->v1->editflag || area->v2->editflag || area->v3->editflag || area->v4->editflag) {
+ if (ED_area_is_global(area)) {
/* Snap to minimum or maximum for global areas. */
- int height = round_fl_to_int(screen_geom_area_height(sa) / UI_DPI_FAC);
- if (abs(height - sa->global->size_min) < abs(height - sa->global->size_max)) {
- sa->global->cur_fixed_height = sa->global->size_min;
+ int height = round_fl_to_int(screen_geom_area_height(area) / UI_DPI_FAC);
+ if (abs(height - area->global->size_min) < abs(height - area->global->size_max)) {
+ area->global->cur_fixed_height = area->global->size_min;
}
else {
- sa->global->cur_fixed_height = sa->global->size_max;
+ area->global->cur_fixed_height = area->global->size_max;
}
- sc->do_refresh = true;
+ screen->do_refresh = true;
redraw_all = true;
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
}
if (redraw_all) {
- ED_screen_areas_iter(win, sc, sa)
- {
- ED_area_tag_redraw(sa);
+ ED_screen_areas_iter (win, screen, area) {
+ ED_area_tag_redraw(area);
}
}
@@ -1763,7 +1769,7 @@ static void area_move_apply_do(const bContext *C,
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); /* redraw everything */
/* Update preview thumbnail */
- BKE_icon_changed(sc->id.icon_id);
+ BKE_icon_changed(screen->id.icon_id);
}
}
@@ -1980,13 +1986,13 @@ static int area_split_menu_init(bContext *C, wmOperator *op)
/* generic init, no UI stuff here, assumes active area */
static int area_split_init(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
sAreaSplitData *sd;
int areaminy = ED_area_headersize();
int dir;
/* required context */
- if (sa == NULL) {
+ if (area == NULL) {
return 0;
}
@@ -1994,10 +2000,10 @@ static int area_split_init(bContext *C, wmOperator *op)
dir = RNA_enum_get(op->ptr, "direction");
/* minimal size */
- if (dir == 'v' && sa->winx < 2 * AREAMINX) {
+ if (dir == 'v' && area->winx < 2 * AREAMINX) {
return 0;
}
- if (dir == 'h' && sa->winy < 2 * areaminy) {
+ if (dir == 'h' && area->winy < 2 * areaminy) {
return 0;
}
@@ -2005,42 +2011,42 @@ static int area_split_init(bContext *C, wmOperator *op)
sd = (sAreaSplitData *)MEM_callocN(sizeof(sAreaSplitData), "op_area_split");
op->customdata = sd;
- sd->sarea = sa;
+ sd->sarea = area;
if (dir == 'v') {
- sd->origmin = sa->v1->vec.x;
- sd->origsize = sa->v4->vec.x - sd->origmin;
+ sd->origmin = area->v1->vec.x;
+ sd->origsize = area->v4->vec.x - sd->origmin;
}
else {
- sd->origmin = sa->v1->vec.y;
- sd->origsize = sa->v2->vec.y - sd->origmin;
+ sd->origmin = area->v1->vec.y;
+ sd->origsize = area->v2->vec.y - sd->origmin;
}
return 1;
}
-/* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
+/* with area as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
/* used with split operator */
-static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
+static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *area, ScrArea *sb)
{
- ScrVert *sav1 = sa->v1;
- ScrVert *sav2 = sa->v2;
- ScrVert *sav3 = sa->v3;
- ScrVert *sav4 = sa->v4;
+ ScrVert *sav1 = area->v1;
+ ScrVert *sav2 = area->v2;
+ ScrVert *sav3 = area->v3;
+ ScrVert *sav4 = area->v4;
ScrVert *sbv1 = sb->v1;
ScrVert *sbv2 = sb->v2;
ScrVert *sbv3 = sb->v3;
ScrVert *sbv4 = sb->v4;
- if (sav1 == sbv4 && sav2 == sbv3) { /* sa to right of sb = W */
+ if (sav1 == sbv4 && sav2 == sbv3) { /* area to right of sb = W */
return BKE_screen_find_edge(screen, sav1, sav2);
}
- else if (sav2 == sbv1 && sav3 == sbv4) { /* sa to bottom of sb = N */
+ else if (sav2 == sbv1 && sav3 == sbv4) { /* area to bottom of sb = N */
return BKE_screen_find_edge(screen, sav2, sav3);
}
- else if (sav3 == sbv2 && sav4 == sbv1) { /* sa to left of sb = E */
+ else if (sav3 == sbv2 && sav4 == sbv1) { /* area to left of sb = E */
return BKE_screen_find_edge(screen, sav3, sav4);
}
- else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/
+ else if (sav1 == sbv2 && sav4 == sbv3) { /* area on top of sb = S*/
return BKE_screen_find_edge(screen, sav1, sav4);
}
@@ -2051,7 +2057,7 @@ static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
static int area_split_apply(bContext *C, wmOperator *op)
{
const wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
float fac;
int dir;
@@ -2059,13 +2065,13 @@ static int area_split_apply(bContext *C, wmOperator *op)
fac = RNA_float_get(op->ptr, "factor");
dir = RNA_enum_get(op->ptr, "direction");
- sd->narea = area_split(win, sc, sd->sarea, dir, fac, 0); /* 0 = no merge */
+ sd->narea = area_split(win, screen, sd->sarea, dir, fac, 0); /* 0 = no merge */
if (sd->narea) {
- sd->nedge = area_findsharededge(sc, sd->sarea, sd->narea);
+ sd->nedge = area_findsharededge(screen, sd->sarea, sd->narea);
/* select newly created edge, prepare for moving edge */
- ED_screen_verts_iter(win, sc, sv)
+ ED_screen_verts_iter(win, screen, sv)
{
sv->editflag = 0;
}
@@ -2085,7 +2091,7 @@ static int area_split_apply(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
/* Update preview thumbnail */
- BKE_icon_changed(sc->id.icon_id);
+ BKE_icon_changed(screen->id.icon_id);
return 1;
}
@@ -2133,12 +2139,12 @@ static void area_split_preview_update_cursor(bContext *C, wmOperator *op)
static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
sAreaSplitData *sd;
int dir;
/* no full window splitting allowed */
- BLI_assert(sc->state == SCREENNORMAL);
+ BLI_assert(screen->state == SCREENNORMAL);
PropertyRNA *prop_dir = RNA_struct_find_property(op->ptr, "direction");
PropertyRNA *prop_factor = RNA_struct_find_property(op->ptr, "factor");
@@ -2194,18 +2200,18 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
}
else if (RNA_property_is_set(op->ptr, prop_dir)) {
- ScrArea *sa = CTX_wm_area(C);
- if (sa == NULL) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area == NULL) {
return OPERATOR_CANCELLED;
}
dir = RNA_property_enum_get(op->ptr, prop_dir);
if (dir == 'h') {
RNA_property_float_set(
- op->ptr, prop_factor, ((float)(event->x - sa->v1->vec.x)) / (float)sa->winx);
+ op->ptr, prop_factor, ((float)(event->x - area->v1->vec.x)) / (float)area->winx);
}
else {
RNA_property_float_set(
- op->ptr, prop_factor, ((float)(event->y - sa->v1->vec.y)) / (float)sa->winy);
+ op->ptr, prop_factor, ((float)(event->y - area->v1->vec.y)) / (float)area->winy);
}
if (!area_split_init(C, op)) {
@@ -2228,7 +2234,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
WM_window_rect_calc(win, &window_rect);
actedge = screen_geom_area_map_find_active_scredge(
- AREAMAP_FROM_SCREEN(sc), &window_rect, event_co[0], event_co[1]);
+ AREAMAP_FROM_SCREEN(screen), &window_rect, event_co[0], event_co[1]);
if (actedge == NULL) {
return OPERATOR_CANCELLED;
}
@@ -2249,7 +2255,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* do the split */
if (area_split_apply(C, op)) {
- area_move_set_limits(win, sc, dir, &sd->bigger, &sd->smaller, NULL);
+ area_move_set_limits(win, screen, dir, &sd->bigger, &sd->smaller, NULL);
/* add temp handler for edge move or cancel */
G.moving |= G_TRANSFORM_WM;
@@ -2331,7 +2337,7 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
case MIDDLEMOUSE:
- case TABKEY:
+ case EVT_TABKEY:
if (sd->previewmode == 0) {
/* pass */
}
@@ -2349,11 +2355,11 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
case RIGHTMOUSE: /* cancel operation */
- case ESCKEY:
+ case EVT_ESCKEY:
area_split_cancel(C, op);
return OPERATOR_CANCELLED;
- case LEFTCTRLKEY:
+ case EVT_LEFTCTRLKEY:
sd->do_snap = event->val == KM_PRESS;
update_factor = true;
break;
@@ -2385,18 +2391,18 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
sd->sarea = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y);
if (sd->sarea) {
- ScrArea *sa = sd->sarea;
+ ScrArea *area = sd->sarea;
if (dir == 'v') {
- sd->origmin = sa->v1->vec.x;
- sd->origsize = sa->v4->vec.x - sd->origmin;
+ sd->origmin = area->v1->vec.x;
+ sd->origsize = area->v4->vec.x - sd->origmin;
}
else {
- sd->origmin = sa->v1->vec.y;
- sd->origsize = sa->v2->vec.y - sd->origmin;
+ sd->origmin = area->v1->vec.y;
+ sd->origsize = area->v2->vec.y - sd->origmin;
}
if (sd->do_snap) {
- sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 1;
+ area->v1->editflag = area->v2->editflag = area->v3->editflag = area->v4->editflag = 1;
const int snap_loc = area_snap_calc_location(CTX_wm_screen(C),
SNAP_FRACTION_AND_ADJACENT,
@@ -2406,7 +2412,7 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
sd->origmin + sd->origsize,
-sd->origmin);
- sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 0;
+ area->v1->editflag = area->v2->editflag = area->v3->editflag = area->v4->editflag = 0;
sd->delta = snap_loc - sd->origval;
}
@@ -2460,8 +2466,8 @@ static void SCREEN_OT_area_split(wmOperatorType *ot)
typedef struct RegionMoveData {
AZone *az;
- ARegion *ar;
- ScrArea *sa;
+ ARegion *region;
+ ScrArea *area;
int bigger, smaller, origval;
int origx, origy;
int maxsize;
@@ -2469,7 +2475,7 @@ typedef struct RegionMoveData {
} RegionMoveData;
-static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge)
+static int area_max_regionsize(ScrArea *area, ARegion *scalear, AZEdge edge)
{
int dist;
@@ -2478,44 +2484,46 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge)
const int align = RGN_ALIGN_ENUM_FROM_MASK(scalear->alignment);
if (ELEM(align, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
- ARegion *ar = scalear->prev;
- dist = ar->winy + scalear->winy - U.pixelsize;
+ ARegion *region = scalear->prev;
+ dist = region->winy + scalear->winy - U.pixelsize;
}
else /* if (ELEM(align, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) */ {
- ARegion *ar = scalear->prev;
- dist = ar->winx + scalear->winx - U.pixelsize;
+ ARegion *region = scalear->prev;
+ dist = region->winx + scalear->winx - U.pixelsize;
}
}
else {
if (edge == AE_RIGHT_TO_TOPLEFT || edge == AE_LEFT_TO_TOPRIGHT) {
- dist = BLI_rcti_size_x(&sa->totrct);
+ dist = BLI_rcti_size_x(&area->totrct);
}
else { /* AE_BOTTOM_TO_TOPLEFT, AE_TOP_TO_BOTTOMRIGHT */
- dist = BLI_rcti_size_y(&sa->totrct);
+ dist = BLI_rcti_size_y(&area->totrct);
}
/* subtractwidth of regions on opposite side
* prevents dragging regions into other opposite regions */
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar == scalear) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region == scalear) {
continue;
}
- if (scalear->alignment == RGN_ALIGN_LEFT && ar->alignment == RGN_ALIGN_RIGHT) {
- dist -= ar->winx;
+ if (scalear->alignment == RGN_ALIGN_LEFT && region->alignment == RGN_ALIGN_RIGHT) {
+ dist -= region->winx;
}
- else if (scalear->alignment == RGN_ALIGN_RIGHT && ar->alignment == RGN_ALIGN_LEFT) {
- dist -= ar->winx;
+ else if (scalear->alignment == RGN_ALIGN_RIGHT && region->alignment == RGN_ALIGN_LEFT) {
+ dist -= region->winx;
}
else if (scalear->alignment == RGN_ALIGN_TOP &&
- (ar->alignment == RGN_ALIGN_BOTTOM ||
- ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_FOOTER))) {
- dist -= ar->winy;
+ (region->alignment == RGN_ALIGN_BOTTOM ||
+ ELEM(
+ region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_FOOTER))) {
+ dist -= region->winy;
}
else if (scalear->alignment == RGN_ALIGN_BOTTOM &&
- (ar->alignment == RGN_ALIGN_TOP ||
- ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_FOOTER))) {
- dist -= ar->winy;
+ (region->alignment == RGN_ALIGN_TOP ||
+ ELEM(
+ region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_FOOTER))) {
+ dist -= region->winy;
}
}
}
@@ -2552,7 +2560,7 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event
az = sad->az;
- if (az->ar) {
+ if (az->region) {
RegionMoveData *rmd = MEM_callocN(sizeof(RegionMoveData), "RegionMoveData");
op->customdata = rmd;
@@ -2561,33 +2569,33 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* special case for region within region - this allows the scale of
* the parent region if the azone edge is not the edge splitting
* both regions */
- if ((az->ar->alignment & RGN_SPLIT_PREV) && az->ar->prev &&
- !is_split_edge(RGN_ALIGN_ENUM_FROM_MASK(az->ar->alignment), az->edge)) {
- rmd->ar = az->ar->prev;
+ if ((az->region->alignment & RGN_SPLIT_PREV) && az->region->prev &&
+ !is_split_edge(RGN_ALIGN_ENUM_FROM_MASK(az->region->alignment), az->edge)) {
+ rmd->region = az->region->prev;
}
else {
- rmd->ar = az->ar;
+ rmd->region = az->region;
}
- rmd->sa = sad->sa1;
+ rmd->area = sad->sa1;
rmd->edge = az->edge;
rmd->origx = event->x;
rmd->origy = event->y;
- rmd->maxsize = area_max_regionsize(rmd->sa, rmd->ar, rmd->edge);
+ rmd->maxsize = area_max_regionsize(rmd->area, rmd->region, rmd->edge);
/* if not set we do now, otherwise it uses type */
- if (rmd->ar->sizex == 0) {
- rmd->ar->sizex = rmd->ar->winx;
+ if (rmd->region->sizex == 0) {
+ rmd->region->sizex = rmd->region->winx;
}
- if (rmd->ar->sizey == 0) {
- rmd->ar->sizey = rmd->ar->winy;
+ if (rmd->region->sizey == 0) {
+ rmd->region->sizey = rmd->region->winy;
}
/* now copy to regionmovedata */
if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) {
- rmd->origval = rmd->ar->sizex;
+ rmd->origval = rmd->region->sizex;
}
else {
- rmd->origval = rmd->ar->sizey;
+ rmd->origval = rmd->region->sizey;
}
CLAMP(rmd->maxsize, 0, 1000);
@@ -2604,14 +2612,14 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event
static void region_scale_validate_size(RegionMoveData *rmd)
{
- if ((rmd->ar->flag & RGN_FLAG_HIDDEN) == 0) {
+ if ((rmd->region->flag & RGN_FLAG_HIDDEN) == 0) {
short *size, maxsize = -1;
if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) {
- size = &rmd->ar->sizex;
+ size = &rmd->region->sizex;
}
else {
- size = &rmd->ar->sizey;
+ size = &rmd->region->sizey;
}
maxsize = rmd->maxsize - (UI_UNIT_Y / UI_DPI_FAC);
@@ -2626,20 +2634,20 @@ static void region_scale_toggle_hidden(bContext *C, RegionMoveData *rmd)
{
/* hidden areas may have bad 'View2D.cur' value,
* correct before displaying. see T45156 */
- if (rmd->ar->flag & RGN_FLAG_HIDDEN) {
- UI_view2d_curRect_validate(&rmd->ar->v2d);
+ if (rmd->region->flag & RGN_FLAG_HIDDEN) {
+ UI_view2d_curRect_validate(&rmd->region->v2d);
}
- region_toggle_hidden(C, rmd->ar, 0);
+ region_toggle_hidden(C, rmd->region, 0);
region_scale_validate_size(rmd);
- if ((rmd->ar->flag & RGN_FLAG_HIDDEN) == 0) {
- if (rmd->ar->regiontype == RGN_TYPE_HEADER) {
- ARegion *ar_tool_header = BKE_area_find_region_type(rmd->sa, RGN_TYPE_TOOL_HEADER);
- if (ar_tool_header != NULL) {
- if ((ar_tool_header->flag & RGN_FLAG_HIDDEN_BY_USER) == 0 &&
- (ar_tool_header->flag & RGN_FLAG_HIDDEN) != 0) {
- region_toggle_hidden(C, ar_tool_header, 0);
+ if ((rmd->region->flag & RGN_FLAG_HIDDEN) == 0) {
+ if (rmd->region->regiontype == RGN_TYPE_HEADER) {
+ ARegion *region_tool_header = BKE_area_find_region_type(rmd->area, RGN_TYPE_TOOL_HEADER);
+ if (region_tool_header != NULL) {
+ if ((region_tool_header->flag & RGN_FLAG_HIDDEN_BY_USER) == 0 &&
+ (region_tool_header->flag & RGN_FLAG_HIDDEN) != 0) {
+ region_toggle_hidden(C, region_tool_header, 0);
}
}
}
@@ -2654,8 +2662,8 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* execute the events */
switch (event->type) {
case MOUSEMOVE: {
- const float aspect = BLI_rctf_size_x(&rmd->ar->v2d.cur) /
- (BLI_rcti_size_x(&rmd->ar->v2d.mask) + 1);
+ const float aspect = BLI_rctf_size_x(&rmd->region->v2d.cur) /
+ (BLI_rcti_size_x(&rmd->region->v2d.mask) + 1);
const int snap_size_threshold = (U.widget_unit * 2) / aspect;
if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) {
delta = event->x - rmd->origx;
@@ -2667,27 +2675,27 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
delta /= UI_DPI_FAC;
const int size_no_snap = rmd->origval + delta;
- rmd->ar->sizex = size_no_snap;
+ rmd->region->sizex = size_no_snap;
- if (rmd->ar->type->snap_size) {
- short sizex_test = rmd->ar->type->snap_size(rmd->ar, rmd->ar->sizex, 0);
- if (ABS(rmd->ar->sizex - sizex_test) < snap_size_threshold) {
- rmd->ar->sizex = sizex_test;
+ if (rmd->region->type->snap_size) {
+ short sizex_test = rmd->region->type->snap_size(rmd->region, rmd->region->sizex, 0);
+ if (abs(rmd->region->sizex - sizex_test) < snap_size_threshold) {
+ rmd->region->sizex = sizex_test;
}
}
- CLAMP(rmd->ar->sizex, 0, rmd->maxsize);
+ CLAMP(rmd->region->sizex, 0, rmd->maxsize);
if (size_no_snap < UI_UNIT_X / aspect) {
- rmd->ar->sizex = rmd->origval;
- if (!(rmd->ar->flag & RGN_FLAG_HIDDEN)) {
+ rmd->region->sizex = rmd->origval;
+ if (!(rmd->region->flag & RGN_FLAG_HIDDEN)) {
region_scale_toggle_hidden(C, rmd);
}
}
- else if (rmd->ar->flag & RGN_FLAG_HIDDEN) {
+ else if (rmd->region->flag & RGN_FLAG_HIDDEN) {
region_scale_toggle_hidden(C, rmd);
}
- else if (rmd->ar->flag & RGN_FLAG_DYNAMIC_SIZE) {
- rmd->ar->sizex = rmd->origval;
+ else if (rmd->region->flag & RGN_FLAG_DYNAMIC_SIZE) {
+ rmd->region->sizex = rmd->origval;
}
}
else {
@@ -2700,33 +2708,33 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
delta /= UI_DPI_FAC;
const int size_no_snap = rmd->origval + delta;
- rmd->ar->sizey = size_no_snap;
+ rmd->region->sizey = size_no_snap;
- if (rmd->ar->type->snap_size) {
- short sizey_test = rmd->ar->type->snap_size(rmd->ar, rmd->ar->sizey, 1);
- if (ABS(rmd->ar->sizey - sizey_test) < snap_size_threshold) {
- rmd->ar->sizey = sizey_test;
+ if (rmd->region->type->snap_size) {
+ short sizey_test = rmd->region->type->snap_size(rmd->region, rmd->region->sizey, 1);
+ if (abs(rmd->region->sizey - sizey_test) < snap_size_threshold) {
+ rmd->region->sizey = sizey_test;
}
}
- CLAMP(rmd->ar->sizey, 0, rmd->maxsize);
+ CLAMP(rmd->region->sizey, 0, rmd->maxsize);
/* note, 'UI_UNIT_Y/4' means you need to drag the footer and execute region
* almost all the way down for it to become hidden, this is done
* otherwise its too easy to do this by accident */
if (size_no_snap < (UI_UNIT_Y / 4) / aspect) {
- rmd->ar->sizey = rmd->origval;
- if (!(rmd->ar->flag & RGN_FLAG_HIDDEN)) {
+ rmd->region->sizey = rmd->origval;
+ if (!(rmd->region->flag & RGN_FLAG_HIDDEN)) {
region_scale_toggle_hidden(C, rmd);
}
}
- else if (rmd->ar->flag & RGN_FLAG_HIDDEN) {
+ else if (rmd->region->flag & RGN_FLAG_HIDDEN) {
region_scale_toggle_hidden(C, rmd);
}
- else if (rmd->ar->flag & RGN_FLAG_DYNAMIC_SIZE) {
- rmd->ar->sizey = rmd->origval;
+ else if (rmd->region->flag & RGN_FLAG_DYNAMIC_SIZE) {
+ rmd->region->sizey = rmd->origval;
}
}
- ED_area_tag_redraw(rmd->sa);
+ ED_area_tag_redraw(rmd->area);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
break;
@@ -2734,14 +2742,14 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
if (event->val == KM_RELEASE) {
if (len_manhattan_v2v2_int(&event->x, &rmd->origx) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
- if (rmd->ar->flag & RGN_FLAG_HIDDEN) {
+ if (rmd->region->flag & RGN_FLAG_HIDDEN) {
region_scale_toggle_hidden(C, rmd);
}
- else if (rmd->ar->flag & RGN_FLAG_TOO_SMALL) {
+ else if (rmd->region->flag & RGN_FLAG_TOO_SMALL) {
region_scale_validate_size(rmd);
}
- ED_area_tag_redraw(rmd->sa);
+ ED_area_tag_redraw(rmd->area);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
}
@@ -2751,7 +2759,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
break;
- case ESCKEY:
+ case EVT_ESCKEY:
break;
}
@@ -2788,35 +2796,36 @@ static void SCREEN_OT_region_scale(wmOperatorType *ot)
static void areas_do_frame_follow(bContext *C, bool middle)
{
- bScreen *scr = CTX_wm_screen(C);
+ bScreen *screen_ctx = CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
- for (wmWindow *window = wm->windows.first; window; window = window->next) {
+ LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
const bScreen *screen = WM_window_get_active_screen(window);
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
/* do follow here if editor type supports it */
- if ((scr->redraws_flag & TIME_FOLLOW)) {
- if ((ar->regiontype == RGN_TYPE_WINDOW &&
- ELEM(sa->spacetype, SPACE_SEQ, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA)) ||
- (sa->spacetype == SPACE_CLIP && ar->regiontype == RGN_TYPE_PREVIEW)) {
- float w = BLI_rctf_size_x(&ar->v2d.cur);
+ if ((screen_ctx->redraws_flag & TIME_FOLLOW)) {
+ if ((region->regiontype == RGN_TYPE_WINDOW &&
+ ELEM(area->spacetype, SPACE_SEQ, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA)) ||
+ (area->spacetype == SPACE_CLIP && region->regiontype == RGN_TYPE_PREVIEW)) {
+ float w = BLI_rctf_size_x(&region->v2d.cur);
if (middle) {
- if ((scene->r.cfra < ar->v2d.cur.xmin) || (scene->r.cfra > ar->v2d.cur.xmax)) {
- ar->v2d.cur.xmax = scene->r.cfra + (w / 2);
- ar->v2d.cur.xmin = scene->r.cfra - (w / 2);
+ if ((scene->r.cfra < region->v2d.cur.xmin) ||
+ (scene->r.cfra > region->v2d.cur.xmax)) {
+ region->v2d.cur.xmax = scene->r.cfra + (w / 2);
+ region->v2d.cur.xmin = scene->r.cfra - (w / 2);
}
}
else {
- if (scene->r.cfra < ar->v2d.cur.xmin) {
- ar->v2d.cur.xmax = scene->r.cfra;
- ar->v2d.cur.xmin = ar->v2d.cur.xmax - w;
+ if (scene->r.cfra < region->v2d.cur.xmin) {
+ region->v2d.cur.xmax = scene->r.cfra;
+ region->v2d.cur.xmin = region->v2d.cur.xmax - w;
}
- else if (scene->r.cfra > ar->v2d.cur.xmax) {
- ar->v2d.cur.xmin = scene->r.cfra;
- ar->v2d.cur.xmax = ar->v2d.cur.xmin + w;
+ else if (scene->r.cfra > region->v2d.cur.xmax) {
+ region->v2d.cur.xmin = scene->r.cfra;
+ region->v2d.cur.xmax = region->v2d.cur.xmin + w;
}
}
}
@@ -3135,7 +3144,7 @@ static void SCREEN_OT_screen_set(wmOperatorType *ot)
ot->poll = ED_operator_screenactive;
/* rna */
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "delta", 1, -1, 1, "Delta", "", -1, 1);
}
/** \} */
@@ -3148,32 +3157,32 @@ static void SCREEN_OT_screen_set(wmOperatorType *ot)
static int screen_maximize_area_exec(bContext *C, wmOperator *op)
{
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = NULL;
+ ScrArea *area = NULL;
const bool hide_panels = RNA_boolean_get(op->ptr, "use_hide_panels");
/* search current screen for 'fullscreen' areas */
/* prevents restoring info header, when mouse is over it */
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->full) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ if (area->full) {
break;
}
}
- if (sa == NULL) {
- sa = CTX_wm_area(C);
+ if (area == NULL) {
+ area = CTX_wm_area(C);
}
if (hide_panels) {
if (!ELEM(screen->state, SCREENNORMAL, SCREENFULL)) {
return OPERATOR_CANCELLED;
}
- ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENFULL);
+ ED_screen_state_toggle(C, CTX_wm_window(C), area, SCREENFULL);
}
else {
if (!ELEM(screen->state, SCREENNORMAL, SCREENMAXIMIZED)) {
return OPERATOR_CANCELLED;
}
- ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
+ ED_screen_state_toggle(C, CTX_wm_window(C), area, SCREENMAXIMIZED);
}
return OPERATOR_FINISHED;
@@ -3374,7 +3383,7 @@ static void area_join_cancel(bContext *C, wmOperator *op)
/* modal callback while selecting area (space) that will be removed */
static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
wmWindow *win = CTX_wm_window(C);
sAreaJoinData *jd;
@@ -3389,24 +3398,24 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case MOUSEMOVE: {
- ScrArea *sa = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y);
+ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y);
int dir = -1;
- if (sa) {
- if (jd->sa1 != sa) {
- dir = area_getorientation(jd->sa1, sa);
+ if (area) {
+ if (jd->sa1 != area) {
+ dir = area_getorientation(jd->sa1, area);
if (dir != -1) {
- jd->sa2 = sa;
+ jd->sa2 = area;
}
else {
/* we are not bordering on the previously selected area
* we check if area has common border with the one marked for removal
* in this case we can swap areas.
*/
- dir = area_getorientation(sa, jd->sa2);
+ dir = area_getorientation(area, jd->sa2);
if (dir != -1) {
jd->sa1 = jd->sa2;
- jd->sa2 = sa;
+ jd->sa2 = area;
}
else {
jd->sa2 = NULL;
@@ -3419,16 +3428,16 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
* we swap the areas if possible to allow user to choose */
if (jd->sa2 != NULL) {
jd->sa1 = jd->sa2;
- jd->sa2 = sa;
+ jd->sa2 = area;
dir = area_getorientation(jd->sa1, jd->sa2);
if (dir == -1) {
printf("oops, didn't expect that!\n");
}
}
else {
- dir = area_getorientation(jd->sa1, sa);
+ dir = area_getorientation(jd->sa1, area);
if (dir != -1) {
- jd->sa2 = sa;
+ jd->sa2 = area;
}
}
WM_event_add_notifier(C, NC_WINDOW, NULL);
@@ -3466,7 +3475,7 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
case RIGHTMOUSE:
- case ESCKEY:
+ case EVT_ESCKEY:
area_join_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -3605,18 +3614,18 @@ static int spacedata_cleanup_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
bScreen *screen;
- ScrArea *sa;
+ ScrArea *area;
int tot = 0;
for (screen = bmain->screens.first; screen; screen = screen->id.next) {
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacedata.first != sa->spacedata.last) {
- SpaceLink *sl = sa->spacedata.first;
-
- BLI_remlink(&sa->spacedata, sl);
- tot += BLI_listbase_count(&sa->spacedata);
- BKE_spacedata_freelist(&sa->spacedata);
- BLI_addtail(&sa->spacedata, sl);
+ for (area = screen->areabase.first; area; area = area->next) {
+ if (area->spacedata.first != area->spacedata.last) {
+ SpaceLink *sl = area->spacedata.first;
+
+ BLI_remlink(&area->spacedata, sl);
+ tot += BLI_listbase_count(&area->spacedata);
+ BKE_spacedata_freelist(&area->spacedata);
+ BLI_addtail(&area->spacedata, sl);
}
}
}
@@ -3802,100 +3811,105 @@ static void view3d_localview_update_rv3d(struct RegionView3D *rv3d)
}
static void region_quadview_init_rv3d(
- ScrArea *sa, ARegion *ar, const char viewlock, const char view, const char persp)
+ ScrArea *area, ARegion *region, const char viewlock, const char view, const char persp)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (persp == RV3D_CAMOB) {
ED_view3d_lastview_store(rv3d);
}
rv3d->viewlock = viewlock;
+ rv3d->runtime_viewlock = 0;
rv3d->view = view;
+ rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
rv3d->persp = persp;
ED_view3d_lock(rv3d);
view3d_localview_update_rv3d(rv3d);
if ((viewlock & RV3D_BOXCLIP) && (persp == RV3D_ORTHO)) {
- ED_view3d_quadview_update(sa, ar, true);
+ ED_view3d_quadview_update(area, region, true);
}
}
/* insert a region in the area region list */
static int region_quadview_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* some rules... */
- if (ar->regiontype != RGN_TYPE_WINDOW) {
+ if (region->regiontype != RGN_TYPE_WINDOW) {
BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-split");
}
- else if (ar->alignment == RGN_ALIGN_QSPLIT) {
+ else if (region->alignment == RGN_ALIGN_QSPLIT) {
/* Exit quad-view */
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
ARegion *arn;
/* keep current region */
- ar->alignment = 0;
+ region->alignment = 0;
- if (sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar_iter;
- RegionView3D *rv3d = ar->regiondata;
+ if (area->spacetype == SPACE_VIEW3D) {
+ ARegion *region_iter;
+ RegionView3D *rv3d = region->regiondata;
/* if this is a locked view, use settings from 'User' view */
if (rv3d->viewlock) {
View3D *v3d_user;
- ARegion *ar_user;
+ ARegion *region_user;
- if (ED_view3d_context_user_region(C, &v3d_user, &ar_user)) {
- if (ar != ar_user) {
- SWAP(void *, ar->regiondata, ar_user->regiondata);
- rv3d = ar->regiondata;
+ if (ED_view3d_context_user_region(C, &v3d_user, &region_user)) {
+ if (region != region_user) {
+ SWAP(void *, region->regiondata, region_user->regiondata);
+ rv3d = region->regiondata;
}
}
}
rv3d->viewlock_quad = RV3D_VIEWLOCK_INIT;
rv3d->viewlock = 0;
- rv3d->rflag &= ~RV3D_CLIPPING;
+
+ /* FIXME: This fixes missing update to workbench TAA. (see T76216)
+ * However, it would be nice if the tagging should be done in a more conventional way. */
+ rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
/* Accumulate locks, in case they're mixed. */
- for (ar_iter = sa->regionbase.first; ar_iter; ar_iter = ar_iter->next) {
- if (ar_iter->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d_iter = ar_iter->regiondata;
+ for (region_iter = area->regionbase.first; region_iter; region_iter = region_iter->next) {
+ if (region_iter->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d_iter = region_iter->regiondata;
rv3d->viewlock_quad |= rv3d_iter->viewlock;
}
}
}
- for (ar = sa->regionbase.first; ar; ar = arn) {
- arn = ar->next;
- if (ar->alignment == RGN_ALIGN_QSPLIT) {
- ED_region_remove(C, sa, ar);
+ for (region = area->regionbase.first; region; region = arn) {
+ arn = region->next;
+ if (region->alignment == RGN_ALIGN_QSPLIT) {
+ ED_region_remove(C, area, region);
}
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
}
- else if (ar->next) {
+ else if (region->next) {
BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-split");
}
else {
/* Enter quad-view */
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
ARegion *newar;
int count;
- ar->alignment = RGN_ALIGN_QSPLIT;
+ region->alignment = RGN_ALIGN_QSPLIT;
for (count = 0; count < 3; count++) {
- newar = BKE_area_region_copy(sa->type, ar);
- BLI_addtail(&sa->regionbase, newar);
+ newar = BKE_area_region_copy(area->type, region);
+ BLI_addtail(&area->regionbase, newar);
}
/* lock views and set them */
- if (sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
+ if (area->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = area->spacedata.first;
int index_qsplit = 0;
/* run ED_view3d_lock() so the correct 'rv3d->viewquat' is set,
@@ -3904,36 +3918,36 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
*
* We could avoid manipulating rv3d->localvd here if exiting
* localview with a 4-split would assign these view locks */
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
const char viewlock = (rv3d->viewlock_quad & RV3D_VIEWLOCK_INIT) ?
(rv3d->viewlock_quad & ~RV3D_VIEWLOCK_INIT) :
- RV3D_LOCKED;
+ RV3D_LOCK_ROTATION;
region_quadview_init_rv3d(
- sa, ar, viewlock, ED_view3d_lock_view_from_index(index_qsplit++), RV3D_ORTHO);
- region_quadview_init_rv3d(sa,
- (ar = ar->next),
+ area, region, viewlock, ED_view3d_lock_view_from_index(index_qsplit++), RV3D_ORTHO);
+ region_quadview_init_rv3d(area,
+ (region = region->next),
viewlock,
ED_view3d_lock_view_from_index(index_qsplit++),
RV3D_ORTHO);
- region_quadview_init_rv3d(sa,
- (ar = ar->next),
+ region_quadview_init_rv3d(area,
+ (region = region->next),
viewlock,
ED_view3d_lock_view_from_index(index_qsplit++),
RV3D_ORTHO);
/* forcing camera is distracting */
#if 0
if (v3d->camera) {
- region_quadview_init_rv3d(sa, (ar = ar->next), 0, RV3D_VIEW_CAMERA, RV3D_CAMOB);
+ region_quadview_init_rv3d(area, (region = region->next), 0, RV3D_VIEW_CAMERA, RV3D_CAMOB);
}
else {
- region_quadview_init_rv3d(sa, (ar = ar->next), 0, RV3D_VIEW_USER, RV3D_PERSP);
+ region_quadview_init_rv3d(area, (region = region->next), 0, RV3D_VIEW_USER, RV3D_PERSP);
}
#else
(void)v3d;
#endif
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
}
@@ -3983,7 +3997,7 @@ static bool region_toggle_poll(bContext *C)
{
ScrArea *area = CTX_wm_area(C);
- /* don't flip anything around in topbar */
+ /* Don't flip anything around in top-bar. */
if (area && area->spacetype == SPACE_TOPBAR) {
CTX_wm_operator_poll_msg_set(C, "Toggling regions in the Top-bar is not allowed");
return 0;
@@ -4021,27 +4035,27 @@ static void SCREEN_OT_region_toggle(wmOperatorType *ot)
/* flip a region alignment */
static int region_flip_exec(bContext *C, wmOperator *UNUSED(op))
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- if (!ar) {
+ if (!region) {
return OPERATOR_CANCELLED;
}
- if (ar->alignment == RGN_ALIGN_TOP) {
- ar->alignment = RGN_ALIGN_BOTTOM;
+ if (region->alignment == RGN_ALIGN_TOP) {
+ region->alignment = RGN_ALIGN_BOTTOM;
}
- else if (ar->alignment == RGN_ALIGN_BOTTOM) {
- ar->alignment = RGN_ALIGN_TOP;
+ else if (region->alignment == RGN_ALIGN_BOTTOM) {
+ region->alignment = RGN_ALIGN_TOP;
}
- else if (ar->alignment == RGN_ALIGN_LEFT) {
- ar->alignment = RGN_ALIGN_RIGHT;
+ else if (region->alignment == RGN_ALIGN_LEFT) {
+ region->alignment = RGN_ALIGN_RIGHT;
}
- else if (ar->alignment == RGN_ALIGN_RIGHT) {
- ar->alignment = RGN_ALIGN_LEFT;
+ else if (region->alignment == RGN_ALIGN_RIGHT) {
+ region->alignment = RGN_ALIGN_LEFT;
}
ED_area_tag_redraw(CTX_wm_area(C));
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -4051,7 +4065,7 @@ static bool region_flip_poll(bContext *C)
{
ScrArea *area = CTX_wm_area(C);
- /* don't flip anything around in topbar */
+ /* Don't flip anything around in top-bar. */
if (area && area->spacetype == SPACE_TOPBAR) {
CTX_wm_operator_poll_msg_set(C, "Flipping regions in the Top-bar is not allowed");
return 0;
@@ -4082,11 +4096,11 @@ static void SCREEN_OT_region_flip(wmOperatorType *ot)
/* show/hide header text menus */
static int header_toggle_menus_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- sa->flag = sa->flag ^ HEADER_NO_PULLDOWN;
+ area->flag = area->flag ^ HEADER_NO_PULLDOWN;
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -4113,42 +4127,42 @@ static void SCREEN_OT_header_toggle_menus(wmOperatorType *ot)
static bool screen_region_context_menu_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- return (sa && sa->spacetype != SPACE_STATUSBAR);
+ ScrArea *area = CTX_wm_area(C);
+ return (area && area->spacetype != SPACE_STATUSBAR);
}
void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_TOP) ?
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_TOP) ?
IFACE_("Flip to Bottom") :
IFACE_("Flip to Top");
{
PointerRNA ptr;
- RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, sa->spacedata.first, &ptr);
- if (!ELEM(sa->spacetype, SPACE_TOPBAR)) {
+ RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, area->spacedata.first, &ptr);
+ if (!ELEM(area->spacetype, SPACE_TOPBAR)) {
uiItemR(layout, &ptr, "show_region_header", 0, IFACE_("Show Header"), ICON_NONE);
}
- ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ ARegion *region_header = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
uiLayout *col = uiLayoutColumn(layout, 0);
- uiLayoutSetActive(col, (ar_header->flag & RGN_FLAG_HIDDEN) == 0);
+ uiLayoutSetActive(col, (region_header->flag & RGN_FLAG_HIDDEN) == 0);
- if (BKE_area_find_region_type(sa, RGN_TYPE_TOOL_HEADER)) {
+ if (BKE_area_find_region_type(area, RGN_TYPE_TOOL_HEADER)) {
uiItemR(col, &ptr, "show_region_tool_header", 0, IFACE_("Show Tool Settings"), ICON_NONE);
}
uiItemO(col,
IFACE_("Show Menus"),
- (sa->flag & HEADER_NO_PULLDOWN) ? ICON_CHECKBOX_DEHLT : ICON_CHECKBOX_HLT,
+ (area->flag & HEADER_NO_PULLDOWN) ? ICON_CHECKBOX_DEHLT : ICON_CHECKBOX_HLT,
"SCREEN_OT_header_toggle_menus");
}
/* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
- if (!ELEM(sa->spacetype, SPACE_TOPBAR)) {
+ if (!ELEM(area->spacetype, SPACE_TOPBAR)) {
uiItemS(layout);
uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
@@ -4156,24 +4170,24 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
/* File browser should be fullscreen all the time, top-bar should
* never be. But other regions can be maximized/restored. */
- if (!ELEM(sa->spacetype, SPACE_FILE, SPACE_TOPBAR)) {
+ if (!ELEM(area->spacetype, SPACE_FILE, SPACE_TOPBAR)) {
uiItemS(layout);
- const char *but_str = sa->full ? IFACE_("Tile Area") : IFACE_("Maximize Area");
+ const char *but_str = area->full ? IFACE_("Tile Area") : IFACE_("Maximize Area");
uiItemO(layout, but_str, ICON_NONE, "SCREEN_OT_screen_full_area");
}
}
void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_TOP) ?
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_TOP) ?
IFACE_("Flip to Bottom") :
IFACE_("Flip to Top");
{
PointerRNA ptr;
- RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, sa->spacedata.first, &ptr);
+ RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, area->spacedata.first, &ptr);
uiItemR(layout, &ptr, "show_region_footer", 0, IFACE_("Show Footer"), ICON_NONE);
}
@@ -4182,20 +4196,20 @@ void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UN
uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
- /* file browser should be fullscreen all the time, topbar should
+ /* File browser should be fullscreen all the time, top-bar should
* never be. But other regions can be maximized/restored... */
- if (!ELEM(sa->spacetype, SPACE_FILE, SPACE_TOPBAR)) {
+ if (!ELEM(area->spacetype, SPACE_FILE, SPACE_TOPBAR)) {
uiItemS(layout);
- const char *but_str = sa->full ? IFACE_("Tile Area") : IFACE_("Maximize Area");
+ const char *but_str = area->full ? IFACE_("Tile Area") : IFACE_("Maximize Area");
uiItemO(layout, but_str, ICON_NONE, "SCREEN_OT_screen_full_area");
}
}
void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
- const ARegion *ar = CTX_wm_region(C);
- const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_LEFT) ?
+ const ARegion *region = CTX_wm_region(C);
+ const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_LEFT) ?
IFACE_("Flip to Right") :
IFACE_("Flip to Left");
@@ -4211,21 +4225,21 @@ static int screen_context_menu_invoke(bContext *C,
{
uiPopupMenu *pup;
uiLayout *layout;
- const ARegion *ar = CTX_wm_region(C);
+ const ARegion *region = CTX_wm_region(C);
- if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
ED_screens_header_tools_menu_create(C, layout, NULL);
UI_popup_menu_end(C, pup);
}
- else if (ar->regiontype == RGN_TYPE_FOOTER) {
+ else if (region->regiontype == RGN_TYPE_FOOTER) {
pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
ED_screens_footer_tools_menu_create(C, layout, NULL);
UI_popup_menu_end(C, pup);
}
- else if (ar->regiontype == RGN_TYPE_NAV_BAR) {
+ else if (region->regiontype == RGN_TYPE_NAV_BAR) {
pup = UI_popup_menu_begin(C, IFACE_("Navigation Bar"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
@@ -4374,9 +4388,9 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
ScreenAnimData *sad = wt->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *window;
- ScrArea *sa;
+ ScrArea *area;
int sync;
- float time;
+ double time;
/* sync, don't sync, or follow scene setting */
if (sad->flag & ANIMPLAY_FLAG_SYNC) {
@@ -4399,7 +4413,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
else if ((scene->audio.flag & AUDIO_SYNC) && (sad->flag & ANIMPLAY_FLAG_REVERSE) == false &&
isfinite(time = BKE_sound_sync_scene(scene_eval))) {
- double newfra = (double)time * FPS;
+ double newfra = time * FPS;
/* give some space here to avoid jumps */
if (newfra + 0.5 > scene->r.cfra && newfra - 0.5 < scene->r.cfra) {
@@ -4423,10 +4437,29 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
else {
if (sync) {
- /* note: this is very simplistic,
- * its has problem that it may skip too many frames.
- * however at least this gives a less jittery playback */
- const int step = max_ii(1, floor((wt->duration - sad->last_duration) * FPS));
+ /* Try to keep the playback in realtime by dropping frames. */
+
+ /* How much time (in frames) has passed since the last frame was drawn? */
+ double delta_frames = wt->delta * FPS;
+
+ /* Add the remaining fraction from the last time step. */
+ delta_frames += sad->lagging_frame_count;
+
+ if (delta_frames < 1.0) {
+ /* We can render faster than the scene frame rate. However skipping or delaying frames
+ * here seems to in practice lead to jittery playback so just step forward a minimum of
+ * one frame. (Even though this can lead to too fast playback, the jitteryness is more
+ * annoying)
+ */
+ delta_frames = 1.0f;
+ sad->lagging_frame_count = 0;
+ }
+ else {
+ /* Extract the delta frame fractions that will be skipped when converting to int. */
+ sad->lagging_frame_count = delta_frames - (int)delta_frames;
+ }
+
+ const int step = delta_frames;
/* skip frames */
if (sad->flag & ANIMPLAY_FLAG_REVERSE) {
@@ -4447,8 +4480,6 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
}
- sad->last_duration = wt->duration;
-
/* reset 'jumped' flag before checking if we need to jump... */
sad->flag &= ~ANIMPLAY_FLAG_JUMPED;
@@ -4505,33 +4536,33 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
for (window = wm->windows.first; window; window = window->next) {
const bScreen *win_screen = WM_window_get_active_screen(window);
- for (sa = win_screen->areabase.first; sa; sa = sa->next) {
- ARegion *ar;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ for (area = win_screen->areabase.first; area; area = area->next) {
+ ARegion *region;
+ for (region = area->regionbase.first; region; region = region->next) {
bool redraw = false;
- if (ar == sad->ar) {
+ if (region == sad->region) {
redraw = true;
}
else if (match_region_with_redraws(
- sa->spacetype, ar->regiontype, sad->redraws, sad->from_anim_edit)) {
+ area->spacetype, region->regiontype, sad->redraws, sad->from_anim_edit)) {
redraw = true;
}
if (redraw) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
/* do follow here if editor type supports it */
if ((sad->redraws & TIME_FOLLOW)) {
- if ((ar->regiontype == RGN_TYPE_WINDOW &&
- ELEM(sa->spacetype, SPACE_SEQ, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA)) ||
- (sa->spacetype == SPACE_CLIP && ar->regiontype == RGN_TYPE_PREVIEW)) {
- float w = BLI_rctf_size_x(&ar->v2d.cur);
- if (scene->r.cfra < ar->v2d.cur.xmin) {
- ar->v2d.cur.xmax = scene->r.cfra;
- ar->v2d.cur.xmin = ar->v2d.cur.xmax - w;
+ if ((region->regiontype == RGN_TYPE_WINDOW &&
+ ELEM(area->spacetype, SPACE_SEQ, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA)) ||
+ (area->spacetype == SPACE_CLIP && region->regiontype == RGN_TYPE_PREVIEW)) {
+ float w = BLI_rctf_size_x(&region->v2d.cur);
+ if (scene->r.cfra < region->v2d.cur.xmin) {
+ region->v2d.cur.xmax = scene->r.cfra;
+ region->v2d.cur.xmin = region->v2d.cur.xmax - w;
}
- else if (scene->r.cfra > ar->v2d.cur.xmax) {
- ar->v2d.cur.xmin = scene->r.cfra;
- ar->v2d.cur.xmax = ar->v2d.cur.xmin + w;
+ else if (scene->r.cfra > region->v2d.cur.xmax) {
+ region->v2d.cur.xmin = scene->r.cfra;
+ region->v2d.cur.xmax = region->v2d.cur.xmin + w;
}
}
}
@@ -4582,7 +4613,7 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot)
/* find window that owns the animation timer */
bScreen *ED_screen_animation_playing(const wmWindowManager *wm)
{
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
bScreen *screen = WM_window_get_active_screen(win);
if (screen->animtimer || screen->scrubbing) {
@@ -4595,7 +4626,7 @@ bScreen *ED_screen_animation_playing(const wmWindowManager *wm)
bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm)
{
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
bScreen *screen = WM_window_get_active_screen(win);
if (screen->animtimer) {
@@ -4615,26 +4646,24 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
/* stop playback now */
- ED_screen_animation_timer(C, 0, 0, 0, 0);
+ ED_screen_animation_timer(C, 0, 0, 0);
BKE_sound_stop_scene(scene_eval);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
else {
/* these settings are currently only available from a menu in the TimeLine */
- int refresh = SPACE_ACTION;
-
if (mode == 1) { /* XXX only play audio forwards!? */
BKE_sound_play_scene(scene_eval);
}
- ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode);
+ ED_screen_animation_timer(C, screen->redraws_flag, sync, mode);
if (screen->animtimer) {
wmTimer *wt = screen->animtimer;
ScreenAnimData *sad = wt->customdata;
- sad->ar = CTX_wm_region(C);
+ sad->region = CTX_wm_region(C);
}
}
@@ -4789,27 +4818,27 @@ static void SCREEN_OT_box_select(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/** \name Full Screen Back Operator
+ *
+ * Use for generic full-screen 'back' button.
* \{ */
-/* *********************** generic fullscreen 'back' button *************** */
-
static int fullscreen_back_exec(bContext *C, wmOperator *op)
{
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = NULL;
+ ScrArea *area = NULL;
/* search current screen for 'fullscreen' areas */
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->full) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ if (area->full) {
break;
}
}
- if (!sa) {
+ if (!area) {
BKE_report(op->reports, RPT_ERROR, "No fullscreen areas were found");
return OPERATOR_CANCELLED;
}
- ED_screen_full_prevspace(C, sa);
+ ED_screen_full_prevspace(C, area);
return OPERATOR_FINISHED;
}
@@ -5030,9 +5059,9 @@ static void SCREEN_OT_new(wmOperatorType *ot)
static int screen_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
WorkSpace *workspace = CTX_wm_workspace(C);
- WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
+ WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, screen);
WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTDELETE, layout);
@@ -5062,26 +5091,26 @@ static void SCREEN_OT_delete(wmOperatorType *ot)
* \{ */
typedef struct RegionAlphaInfo {
- ScrArea *sa;
- ARegion *ar, *child_ar; /* other region */
+ ScrArea *area;
+ ARegion *region, *child_region; /* other region */
int hidden;
} RegionAlphaInfo;
#define TIMEOUT 0.1f
#define TIMESTEP (1.0f / 60.0f)
-float ED_region_blend_alpha(ARegion *ar)
+float ED_region_blend_alpha(ARegion *region)
{
/* check parent too */
- if (ar->regiontimer == NULL && (ar->alignment & RGN_SPLIT_PREV) && ar->prev) {
- ar = ar->prev;
+ if (region->regiontimer == NULL && (region->alignment & RGN_SPLIT_PREV) && region->prev) {
+ region = region->prev;
}
- if (ar->regiontimer) {
- RegionAlphaInfo *rgi = ar->regiontimer->customdata;
+ if (region->regiontimer) {
+ RegionAlphaInfo *rgi = region->regiontimer->customdata;
float alpha;
- alpha = (float)ar->regiontimer->duration / TIMEOUT;
+ alpha = (float)region->regiontimer->duration / TIMEOUT;
/* makes sure the blend out works 100% - without area redraws */
if (rgi->hidden) {
alpha = 0.9f - TIMESTEP - alpha;
@@ -5094,71 +5123,71 @@ float ED_region_blend_alpha(ARegion *ar)
}
/* assumes region has running region-blend timer */
-static void region_blend_end(bContext *C, ARegion *ar, const bool is_running)
+static void region_blend_end(bContext *C, ARegion *region, const bool is_running)
{
- RegionAlphaInfo *rgi = ar->regiontimer->customdata;
+ RegionAlphaInfo *rgi = region->regiontimer->customdata;
/* always send redraw */
- ED_region_tag_redraw(ar);
- if (rgi->child_ar) {
- ED_region_tag_redraw(rgi->child_ar);
+ ED_region_tag_redraw(region);
+ if (rgi->child_region) {
+ ED_region_tag_redraw(rgi->child_region);
}
/* if running timer was hiding, the flag toggle went wrong */
if (is_running) {
if (rgi->hidden) {
- rgi->ar->flag &= ~RGN_FLAG_HIDDEN;
+ rgi->region->flag &= ~RGN_FLAG_HIDDEN;
}
}
else {
if (rgi->hidden) {
- rgi->ar->flag |= rgi->hidden;
- ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), rgi->sa);
+ rgi->region->flag |= rgi->hidden;
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), rgi->area);
}
/* area decoration needs redraw in end */
- ED_area_tag_redraw(rgi->sa);
+ ED_area_tag_redraw(rgi->area);
}
- WM_event_remove_timer(CTX_wm_manager(C), NULL, ar->regiontimer); /* frees rgi */
- ar->regiontimer = NULL;
+ WM_event_remove_timer(CTX_wm_manager(C), NULL, region->regiontimer); /* frees rgi */
+ region->regiontimer = NULL;
}
/**
- * \note Assumes that \a ar itself is not a split version from previous region.
+ * \note Assumes that \a region itself is not a split version from previous region.
*/
-void ED_region_visibility_change_update_animated(bContext *C, ScrArea *sa, ARegion *ar)
+void ED_region_visibility_change_update_animated(bContext *C, ScrArea *area, ARegion *region)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
RegionAlphaInfo *rgi;
/* end running timer */
- if (ar->regiontimer) {
+ if (region->regiontimer) {
- region_blend_end(C, ar, true);
+ region_blend_end(C, region, true);
}
rgi = MEM_callocN(sizeof(RegionAlphaInfo), "RegionAlphaInfo");
- rgi->hidden = ar->flag & RGN_FLAG_HIDDEN;
- rgi->sa = sa;
- rgi->ar = ar;
- ar->flag &= ~RGN_FLAG_HIDDEN;
+ rgi->hidden = region->flag & RGN_FLAG_HIDDEN;
+ rgi->area = area;
+ rgi->region = region;
+ region->flag &= ~RGN_FLAG_HIDDEN;
/* blend in, reinitialize regions because it got unhidden */
if (rgi->hidden == 0) {
- ED_area_initialize(wm, win, sa);
+ ED_area_initialize(wm, win, area);
}
else {
- WM_event_remove_handlers(C, &ar->handlers);
+ WM_event_remove_handlers(C, &region->handlers);
}
- if (ar->next) {
- if (ar->next->alignment & RGN_SPLIT_PREV) {
- rgi->child_ar = ar->next;
+ if (region->next) {
+ if (region->next->alignment & RGN_SPLIT_PREV) {
+ rgi->child_region = region->next;
}
}
/* new timer */
- ar->regiontimer = WM_event_add_timer(wm, win, TIMERREGION, TIMESTEP);
- ar->regiontimer->customdata = rgi;
+ region->regiontimer = WM_event_add_timer(wm, win, TIMERREGION, TIMESTEP);
+ region->regiontimer->customdata = rgi;
}
/* timer runs in win->handlers, so it cannot use context to find area/region */
@@ -5175,14 +5204,14 @@ static int region_blend_invoke(bContext *C, wmOperator *UNUSED(op), const wmEven
rgi = timer->customdata;
/* always send redraws */
- ED_region_tag_redraw(rgi->ar);
- if (rgi->child_ar) {
- ED_region_tag_redraw(rgi->child_ar);
+ ED_region_tag_redraw(rgi->region);
+ if (rgi->child_region) {
+ ED_region_tag_redraw(rgi->child_region);
}
/* end timer? */
- if (rgi->ar->regiontimer->duration > (double)TIMEOUT) {
- region_blend_end(C, rgi->ar, false);
+ if (rgi->region->regiontimer->duration > (double)TIMEOUT) {
+ region_blend_end(C, rgi->region, false);
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
@@ -5213,8 +5242,8 @@ static void SCREEN_OT_region_blend(wmOperatorType *ot)
static bool space_type_set_or_cycle_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- return (sa && !ELEM(sa->spacetype, SPACE_TOPBAR, SPACE_STATUSBAR));
+ ScrArea *area = CTX_wm_area(C);
+ return (area && !ELEM(area->spacetype, SPACE_TOPBAR, SPACE_STATUSBAR));
}
static int space_type_set_or_cycle_exec(bContext *C, wmOperator *op)
@@ -5222,12 +5251,12 @@ static int space_type_set_or_cycle_exec(bContext *C, wmOperator *op)
const int space_type = RNA_enum_get(op->ptr, "space_type");
PointerRNA ptr;
- ScrArea *sa = CTX_wm_area(C);
- RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Area, sa, &ptr);
+ ScrArea *area = CTX_wm_area(C);
+ RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Area, area, &ptr);
PropertyRNA *prop_type = RNA_struct_find_property(&ptr, "type");
PropertyRNA *prop_ui_type = RNA_struct_find_property(&ptr, "ui_type");
- if (sa->spacetype != space_type) {
+ if (area->spacetype != space_type) {
/* Set the type. */
RNA_property_enum_set(&ptr, prop_type, space_type);
RNA_property_update(C, &ptr, prop_type);
@@ -5286,25 +5315,25 @@ static const EnumPropertyItem space_context_cycle_direction[] = {
static bool space_context_cycle_poll(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- /* sa might be NULL if called out of window bounds */
- return (sa && ELEM(sa->spacetype, SPACE_PROPERTIES, SPACE_USERPREF));
+ ScrArea *area = CTX_wm_area(C);
+ /* area might be NULL if called out of window bounds */
+ return (area && ELEM(area->spacetype, SPACE_PROPERTIES, SPACE_USERPREF));
}
/**
* Helper to get the correct RNA pointer/property pair for changing
- * the display context of active space type in \a sa.
+ * the display context of active space type in \a area.
*/
static void context_cycle_prop_get(bScreen *screen,
- const ScrArea *sa,
+ const ScrArea *area,
PointerRNA *r_ptr,
PropertyRNA **r_prop)
{
const char *propname;
- switch (sa->spacetype) {
+ switch (area->spacetype) {
case SPACE_PROPERTIES:
- RNA_pointer_create(&screen->id, &RNA_SpaceProperties, sa->spacedata.first, r_ptr);
+ RNA_pointer_create(&screen->id, &RNA_SpaceProperties, area->spacedata.first, r_ptr);
propname = "context";
break;
case SPACE_USERPREF:
@@ -5377,7 +5406,7 @@ static int space_workspace_cycle_invoke(bContext *C, wmOperator *op, const wmEve
ListBase ordered;
BKE_id_ordered_list(&ordered, &bmain->workspaces);
- for (LinkData *link = ordered.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &ordered) {
if (link->data == workspace_src) {
if (direction == SPACE_CONTEXT_CYCLE_PREV) {
workspace_dst = (link->prev) ? link->prev->data : NULL;
@@ -5510,7 +5539,7 @@ static void keymap_modal_set(wmKeyConfig *keyconf)
wmKeyMap *keymap;
/* Standard Modal keymap ------------------------------------------------ */
- keymap = WM_modalkeymap_add(keyconf, "Standard Modal Map", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "Standard Modal Map", modal_items);
WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move");
}
@@ -5518,7 +5547,7 @@ static void keymap_modal_set(wmKeyConfig *keyconf)
static bool blend_file_drop_poll(bContext *UNUSED(C),
wmDrag *drag,
const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
if (drag->type == WM_DRAG_PATH) {
if (drag->icon == ICON_FILE_BLEND) {
diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c
index 661c17f55d2..733e8b694a6 100644
--- a/source/blender/editors/screen/screen_user_menu.c
+++ b/source/blender/editors/screen/screen_user_menu.c
@@ -21,25 +21,25 @@
* \ingroup spview3d
*/
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BKE_blender_user_menu.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "BKE_idprop.h"
+#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -113,7 +113,7 @@ bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(ListBase *lb,
IDProperty *prop,
short opcontext)
{
- for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
+ LISTBASE_FOREACH (bUserMenuItem *, umi, lb) {
if (umi->type == USER_MENU_TYPE_OPERATOR) {
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
if (STREQ(ot->idname, umi_op->op_idname) && (opcontext == umi_op->opcontext) &&
@@ -128,7 +128,7 @@ bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(ListBase *lb,
struct bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(struct ListBase *lb,
const struct MenuType *mt)
{
- for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
+ LISTBASE_FOREACH (bUserMenuItem *, umi, lb) {
if (umi->type == USER_MENU_TYPE_MENU) {
bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
if (STREQ(mt->idname, umi_mt->mt_idname)) {
@@ -144,7 +144,7 @@ struct bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(struct ListBase *l
const char *prop_id,
int prop_index)
{
- for (bUserMenuItem *umi = lb->first; umi; umi = umi->next) {
+ LISTBASE_FOREACH (bUserMenuItem *, umi, lb) {
if (umi->type == USER_MENU_TYPE_PROP) {
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
if (STREQ(context_data_path, umi_pr->context_data_path) && STREQ(prop_id, umi_pr->prop_id) &&
@@ -222,7 +222,7 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu)
if (um == NULL) {
continue;
}
- for (bUserMenuItem *umi = um->items.first; umi; umi = umi->next) {
+ LISTBASE_FOREACH (bUserMenuItem *, umi, &um->items) {
const char *ui_name = umi->ui_name[0] ? umi->ui_name : NULL;
if (umi->type == USER_MENU_TYPE_OPERATOR) {
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 005c76d26b0..83ded5b3503 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -22,16 +22,16 @@
* \ingroup edscr
*/
-#include <string.h>
#include <errno.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -48,13 +48,13 @@
#include "UI_interface.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "screen_intern.h"
typedef struct ScreenshotData {
- unsigned int *dumprect;
+ uint *dumprect;
int dumpsx, dumpsy;
rcti crop;
@@ -76,13 +76,13 @@ static int screenshot_data_create(bContext *C, wmOperator *op)
if (dumprect) {
ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot");
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
scd->dumpsx = dumprect_size[0];
scd->dumpsy = dumprect_size[1];
scd->dumprect = dumprect;
- if (sa) {
- scd->crop = sa->totrct;
+ if (area) {
+ scd->crop = area->totrct;
}
BKE_imformat_defaults(&scd->im_format);
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index bbb959c27ff..8feef0c675a 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -21,15 +21,15 @@
#include <stdlib.h>
#include <string.h>
-#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
+#include "BLI_utildefines.h"
#include "BKE_appdir.h"
#include "BKE_blendfile.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_workspace.h"
@@ -198,8 +198,7 @@ WorkSpace *ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindo
/* TODO(campbell): tools */
- for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old;
- layout_old = layout_old->next) {
+ LISTBASE_FOREACH (WorkSpaceLayout *, layout_old, layouts_old) {
WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(
bmain, workspace_new, layout_old, win);
@@ -222,7 +221,7 @@ bool ED_workspace_delete(WorkSpace *workspace, Main *bmain, bContext *C, wmWindo
ListBase ordered;
BKE_id_ordered_list(&ordered, &bmain->workspaces);
WorkSpace *prev = NULL, *next = NULL;
- for (LinkData *link = ordered.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &ordered) {
if (link->data == workspace) {
prev = link->prev ? link->prev->data : NULL;
next = link->next ? link->next->data : NULL;
@@ -232,7 +231,7 @@ bool ED_workspace_delete(WorkSpace *workspace, Main *bmain, bContext *C, wmWindo
BLI_freelistN(&ordered);
BLI_assert((prev != NULL) || (next != NULL));
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
WorkSpace *workspace_active = WM_window_get_active_workspace(win);
if (workspace_active == workspace) {
ED_workspace_change((prev != NULL) ? prev : next, C, wm, win);
@@ -266,8 +265,7 @@ static WorkSpace *workspace_context_get(bContext *C)
return (WorkSpace *)id;
}
- wmWindow *win = CTX_wm_window(C);
- return WM_window_get_active_workspace(win);
+ return CTX_wm_workspace(C);
}
static bool workspace_context_poll(bContext *C)
@@ -334,7 +332,7 @@ static int workspace_append_activate_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", filepath);
WorkSpace *appended_workspace = (WorkSpace *)WM_file_append_datablock(
- C, filepath, ID_WS, idname);
+ bmain, CTX_data_scene(C), CTX_data_view_layer(C), CTX_wm_view3d(C), filepath, ID_WS, idname);
if (appended_workspace) {
/* Set defaults. */
@@ -482,7 +480,7 @@ static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
ListBase templates;
BKE_appdir_app_templates(&templates);
- for (LinkData *link = templates.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &templates) {
char *template = link->data;
char display_name[FILE_MAX];
diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c
index 67ac5067134..cf9637788a9 100644
--- a/source/blender/editors/screen/workspace_layout_edit.c
+++ b/source/blender/editors/screen/workspace_layout_edit.c
@@ -20,8 +20,8 @@
#include <stdlib.h>
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "DNA_screen_types.h"
#include "DNA_workspace_types.h"
@@ -68,7 +68,7 @@ WorkSpaceLayout *ED_workspace_layout_duplicate(Main *bmain,
screen_new = BKE_workspace_layout_screen_get(layout_new);
if (BKE_screen_is_fullscreen_area(screen_old)) {
- for (ScrArea *area_old = screen_old->areabase.first; area_old; area_old = area_old->next) {
+ LISTBASE_FOREACH (ScrArea *, area_old, &screen_old->areabase) {
if (area_old->full) {
ScrArea *area_new = (ScrArea *)screen_new->areabase.first;
ED_area_data_copy(area_new, area_old, true);
@@ -172,9 +172,9 @@ bool ED_workspace_layout_cycle(WorkSpace *workspace, const short direction, bCon
WorkSpaceLayout *old_layout = BKE_workspace_active_layout_get(win->workspace_hook);
WorkSpaceLayout *new_layout;
const bScreen *old_screen = BKE_workspace_layout_screen_get(old_layout);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- if (old_screen->temp || (sa && sa->full && sa->full->temp)) {
+ if (old_screen->temp || (area && area->full && area->full->temp)) {
return false;
}
@@ -188,9 +188,9 @@ bool ED_workspace_layout_cycle(WorkSpace *workspace, const short direction, bCon
if (new_layout && (old_layout != new_layout)) {
bScreen *new_screen = BKE_workspace_layout_screen_get(new_layout);
- if (sa && sa->full) {
+ if (area && area->full) {
/* return to previous state before switching screens */
- ED_screen_full_restore(C, sa); /* may free screen of old_layout */
+ ED_screen_full_restore(C, area); /* may free screen of old_layout */
}
ED_screen_change(C, new_screen);
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index a5cc262ddcd..b8754953741 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -59,6 +59,18 @@ set(SRC
paint_vertex_weight_ops.c
paint_vertex_weight_utils.c
sculpt.c
+ sculpt_automasking.c
+ sculpt_cloth.c
+ sculpt_detail.c
+ sculpt_dyntopo.c
+ sculpt_face_set.c
+ sculpt_filter_mask.c
+ sculpt_filter_mesh.c
+ sculpt_mask_expand.c
+ sculpt_multiplane_scrape.c
+ sculpt_pose.c
+ sculpt_smooth.c
+ sculpt_transform.c
sculpt_undo.c
sculpt_uv.c
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 19b4b9f569c..191a064a95c 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2009 by Nicholas Bishop
@@ -29,8 +29,8 @@
#include "BLI_utildefines.h"
#include "DNA_brush_types.h"
-#include "DNA_customdata_types.h"
#include "DNA_color_types.h"
+#include "DNA_customdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -39,13 +39,13 @@
#include "DNA_view3d_types.h"
#include "BKE_brush.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_image.h"
#include "BKE_node.h"
-#include "BKE_paint.h"
-#include "BKE_colortools.h"
#include "BKE_object.h"
+#include "BKE_paint.h"
#include "WM_api.h"
#include "wm_cursors.h"
@@ -98,7 +98,7 @@ static TexSnapshot primary_snap = {0};
static TexSnapshot secondary_snap = {0};
static CursorSnapshot cursor_snap = {0};
-/* delete overlay cursor textures to preserve memory and invalidate all overlay flags */
+/* Delete overlay cursor textures to preserve memory and invalidate all overlay flags. */
void paint_cursor_delete_textures(void)
{
if (primary_snap.overlay_texture) {
@@ -125,7 +125,7 @@ static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool co
//(BKE_brush_size_get(vc->scene, brush) <= snap->BKE_brush_size_get)) &&
(mtex->brush_map_mode != MTEX_MAP_MODE_TILED ||
- (vc->ar->winx == snap->winx && vc->ar->winy == snap->winy)) &&
+ (vc->region->winx == snap->winx && vc->region->winy == snap->winy)) &&
(mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL || snap->old_zoom == zoom) &&
snap->old_col == col);
}
@@ -133,8 +133,8 @@ static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool co
static void make_tex_snap(TexSnapshot *snap, ViewContext *vc, float zoom)
{
snap->old_zoom = zoom;
- snap->winx = vc->ar->winx;
- snap->winy = vc->ar->winy;
+ snap->winx = vc->region->winx;
+ snap->winy = vc->region->winy;
}
typedef struct LoadTexData {
@@ -171,9 +171,11 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
bool convert_to_linear = false;
struct ColorSpace *colorspace = NULL;
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
if (mtex->tex && mtex->tex->type == TEX_IMAGE && mtex->tex->ima) {
ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(mtex->tex->ima, &mtex->tex->iuser, pool);
- /* For consistency, sampling always returns color in linear space */
+ /* For consistency, sampling always returns color in linear space. */
if (tex_ibuf && tex_ibuf->rect_float == NULL) {
convert_to_linear = true;
colorspace = tex_ibuf->rect_colorspace;
@@ -182,7 +184,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
}
for (int i = 0; i < size; i++) {
- // largely duplicated from tex_strength
+ /* Largely duplicated from tex_strength. */
int index = j * size + i;
@@ -191,8 +193,8 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
float len;
if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
- x *= vc->ar->winx / radius;
- y *= vc->ar->winy / radius;
+ x *= vc->region->winx / radius;
+ y *= vc->region->winy / radius;
}
else {
x = (x - 0.5f) * 2.0f;
@@ -214,8 +216,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
if (col) {
float rgba[4];
- paint_get_tex_pixel_col(
- mtex, x, y, rgba, pool, tls->thread_id, convert_to_linear, colorspace);
+ paint_get_tex_pixel_col(mtex, x, y, rgba, pool, thread_id, convert_to_linear, colorspace);
buffer[index * 4] = rgba[0] * 255;
buffer[index * 4 + 1] = rgba[1] * 255;
@@ -223,11 +224,11 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
buffer[index * 4 + 3] = rgba[3] * 255;
}
else {
- float avg = paint_get_tex_pixel(mtex, x, y, pool, tls->thread_id);
+ float avg = paint_get_tex_pixel(mtex, x, y, pool, thread_id);
avg += br->texture_sample_bias;
- /* clamp to avoid precision overflow */
+ /* Clamp to avoid precision overflow. */
CLAMP(avg, 0.0f, 1.0f);
buffer[index] = 255 - (GLubyte)(255 * avg);
}
@@ -269,7 +270,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
if (refresh) {
struct ImagePool *pool = NULL;
- /* stencil is rotated later */
+ /* Stencil is rotated later. */
const float rotation = (mtex->brush_map_mode != MTEX_MAP_MODE_STENCIL) ? -mtex->rot : 0.0f;
const float radius = BKE_brush_size_get(vc->scene, br) * zoom;
@@ -317,7 +318,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
pool = BKE_image_pool_new();
if (mtex->tex && mtex->tex->nodetree) {
- /* has internal flag to detect it only does it once */
+ /* Has internal flag to detect it only does it once. */
ntreeTexBeginExecTree(mtex->tex->nodetree);
}
@@ -400,7 +401,7 @@ static void load_tex_cursor_task_cb(void *__restrict userdata,
const int size = data->size;
for (int i = 0; i < size; i++) {
- // largely duplicated from tex_strength
+ /* Largely duplicated from tex_strength. */
const int index = j * size + i;
const float x = (((float)i / size) - 0.5f) * 2.0f;
@@ -408,7 +409,9 @@ static void load_tex_cursor_task_cb(void *__restrict userdata,
const float len = sqrtf(x * x + y * y);
if (len <= 1.0f) {
- float avg = BKE_brush_curve_strength_clamped(br, len, 1.0f); /* Falloff curve */
+
+ /* Falloff curve. */
+ float avg = BKE_brush_curve_strength_clamped(br, len, 1.0f);
buffer[index] = (GLubyte)(255 * avg);
}
@@ -520,7 +523,7 @@ static int project_brush_radius(ViewContext *vc, float radius, const float locat
ED_view3d_global_to_vector(vc->rv3d, location, view);
- /* create a vector that is not orthogonal to view */
+ /* Create a vector that is not orthogonal to view. */
if (fabsf(view[0]) < 0.1f) {
nonortho[0] = view[0] + 1.0f;
@@ -538,23 +541,25 @@ static int project_brush_radius(ViewContext *vc, float radius, const float locat
nonortho[2] = view[2] + 1.0f;
}
- /* get a vector in the plane of the view */
+ /* Get a vector in the plane of the view. */
cross_v3_v3v3(ortho, nonortho, view);
normalize_v3(ortho);
- /* make a point on the surface of the brush tangent to the view */
+ /* Make a point on the surface of the brush tangent to the view. */
mul_v3_fl(ortho, radius);
add_v3_v3v3(offset, location, ortho);
- /* project the center of the brush, and the tangent point to the view onto the screen */
- if ((ED_view3d_project_float_global(vc->ar, location, p1, V3D_PROJ_TEST_NOP) ==
+ /* Project the center of the brush, and the tangent point to the view onto the screen. */
+ if ((ED_view3d_project_float_global(vc->region, location, p1, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK) &&
- (ED_view3d_project_float_global(vc->ar, offset, p2, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) {
- /* the distance between these points is the size of the projected brush in pixels */
+ (ED_view3d_project_float_global(vc->region, offset, p2, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK)) {
+ /* The distance between these points is the size of the projected brush in pixels. */
return len_v2v2(p1, p2);
}
else {
- BLI_assert(0); /* assert because the code that sets up the vectors should disallow this */
+ /* Assert because the code that sets up the vectors should disallow this. */
+ BLI_assert(0);
return 0;
}
}
@@ -577,7 +582,7 @@ static bool sculpt_get_brush_geometry(bContext *C,
if (vc->obact->sculpt && vc->obact->sculpt->pbvh) {
if (!ups->stroke_active) {
- hit = sculpt_stroke_get_location(C, location, mouse);
+ hit = SCULPT_stroke_get_location(C, location, mouse);
}
else {
hit = ups->last_hit;
@@ -608,7 +613,7 @@ static bool sculpt_get_brush_geometry(bContext *C,
}
/* Draw an overlay that shows what effect the brush's texture will
- * have on brush strength */
+ * have on brush strength. */
static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
Brush *brush,
ViewContext *vc,
@@ -619,7 +624,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
bool primary)
{
rctf quad;
- /* check for overlay mode */
+ /* Check for overlay mode. */
MTex *mtex = (primary) ? &brush->mtex : &brush->mask_mtex;
bool valid = ((primary) ? (brush->overlay_flags & BRUSH_OVERLAY_PRIMARY) != 0 :
@@ -642,12 +647,12 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
GPU_matrix_push();
- /* brush rotation */
+ /* Brush rotation. */
GPU_matrix_translate_2f(x, y);
GPU_matrix_rotate_2d(-RAD2DEGF(primary ? ups->brush_rotation : ups->brush_rotation_sec));
GPU_matrix_translate_2f(-x, -y);
- /* scale based on tablet pressure */
+ /* Scale based on tablet pressure. */
if (primary && ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
const float scale = ups->size_pressure_value;
GPU_matrix_translate_2f(x, y);
@@ -672,10 +677,10 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
quad.xmin = 0;
quad.ymin = 0;
- quad.xmax = BLI_rcti_size_x(&vc->ar->winrct);
- quad.ymax = BLI_rcti_size_y(&vc->ar->winrct);
+ quad.xmax = BLI_rcti_size_x(&vc->region->winrct);
+ quad.ymax = BLI_rcti_size_y(&vc->region->winrct);
}
- /* Stencil code goes here */
+ /* Stencil code goes here. */
else {
if (primary) {
quad.xmin = -brush->stencil_dimension[0];
@@ -699,7 +704,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
GPU_matrix_rotate_2d(RAD2DEGF(mtex->rot));
}
- /* set quad color. Colored overlay does not get blending */
+ /* Set quad color. Colored overlay does not get blending. */
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
uint texCoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -714,7 +719,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, overlay_alpha * 0.01f);
}
- /* draw textured quad */
+ /* Draw textured quad. */
immUniform1i("image", 0);
immBegin(GPU_PRIM_TRI_FAN, 4);
@@ -739,12 +744,12 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
}
/* Draw an overlay that shows what effect the brush's texture will
- * have on brush strength */
+ * have on brush strength. */
static bool paint_draw_cursor_overlay(
UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom)
{
rctf quad;
- /* check for overlay mode */
+ /* Check for overlay mode. */
if (!(brush->overlay_flags & BRUSH_OVERLAY_CURSOR)) {
return false;
@@ -777,7 +782,7 @@ static bool paint_draw_cursor_overlay(
quad.ymax = y + radius;
}
- /* scale based on tablet pressure */
+ /* Scale based on tablet pressure. */
if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
do_pop = true;
GPU_matrix_push();
@@ -795,9 +800,9 @@ static bool paint_draw_cursor_overlay(
immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, brush->cursor_overlay_alpha * 0.01f);
- /* draw textured quad */
+ /* Draw textured quad. */
- /* draw textured quad */
+ /* Draw textured quad. */
immUniform1i("image", 0);
immBegin(GPU_PRIM_TRI_FAN, 4);
@@ -841,9 +846,9 @@ static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
/* Translate to region. */
GPU_matrix_push();
- GPU_matrix_translate_2f(vc->ar->winrct.xmin, vc->ar->winrct.ymin);
- x -= vc->ar->winrct.xmin;
- y -= vc->ar->winrct.ymin;
+ GPU_matrix_translate_2f(vc->region->winrct.xmin, vc->region->winrct.ymin);
+ x -= vc->region->winrct.xmin;
+ y -= vc->region->winrct.ymin;
/* Colored overlay should be drawn separately. */
if (col) {
@@ -872,12 +877,8 @@ static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
return alpha_overlay_active;
}
-BLI_INLINE void draw_tri_point(unsigned int pos,
- const float sel_col[4],
- float pivot_col[4],
- float *co,
- float width,
- bool selected)
+BLI_INLINE void draw_tri_point(
+ uint pos, const float sel_col[4], float pivot_col[4], float *co, float width, bool selected)
{
immUniformColor4fv(selected ? sel_col : pivot_col);
@@ -906,12 +907,8 @@ BLI_INLINE void draw_tri_point(unsigned int pos,
immEnd();
}
-BLI_INLINE void draw_rect_point(unsigned int pos,
- const float sel_col[4],
- float handle_col[4],
- float *co,
- float width,
- bool selected)
+BLI_INLINE void draw_rect_point(
+ uint pos, const float sel_col[4], float handle_col[4], float *co, float width, bool selected)
{
immUniformColor4fv(selected ? sel_col : handle_col);
@@ -931,7 +928,7 @@ BLI_INLINE void draw_rect_point(unsigned int pos,
imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
}
-BLI_INLINE void draw_bezier_handle_lines(unsigned int pos, float sel_col[4], BezTriple *bez)
+BLI_INLINE void draw_bezier_handle_lines(uint pos, float sel_col[4], BezTriple *bez)
{
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
GPU_line_width(3.0f);
@@ -970,7 +967,7 @@ BLI_INLINE void draw_bezier_handle_lines(unsigned int pos, float sel_col[4], Bez
static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc)
{
GPU_matrix_push();
- GPU_matrix_translate_2f(vc->ar->winrct.xmin, vc->ar->winrct.ymin);
+ GPU_matrix_translate_2f(vc->region->winrct.xmin, vc->region->winrct.ymin);
if (brush->paint_curve && brush->paint_curve->points) {
int i;
@@ -980,7 +977,7 @@ static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc)
GPU_line_smooth(true);
GPU_blend(true);
- /* draw the bezier handles and the curve segment between the current and next point */
+ /* Draw the bezier handles and the curve segment between the current and next point. */
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -994,7 +991,7 @@ static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc)
int j;
PaintCurvePoint *cp_next = cp + 1;
float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
- /* use color coding to distinguish handles vs curve segments */
+ /* Use color coding to distinguish handles vs curve segments. */
draw_bezier_handle_lines(pos, selec_col, &cp->bez);
draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2);
draw_rect_point(
@@ -1031,7 +1028,7 @@ static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc)
immEnd();
}
- /* draw last line segment */
+ /* Draw last line segment. */
draw_bezier_handle_lines(pos, selec_col, &cp->bez);
draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2);
draw_rect_point(
@@ -1048,7 +1045,7 @@ static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc)
}
/* Special actions taken when paint cursor goes over mesh */
-/* TODO: sculpt only for now */
+/* TODO: sculpt only for now. */
static void paint_cursor_on_hit(UnifiedPaintSettings *ups,
Brush *brush,
ViewContext *vc,
@@ -1056,9 +1053,9 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups,
{
float unprojected_radius, projected_radius;
- /* update the brush's cached 3D radius */
+ /* Update the brush's cached 3D radius. */
if (!BKE_brush_use_locked_size(vc->scene, brush)) {
- /* get 2D brush radius */
+ /* Get 2D brush radius. */
if (ups->draw_anchored) {
projected_radius = ups->anchored_size;
}
@@ -1071,15 +1068,15 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups,
}
}
- /* convert brush radius from 2D to 3D */
+ /* Convert brush radius from 2D to 3D. */
unprojected_radius = paint_calc_object_space_radius(vc, location, projected_radius);
- /* scale 3D brush radius by pressure */
+ /* Scale 3D brush radius by pressure. */
if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
unprojected_radius *= ups->size_pressure_value;
}
- /* set cached value in either Brush or UnifiedPaintSettings */
+ /* Set cached value in either Brush or UnifiedPaintSettings. */
BKE_brush_unprojected_radius_set(vc->scene, brush, unprojected_radius);
}
}
@@ -1096,27 +1093,33 @@ static bool ommit_cursor_drawing(Paint *paint, ePaintMode mode, Brush *brush)
return true;
}
-static void cursor_draw_point_screen_space(
- const uint gpuattr, const ARegion *ar, float true_location[3], float obmat[4][4], int size)
+static void cursor_draw_point_screen_space(const uint gpuattr,
+ const ARegion *region,
+ const float true_location[3],
+ const float obmat[4][4],
+ const int size)
{
float translation_vertex_cursor[3], location[3];
copy_v3_v3(location, true_location);
mul_m4_v3(obmat, location);
- ED_view3d_project(ar, location, translation_vertex_cursor);
- imm_draw_circle_fill_3d(
- gpuattr, translation_vertex_cursor[0], translation_vertex_cursor[1], size, 10);
+ ED_view3d_project(region, location, translation_vertex_cursor);
+ /* Do not draw points behind the view. Z [near, far] is mapped to [-1, 1]. */
+ if (translation_vertex_cursor[2] <= 1.0f) {
+ imm_draw_circle_fill_3d(
+ gpuattr, translation_vertex_cursor[0], translation_vertex_cursor[1], size, 10);
+ }
}
static void cursor_draw_tiling_preview(const uint gpuattr,
- const ARegion *ar,
+ const ARegion *region,
const float true_location[3],
Sculpt *sd,
Object *ob,
- float radius)
+ const float radius)
{
BoundBox *bb = BKE_object_boundbox_get(ob);
float orgLoc[3], location[3];
- int dim, tile_pass = 0;
+ int tile_pass = 0;
int start[3];
int end[3];
int cur[3];
@@ -1125,7 +1128,7 @@ static void cursor_draw_tiling_preview(const uint gpuattr,
const float *step = sd->paint.tile_offset;
copy_v3_v3(orgLoc, true_location);
- for (dim = 0; dim < 3; dim++) {
+ for (int dim = 0; dim < 3; dim++) {
if ((sd->paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) {
start[dim] = (bbMin[dim] - orgLoc[dim] - radius) / step[dim];
end[dim] = (bbMax[dim] - orgLoc[dim] + radius) / step[dim];
@@ -1139,25 +1142,25 @@ static void cursor_draw_tiling_preview(const uint gpuattr,
for (cur[1] = start[1]; cur[1] <= end[1]; cur[1]++) {
for (cur[2] = start[2]; cur[2] <= end[2]; cur[2]++) {
if (!cur[0] && !cur[1] && !cur[2]) {
- /* skip tile at orgLoc, this was already handled before all others */
+ /* Skip tile at orgLoc, this was already handled before all others. */
continue;
}
tile_pass++;
- for (dim = 0; dim < 3; dim++) {
+ for (int dim = 0; dim < 3; dim++) {
location[dim] = cur[dim] * step[dim] + orgLoc[dim];
}
- cursor_draw_point_screen_space(gpuattr, ar, location, ob->obmat, 3);
+ cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3);
}
}
}
}
static void cursor_draw_point_with_symmetry(const uint gpuattr,
- const ARegion *ar,
+ const ARegion *region,
const float true_location[3],
Sculpt *sd,
Object *ob,
- float radius)
+ const float radius)
{
const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
float location[3], symm_rot_mat[4][4];
@@ -1165,14 +1168,14 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
for (int i = 0; i <= symm; i++) {
if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) {
- /* Axis Symmetry */
+ /* Axis Symmetry. */
flip_v3_v3(location, true_location, (char)i);
- cursor_draw_point_screen_space(gpuattr, ar, location, ob->obmat, 3);
+ cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3);
- /* Tiling */
- cursor_draw_tiling_preview(gpuattr, ar, location, sd, ob, radius);
+ /* Tiling. */
+ cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius);
- /* Radial Symmetry */
+ /* Radial Symmetry. */
for (char raxis = 0; raxis < 3; raxis++) {
for (int r = 1; r < sd->radial_symm[raxis]; r++) {
float angle = 2 * M_PI * r / sd->radial_symm[(int)raxis];
@@ -1181,8 +1184,8 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
rotate_m4(symm_rot_mat, raxis + 'X', angle);
mul_m4_v3(symm_rot_mat, location);
- cursor_draw_tiling_preview(gpuattr, ar, location, sd, ob, radius);
- cursor_draw_point_screen_space(gpuattr, ar, location, ob->obmat, 3);
+ cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius);
+ cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3);
}
}
}
@@ -1203,7 +1206,7 @@ static void sculpt_geometry_preview_lines_draw(const uint gpuattr, SculptSession
if (ss->preview_vert_index_count > 0) {
immBegin(GPU_PRIM_LINES, ss->preview_vert_index_count);
for (int i = 0; i < ss->preview_vert_index_count; i++) {
- immVertex3fv(gpuattr, sculpt_vertex_co_get(ss, ss->preview_vert_index_list[i]));
+ immVertex3fv(gpuattr, SCULPT_vertex_co_get(ss, ss->preview_vert_index_list[i]));
}
immEnd();
}
@@ -1214,68 +1217,32 @@ static void sculpt_geometry_preview_lines_draw(const uint gpuattr, SculptSession
}
}
-static void sculpt_multiplane_scrape_preview_draw(const uint gpuattr,
- SculptSession *ss,
- const float outline_col[3],
- float outline_alpha)
+static void SCULPT_layer_brush_height_preview_draw(const uint gpuattr,
+ const Brush *brush,
+ const float obmat[4][4],
+ const float location[3],
+ const float normal[3],
+ const float rds,
+ const float line_width,
+ const float outline_col[3],
+ const float alpha)
{
- float local_mat_inv[4][4];
- invert_m4_m4(local_mat_inv, ss->cache->stroke_local_mat);
- GPU_matrix_mul(local_mat_inv);
- float angle = ss->cache->multiplane_scrape_sampled_angle;
- if (ss->cache->pen_flip || ss->cache->invert) {
- angle = -angle;
- }
-
- float offset = ss->cache->radius * 0.25f;
-
- float p[3] = {0.0f, 0.0f, ss->cache->radius};
- float y_axis[3] = {0.0f, 1.0f, 0.0f};
- float p_l[3];
- float p_r[3];
- float area_center[3] = {0.0f, 0.0f, 0.0f};
- rotate_v3_v3v3fl(p_r, p, y_axis, DEG2RADF((angle + 180) * 0.5f));
- rotate_v3_v3v3fl(p_l, p, y_axis, DEG2RADF(-(angle + 180) * 0.5f));
-
- immBegin(GPU_PRIM_LINES, 14);
- immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
- immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
- immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
- immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
-
- immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
- immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
- immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
- immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
-
- immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
- immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
-
- immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
- immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
-
- immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
- immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
-
- immEnd();
-
- immUniformColor3fvAlpha(outline_col, outline_alpha * 0.1f);
- immBegin(GPU_PRIM_TRIS, 12);
- immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
- immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
- immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
- immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
- immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
- immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
-
- immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
- immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
- immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
- immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
- immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
- immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
-
- immEnd();
+ float cursor_trans[4][4], cursor_rot[4][4];
+ float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f};
+ float quat[4];
+ float height_preview_trans[3];
+ copy_m4_m4(cursor_trans, obmat);
+ madd_v3_v3v3fl(height_preview_trans, location, normal, brush->height);
+ translate_m4(
+ cursor_trans, height_preview_trans[0], height_preview_trans[1], height_preview_trans[2]);
+ rotation_between_vecs_to_quat(quat, z_axis, normal);
+ quat_to_mat4(cursor_rot, quat);
+ GPU_matrix_mul(cursor_trans);
+ GPU_matrix_mul(cursor_rot);
+
+ GPU_line_width(line_width);
+ immUniformColor3fvAlpha(outline_col, alpha * 0.5f);
+ imm_draw_circle_wire_3d(gpuattr, 0, 0, rds, 80);
}
static bool paint_use_2d_cursor(ePaintMode mode)
@@ -1288,11 +1255,12 @@ static bool paint_use_2d_cursor(ePaintMode mode)
static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
{
- ARegion *ar = CTX_wm_region(C);
- if (ar && ar->regiontype != RGN_TYPE_WINDOW) {
+ ARegion *region = CTX_wm_region(C);
+ if (region && region->regiontype != RGN_TYPE_WINDOW) {
return;
}
+ const wmWindowManager *wm = CTX_wm_manager(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Scene *scene = CTX_data_scene(C);
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
@@ -1308,8 +1276,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
return;
}
- /* can't use stroke vc here because this will be called during
- * mouse over too, not just during a stroke */
+ /* Can't use stroke vc here because this will be called during
+ * mouse over too, not just during a stroke. */
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
@@ -1317,7 +1285,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
return;
}
- /* skip everything and draw brush here */
+ /* Skip everything and draw brush here. */
if (brush->flag & BRUSH_CURVE) {
paint_draw_curve_cursor(brush, &vc);
return;
@@ -1327,32 +1295,35 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
get_imapaint_zoom(C, &zoomx, &zoomy);
zoomx = max_ff(zoomx, zoomy);
- /* set various defaults */
+ /* Set various defaults. */
const float *outline_col = brush->add_col;
const float outline_alpha = brush->add_col[3];
float translation[2] = {x, y};
float final_radius = (BKE_brush_size_get(scene, brush) * zoomx);
- /* don't calculate rake angles while a stroke is active because the rake variables are global
+ /* Don't calculate rake angles while a stroke is active because the rake variables are global
* and we may get interference with the stroke itself.
- * For line strokes, such interference is visible */
+ * For line strokes, such interference is visible. */
if (!ups->stroke_active) {
paint_calculate_rake_rotation(ups, brush, translation);
}
- /* draw overlay */
+ /* Draw overlay. */
bool alpha_overlay_active = paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
if (ups->draw_anchored) {
final_radius = ups->anchored_size;
copy_v2_fl2(translation,
- ups->anchored_initial_mouse[0] + ar->winrct.xmin,
- ups->anchored_initial_mouse[1] + ar->winrct.ymin);
+ ups->anchored_initial_mouse[0] + region->winrct.xmin,
+ ups->anchored_initial_mouse[1] + region->winrct.ymin);
}
- /* make lines pretty */
+ /* Make lines pretty. */
GPU_line_width(2.0f);
- GPU_blend(true); /* TODO: also set blend mode? */
+
+ /* TODO: also set blend mode? */
+ GPU_blend(true);
+
GPU_line_smooth(true);
if (use_2d_cursor) {
@@ -1361,45 +1332,46 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
immUniformColor3fvAlpha(outline_col, outline_alpha);
- /* draw brush outline */
+ /* Draw brush outline. */
if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
imm_draw_circle_wire_2d(
pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40);
- /* outer at half alpha */
+ /* Outer at half alpha. */
immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
}
GPU_line_width(1.0f);
imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius, 40);
}
- else { /* 3d painting */
+ else {
+ /* 3D Painting. */
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
/* TODO: as sculpt and other paint modes are unified, this
- * special mode of drawing will go away */
+ * special mode of drawing will go away. */
Object *obact = vc.obact;
SculptSession *ss = obact ? obact->sculpt : NULL;
if ((mode == PAINT_MODE_SCULPT) && ss) {
float location[3];
int pixel_radius;
- /* test if brush is over the mesh */
+ /* Test if brush is over the mesh. */
bool hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location, ups);
if (BKE_brush_use_locked_size(scene, brush)) {
BKE_brush_size_set(scene, brush, pixel_radius);
}
- /* check if brush is subtracting, use different color then */
+ /* Check if brush is subtracting, use different color then */
/* TODO: no way currently to know state of pen flip or
- * invert key modifier without starting a stroke */
+ * invert key modifier without starting a stroke. */
if (((ups->draw_inverted == 0) ^ ((brush->flag & BRUSH_DIR_IN) == 0)) &&
BKE_brush_sculpt_has_secondary_color(brush)) {
outline_col = brush->sub_col;
}
- /* only do if brush is over the mesh */
+ /* Only do if brush is over the mesh. */
if (hit) {
paint_cursor_on_hit(ups, brush, &vc, location);
}
@@ -1410,26 +1382,26 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
if (ups->stroke_active && BKE_brush_use_size_pressure(brush) && mode != PAINT_MODE_SCULPT) {
imm_draw_circle_wire_3d(
pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40);
- /* outer at half alpha */
+ /* Outer at half alpha. */
immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
}
- /* Only sculpt mode cursor for now */
- /* Disable for PBVH_GRIDS */
+ /* Only sculpt mode cursor for now. */
+ /* Disable for PBVH_GRIDS. */
bool is_multires = ss && ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS;
SculptCursorGeometryInfo gi;
- float mouse[2] = {x - ar->winrct.xmin, y - ar->winrct.ymin};
+ float mouse[2] = {x - region->winrct.xmin, y - region->winrct.ymin};
int prev_active_vertex_index = -1;
bool is_cursor_over_mesh = false;
- /* Update the active vertex */
+ /* Update the active vertex. */
if ((mode == PAINT_MODE_SCULPT) && ss && !ups->stroke_active) {
prev_active_vertex_index = ss->active_vertex_index;
- is_cursor_over_mesh = sculpt_cursor_geometry_info_update(
+ is_cursor_over_mesh = SCULPT_cursor_geometry_info_update(
C, &gi, mouse, (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE));
}
- /* Use special paint crosshair cursor in all paint modes*/
+ /* Use special paint crosshair cursor in all paint modes. */
wmWindow *win = CTX_wm_window(C);
WM_cursor_set(win, WM_CURSOR_PAINT);
@@ -1454,45 +1426,50 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
rds = BKE_brush_unprojected_radius_get(scene, brush);
}
- wmViewport(&ar->winrct);
+ wmViewport(&region->winrct);
- /* Draw 3D active vertex preview with symmetry*/
+ /* Draw 3D active vertex preview with symmetry. */
if (len_v3v3(gi.active_vertex_co, gi.location) < rds) {
- cursor_draw_point_with_symmetry(pos, ar, gi.active_vertex_co, sd, vc.obact, rds);
+ cursor_draw_point_with_symmetry(pos, region, gi.active_vertex_co, sd, vc.obact, rds);
}
/* Draw pose brush origins. */
if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
- if (update_previews) {
+
+ /* Just after switching to the Pose Brush, the active vertex can be the same and the
+ * cursor won't be tagged to update, so always initialize the preview chain if it is
+ * null before drawing it. */
+ if (update_previews || !ss->pose_ik_chain_preview) {
BKE_sculpt_update_object_for_edit(depsgraph, vc.obact, true, false);
/* Free the previous pose brush preview. */
if (ss->pose_ik_chain_preview) {
- sculpt_pose_ik_chain_free(ss->pose_ik_chain_preview);
+ SCULPT_pose_ik_chain_free(ss->pose_ik_chain_preview);
}
/* Generate a new pose brush preview from the current cursor location. */
- ss->pose_ik_chain_preview = sculpt_pose_ik_chain_init(
+ ss->pose_ik_chain_preview = SCULPT_pose_ik_chain_init(
sd, vc.obact, ss, brush, gi.location, rds);
}
/* Draw the pose brush rotation origins. */
for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) {
cursor_draw_point_screen_space(pos,
- ar,
+ region,
ss->pose_ik_chain_preview->segments[i].initial_orig,
vc.obact->obmat,
3);
}
}
- /* Draw 3D brush cursor */
+ /* Draw 3D brush cursor. */
GPU_matrix_push_projection();
- ED_view3d_draw_setup_view(CTX_wm_window(C),
+ ED_view3d_draw_setup_view(wm,
+ CTX_wm_window(C),
CTX_data_depsgraph_pointer(C),
CTX_data_scene(C),
- ar,
+ region,
CTX_wm_view3d(C),
NULL,
NULL,
@@ -1513,23 +1490,48 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
immUniformColor3fvAlpha(outline_col, outline_alpha);
GPU_line_width(2.0f);
imm_draw_circle_wire_3d(pos, 0, 0, rds, 80);
+
GPU_line_width(1.0f);
immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
imm_draw_circle_wire_3d(pos, 0, 0, rds * clamp_f(brush->alpha, 0.0f, 1.0f), 80);
GPU_matrix_pop();
- /* Update and draw dynamic mesh preview lines */
+ /* Cloth brush simulation areas. */
+ if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
+ GPU_matrix_push();
+ const float white[3] = {1.0f, 1.0f, 1.0f};
+ SCULPT_cloth_simulation_limits_draw(
+ pos, brush, vc.obact->obmat, gi.location, gi.normal, rds, 1.0f, white, 0.25f);
+ GPU_matrix_pop();
+ }
+
+ /* Layer brush height. */
+ if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
+ GPU_matrix_push();
+ SCULPT_layer_brush_height_preview_draw(pos,
+ brush,
+ vc.obact->obmat,
+ gi.location,
+ gi.normal,
+ rds,
+ 1.0f,
+ outline_col,
+ outline_alpha);
+ GPU_matrix_pop();
+ }
+
+ /* Update and draw dynamic mesh preview lines. */
GPU_matrix_push();
GPU_matrix_mul(vc.obact->obmat);
if (brush->sculpt_tool == SCULPT_TOOL_GRAB && (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) &&
!is_multires) {
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->deform_modifiers_active) {
- sculpt_geometry_preview_lines_update(C, ss, rds);
+ SCULPT_geometry_preview_lines_update(C, ss, rds);
sculpt_geometry_preview_lines_draw(pos, ss);
}
}
- /* Draw pose brush line preview */
+ /* Draw pose brush line preview. */
if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
GPU_line_width(2.0f);
@@ -1551,9 +1553,9 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
else {
/* Draw default cursor when the mouse is not over the mesh or there are no supported
- * overlays active */
+ * overlays active. */
GPU_line_width(1.0f);
- /* Reduce alpha to increase the contrast when the cursor is over the mesh */
+ /* Reduce alpha to increase the contrast when the cursor is over the mesh. */
immUniformColor3fvAlpha(outline_col, outline_alpha * 0.8);
imm_draw_circle_wire_3d(pos, translation[0], translation[1], final_radius, 80);
immUniformColor3fvAlpha(outline_col, outline_alpha * 0.35f);
@@ -1566,17 +1568,18 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
else {
if (vc.obact->sculpt->cache && !vc.obact->sculpt->cache->first_time) {
- wmViewport(&ar->winrct);
+ wmViewport(&region->winrct);
- /* Draw cached dynamic mesh preview lines */
+ /* Draw cached dynamic mesh preview lines. */
if (brush->sculpt_tool == SCULPT_TOOL_GRAB && (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) &&
!is_multires) {
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->deform_modifiers_active) {
GPU_matrix_push_projection();
- ED_view3d_draw_setup_view(CTX_wm_window(C),
+ ED_view3d_draw_setup_view(wm,
+ CTX_wm_window(C),
CTX_data_depsgraph_pointer(C),
CTX_data_scene(C),
- ar,
+ region,
CTX_wm_view3d(C),
NULL,
NULL,
@@ -1592,27 +1595,71 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
if (brush->sculpt_tool == SCULPT_TOOL_MULTIPLANE_SCRAPE &&
brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW && !ss->cache->first_time) {
GPU_matrix_push_projection();
- ED_view3d_draw_setup_view(CTX_wm_window(C),
+ ED_view3d_draw_setup_view(wm,
+ CTX_wm_window(C),
CTX_data_depsgraph_pointer(C),
CTX_data_scene(C),
- ar,
+ region,
CTX_wm_view3d(C),
NULL,
NULL,
NULL);
GPU_matrix_push();
GPU_matrix_mul(vc.obact->obmat);
- sculpt_multiplane_scrape_preview_draw(pos, ss, outline_col, outline_alpha);
+ SCULPT_multiplane_scrape_preview_draw(pos, ss, outline_col, outline_alpha);
GPU_matrix_pop();
GPU_matrix_pop_projection();
}
+ if (brush->sculpt_tool == SCULPT_TOOL_CLOTH && !ss->cache->first_time) {
+ GPU_matrix_push_projection();
+ ED_view3d_draw_setup_view(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ CTX_data_depsgraph_pointer(C),
+ CTX_data_scene(C),
+ region,
+ CTX_wm_view3d(C),
+ NULL,
+ NULL,
+ NULL);
+
+ /* Plane falloff preview */
+ if (brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE) {
+ GPU_matrix_push();
+ GPU_matrix_mul(vc.obact->obmat);
+ SCULPT_cloth_plane_falloff_preview_draw(pos, ss, outline_col, outline_alpha);
+ GPU_matrix_pop();
+ }
+
+ /* Display the simulation limits if sculpting outside them. */
+ /* This does not makes much sense of plane fallof as the fallof is infinte. */
+ else if (brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_RADIAL) {
+ if (len_v3v3(ss->cache->true_location, ss->cache->true_initial_location) >
+ ss->cache->radius * (1.0f + brush->cloth_sim_limit)) {
+ const float red[3] = {1.0f, 0.2f, 0.2f};
+ GPU_matrix_push();
+ SCULPT_cloth_simulation_limits_draw(pos,
+ brush,
+ vc.obact->obmat,
+ ss->cache->true_initial_location,
+ ss->cache->true_initial_normal,
+ ss->cache->radius,
+ 2.0f,
+ red,
+ 0.8f);
+ GPU_matrix_pop();
+ }
+ }
+
+ GPU_matrix_pop_projection();
+ }
+
wmWindowViewport(win);
}
}
}
else {
- /* Draw default cursor in unsupported modes */
+ /* Draw default cursor in unsupported modes. */
GPU_line_width(1.0f);
imm_draw_circle_wire_3d(pos, translation[0], translation[1], final_radius, 40);
}
@@ -1620,7 +1667,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
immUnbindProgram();
- /* restore GL state */
+ /* Restore GL state. */
GPU_blend(false);
GPU_line_smooth(false);
}
@@ -1636,7 +1683,7 @@ void paint_cursor_start(bContext *C, bool (*poll)(bContext *C))
CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL);
}
- /* invalidate the paint cursors */
+ /* Invalidate the paint cursors. */
BKE_paint_invalidate_overlay_all();
}
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 62c31c91f8d..68fd2f15877 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -18,8 +18,8 @@
* \ingroup edsculpt
*/
-#include <string.h>
#include <limits.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -35,8 +35,8 @@
#include "BKE_main.h"
#include "BKE_paint.h"
-#include "ED_view3d.h"
#include "ED_paint.h"
+#include "ED_view3d.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -87,39 +87,35 @@ static PaintCurvePoint *paintcurve_point_get_closest(
{
PaintCurvePoint *pcp, *closest = NULL;
int i;
- float dist, closest_dist = FLT_MAX;
+ float closest_dist = threshold;
for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
- dist = len_manhattan_v2v2(pos, pcp->bez.vec[0]);
- if (dist < threshold) {
- if (dist < closest_dist) {
- closest = pcp;
- closest_dist = dist;
- if (point) {
- *point = SEL_F1;
- }
- }
+ float dist[3];
+ char point_sel = 0;
+
+ dist[0] = len_manhattan_v2v2(pos, pcp->bez.vec[0]);
+ dist[1] = len_manhattan_v2v2(pos, pcp->bez.vec[1]);
+ dist[2] = len_manhattan_v2v2(pos, pcp->bez.vec[2]);
+
+ if (dist[1] < closest_dist) {
+ closest_dist = dist[1];
+ point_sel = SEL_F2;
}
- if (!ignore_pivot) {
- dist = len_manhattan_v2v2(pos, pcp->bez.vec[1]);
- if (dist < threshold) {
- if (dist < closest_dist) {
- closest = pcp;
- closest_dist = dist;
- if (point) {
- *point = SEL_F2;
- }
- }
- }
+ if (dist[0] < closest_dist) {
+ closest_dist = dist[0];
+ point_sel = SEL_F1;
+ }
+ if (dist[2] < closest_dist) {
+ closest_dist = dist[2];
+ point_sel = SEL_F3;
}
- dist = len_manhattan_v2v2(pos, pcp->bez.vec[2]);
- if (dist < threshold) {
- if (dist < closest_dist) {
- closest = pcp;
- closest_dist = dist;
- if (point) {
- *point = SEL_F3;
+ if (point_sel) {
+ closest = pcp;
+ if (point) {
+ if (ignore_pivot && point_sel == SEL_F2) {
+ point_sel = (dist[0] < dist[2]) ? SEL_F1 : SEL_F3;
}
+ *point = point_sel;
}
}
}
@@ -200,7 +196,7 @@ static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
PaintCurve *pc;
PaintCurvePoint *pcp;
wmWindow *window = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float vec[3] = {loc[0], loc[1], 0.0};
int add_index;
int i;
@@ -254,7 +250,7 @@ static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
ED_paintcurve_undo_push_end();
- WM_paint_cursor_tag_redraw(window, ar);
+ WM_paint_cursor_tag_redraw(window, region);
}
static int paintcurve_add_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -313,7 +309,7 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
PaintCurve *pc;
PaintCurvePoint *pcp;
wmWindow *window = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
int i;
int tot_del = 0;
pc = br->paint_curve;
@@ -365,7 +361,7 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
ED_paintcurve_undo_push_end();
- WM_paint_cursor_tag_redraw(window, ar);
+ WM_paint_cursor_tag_redraw(window, region);
return OPERATOR_FINISHED;
}
@@ -389,7 +385,7 @@ static bool paintcurve_point_select(
bContext *C, wmOperator *op, const int loc[2], bool toggle, bool extend)
{
wmWindow *window = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Paint *p = BKE_paint_get_active_from_context(C);
Brush *br = p->brush;
PaintCurve *pc;
@@ -481,7 +477,7 @@ static bool paintcurve_point_select(
ED_paintcurve_undo_push_end();
- WM_paint_cursor_tag_redraw(window, ar);
+ WM_paint_cursor_tag_redraw(window, region);
return true;
}
@@ -590,7 +586,7 @@ static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
if (pcp) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
wmWindow *window = CTX_wm_window(C);
PointSlideData *psd = MEM_mallocN(sizeof(PointSlideData), "PointSlideData");
copy_v2_v2_int(psd->initial_loc, event->mval);
@@ -613,7 +609,7 @@ static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *e
BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points);
WM_event_add_modal_handler(C, op);
- WM_paint_cursor_tag_redraw(window, ar);
+ WM_paint_cursor_tag_redraw(window, region);
return OPERATOR_RUNNING_MODAL;
}
@@ -633,7 +629,7 @@ static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *ev
switch (event->type) {
case MOUSEMOVE: {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
wmWindow *window = CTX_wm_window(C);
float diff[2] = {event->mval[0] - psd->initial_loc[0], event->mval[1] - psd->initial_loc[1]};
if (psd->select == 1) {
@@ -652,7 +648,7 @@ static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *ev
add_v2_v2v2(psd->pcp->bez.vec[opposite], psd->pcp->bez.vec[1], diff);
}
}
- WM_paint_cursor_tag_redraw(window, ar);
+ WM_paint_cursor_tag_redraw(window, region);
break;
}
default:
@@ -731,7 +727,7 @@ static int paintcurve_cursor_invoke(bContext *C, wmOperator *UNUSED(op), const w
switch (mode) {
case PAINT_MODE_TEXTURE_2D: {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceImage *sima = CTX_wm_space_image(C);
float location[2];
@@ -740,7 +736,7 @@ static int paintcurve_cursor_invoke(bContext *C, wmOperator *UNUSED(op), const w
}
UI_view2d_region_to_view(
- &ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
+ &region->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
copy_v2_v2(sima->cursor, location);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
break;
diff --git a/source/blender/editors/sculpt_paint/paint_curve_undo.c b/source/blender/editors/sculpt_paint/paint_curve_undo.c
index 5797eb68dd3..a3daef19f11 100644
--- a/source/blender/editors/sculpt_paint/paint_curve_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_curve_undo.c
@@ -179,6 +179,7 @@ void ED_paintcurve_undo_push_end(void)
{
UndoStack *ustack = ED_undo_stack_get();
BKE_undosys_step_push(ustack, NULL, NULL);
+ BKE_undosys_stack_limit_steps_and_memory_defaults(ustack);
WM_file_tag_modified();
}
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index 026dc39c668..e9dcc4a356a 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2010 by Nicholas Bishop
@@ -33,12 +33,12 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_paint.h"
+#include "BKE_pbvh.h"
#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
@@ -55,18 +55,20 @@
#include "bmesh.h"
#include "paint_intern.h"
-#include "sculpt_intern.h" /* for undo push */
+
+/* For undo push. */
+#include "sculpt_intern.h"
#include <assert.h>
-/* return true if the element should be hidden/shown */
+/* Return true if the element should be hidden/shown. */
static bool is_effected(PartialVisArea area,
float planes[4][4],
const float co[3],
const float mask)
{
if (area == PARTIALVIS_ALL) {
- return 1;
+ return true;
}
else if (area == PARTIALVIS_MASKED) {
return mask > 0.5f;
@@ -95,13 +97,13 @@ static void partialvis_update_mesh(Object *ob,
BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
paint_mask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
- sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
+ SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
for (i = 0; i < totvert; i++) {
MVert *v = &mvert[vert_indices[i]];
float vmask = paint_mask ? paint_mask[vert_indices[i]] : 0;
- /* hide vertex if in the hide volume */
+ /* Hide vertex if in the hide volume. */
if (is_effected(area, planes, v->co, vmask)) {
if (action == PARTIALVIS_HIDE) {
v->flag |= ME_HIDE;
@@ -135,35 +137,34 @@ static void partialvis_update_grids(Depsgraph *depsgraph,
{
CCGElem **grids;
BLI_bitmap **grid_hidden;
- int *grid_indices, totgrid, i;
+ int *grid_indices, totgrid;
bool any_changed = false, any_visible = false;
- /* get PBVH data */
+ /* Get PBVH data. */
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, &grids);
grid_hidden = BKE_pbvh_grid_hidden(pbvh);
CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
- sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
+ SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
- for (i = 0; i < totgrid; i++) {
+ for (int i = 0; i < totgrid; i++) {
int any_hidden = 0;
- int g = grid_indices[i], x, y;
+ int g = grid_indices[i];
BLI_bitmap *gh = grid_hidden[g];
if (!gh) {
switch (action) {
case PARTIALVIS_HIDE:
- /* create grid flags data */
+ /* Create grid flags data. */
gh = grid_hidden[g] = BLI_BITMAP_NEW(key.grid_area, "partialvis_update_grids");
break;
case PARTIALVIS_SHOW:
- /* entire grid is visible, nothing to show */
+ /* Entire grid is visible, nothing to show. */
continue;
}
}
else if (action == PARTIALVIS_SHOW && area == PARTIALVIS_ALL) {
- /* special case if we're showing all, just free the
- * grid */
+ /* Special case if we're showing all, just free the grid. */
MEM_freeN(gh);
grid_hidden[g] = NULL;
any_changed = true;
@@ -171,21 +172,21 @@ static void partialvis_update_grids(Depsgraph *depsgraph,
continue;
}
- for (y = 0; y < key.grid_size; y++) {
- for (x = 0; x < key.grid_size; x++) {
+ for (int y = 0; y < key.grid_size; y++) {
+ for (int x = 0; x < key.grid_size; x++) {
CCGElem *elem = CCG_grid_elem(&key, grids[g], x, y);
const float *co = CCG_elem_co(&key, elem);
float mask = key.has_mask ? *CCG_elem_mask(&key, elem) : 0.0f;
- /* skip grid element if not in the effected area */
+ /* Skip grid element if not in the effected area. */
if (is_effected(area, planes, co, mask)) {
- /* set or clear the hide flag */
+ /* Set or clear the hide flag. */
BLI_BITMAP_SET(gh, y * key.grid_size + x, action == PARTIALVIS_HIDE);
any_changed = true;
}
- /* keep track of whether any elements are still hidden */
+ /* Keep track of whether any elements are still hidden. */
if (BLI_BITMAP_TEST(gh, y * key.grid_size + x)) {
any_hidden = true;
}
@@ -195,15 +196,14 @@ static void partialvis_update_grids(Depsgraph *depsgraph,
}
}
- /* if everything in the grid is now visible, free the grid
- * flags */
+ /* If everything in the grid is now visible, free the grid flags. */
if (!any_hidden) {
MEM_freeN(gh);
grid_hidden[g] = NULL;
}
}
- /* mark updates if anything was hidden/shown */
+ /* Mark updates if anything was hidden/shown. */
if (any_changed) {
BKE_pbvh_node_mark_rebuild_draw(node);
BKE_pbvh_node_fully_hidden_set(node, !any_visible);
@@ -225,7 +225,7 @@ static void partialvis_update_bmesh_verts(BMesh *bm,
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
float *vmask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK);
- /* hide vertex if in the hide volume */
+ /* Hide vertex if in the hide volume. */
if (is_effected(area, planes, v->co, *vmask)) {
if (action == PARTIALVIS_HIDE) {
BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
@@ -274,13 +274,13 @@ static void partialvis_update_bmesh(Object *ob,
other = BKE_pbvh_bmesh_node_other_verts(node);
faces = BKE_pbvh_bmesh_node_faces(node);
- sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
+ SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
partialvis_update_bmesh_verts(bm, unique, action, area, planes, &any_changed, &any_visible);
partialvis_update_bmesh_verts(bm, other, action, area, planes, &any_changed, &any_visible);
- /* finally loop over node faces and tag the ones that are fully hidden */
+ /* Finally loop over node faces and tag the ones that are fully hidden. */
partialvis_update_bmesh_faces(faces);
if (any_changed) {
@@ -307,7 +307,7 @@ static void clip_planes_from_rect(bContext *C,
view3d_operator_needs_opengl(C);
ED_view3d_viewcontext_init(C, &vc, depsgraph);
- ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc.region, vc.obact, rect);
}
/* If mode is inside, get all PBVH nodes that lie at least partially
@@ -319,7 +319,7 @@ static void get_pbvh_nodes(
{
BKE_pbvh_SearchCallback cb = NULL;
- /* select search callback */
+ /* Select search callback. */
switch (mode) {
case PARTIALVIS_INSIDE:
cb = BKE_pbvh_node_frustum_contain_AABB;
@@ -338,7 +338,7 @@ static void get_pbvh_nodes(
static int hide_show_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Object *ob = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Mesh *me = ob->data;
@@ -349,9 +349,9 @@ static int hide_show_exec(bContext *C, wmOperator *op)
PBVHType pbvh_type;
float clip_planes[4][4];
rcti rect;
- int totnode, i;
+ int totnode;
- /* read operator properties */
+ /* Read operator properties. */
action = RNA_enum_get(op->ptr, "action");
area = RNA_enum_get(op->ptr, "area");
rect_from_props(&rect, op->ptr);
@@ -366,17 +366,17 @@ static int hide_show_exec(bContext *C, wmOperator *op)
negate_m4(clip_planes);
- /* start undo */
+ /* Start undo. */
switch (action) {
case PARTIALVIS_HIDE:
- sculpt_undo_push_begin("Hide area");
+ SCULPT_undo_push_begin("Hide area");
break;
case PARTIALVIS_SHOW:
- sculpt_undo_push_begin("Show area");
+ SCULPT_undo_push_begin("Show area");
break;
}
- for (i = 0; i < totnode; i++) {
+ for (int i = 0; i < totnode; i++) {
switch (pbvh_type) {
case PBVH_FACES:
partialvis_update_mesh(ob, pbvh, nodes[i], action, area, clip_planes);
@@ -394,16 +394,19 @@ static int hide_show_exec(bContext *C, wmOperator *op)
MEM_freeN(nodes);
}
- /* end undo */
- sculpt_undo_push_end();
+ /* End undo. */
+ SCULPT_undo_push_end();
- /* ensure that edges and faces get hidden as well (not used by
- * sculpt but it looks wrong when entering editmode otherwise) */
+ /* Ensure that edges and faces get hidden as well (not used by
+ * sculpt but it looks wrong when entering editmode otherwise). */
if (pbvh_type == PBVH_FACES) {
BKE_mesh_flush_hidden_from_verts(me);
}
- ED_region_tag_redraw(ar);
+ SCULPT_visibility_sync_all_vertex_to_face_sets(ob->sculpt);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -440,21 +443,21 @@ void PAINT_OT_hide_show(struct wmOperatorType *ot)
{0, NULL, 0, NULL, NULL},
};
- /* identifiers */
+ /* Identifiers. */
ot->name = "Hide/Show";
ot->idname = "PAINT_OT_hide_show";
ot->description = "Hide/show some vertices";
- /* api callbacks */
+ /* API callbacks. */
ot->invoke = hide_show_invoke;
ot->modal = WM_gesture_box_modal;
ot->exec = hide_show_exec;
- /* sculpt-only for now */
- ot->poll = sculpt_mode_poll_view3d;
+ /* Sculpt-only for now. */
+ ot->poll = SCULPT_mode_poll_view3d;
ot->flag = OPTYPE_REGISTER;
- /* rna */
+ /* RNA. */
RNA_def_enum(ot->srna,
"action",
action_items,
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 6d1a32d1c45..e227db1c644 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -24,14 +24,14 @@
*/
#include <float.h>
-#include <string.h>
-#include <stdio.h>
#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -44,9 +44,9 @@
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "BKE_brush.h"
#include "BKE_colorband.h"
#include "BKE_context.h"
-#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -67,9 +67,9 @@
#include "ED_view3d.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -120,7 +120,7 @@ void imapaint_region_tiles(
}
void ED_imapaint_dirty_region(
- Image *ima, ImBuf *ibuf, int tile_number, int x, int y, int w, int h, bool find_old)
+ Image *ima, ImBuf *ibuf, ImageUser *iuser, int x, int y, int w, int h, bool find_old)
{
ImBuf *tmpibuf = NULL;
int tilex, tiley, tilew, tileh, tx, ty;
@@ -153,7 +153,7 @@ void ED_imapaint_dirty_region(
for (ty = tiley; ty <= tileh; ty++) {
for (tx = tilex; tx <= tilew; tx++) {
ED_image_paint_tile_push(
- undo_tiles, ima, ibuf, &tmpibuf, tile_number, tx, ty, NULL, NULL, false, find_old);
+ undo_tiles, ima, ibuf, &tmpibuf, iuser, tx, ty, NULL, NULL, false, find_old);
}
}
@@ -289,9 +289,9 @@ static bool image_paint_poll_ex(bContext *C, bool check_tool)
SpaceImage *sima = CTX_wm_space_image(C);
if (sima) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- if ((sima->mode == SI_MODE_PAINT) && ar->regiontype == RGN_TYPE_WINDOW) {
+ if ((sima->mode == SI_MODE_PAINT) && region->regiontype == RGN_TYPE_WINDOW) {
return 1;
}
}
@@ -388,6 +388,10 @@ void paint_brush_color_get(struct Scene *scene,
break;
}
}
+ /* Gradient / Colorband colors are not considered PROP_COLOR_GAMMA.
+ * Brush colors are expected to be in sRGB though. */
+ IMB_colormanagement_scene_linear_to_srgb_v3(color_gr);
+
copy_v3_v3(color, color_gr);
}
else {
@@ -440,7 +444,7 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- ARegion *ar = pop->vc.ar;
+ ARegion *region = pop->vc.region;
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -449,7 +453,8 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
immBegin(GPU_PRIM_LINES, 2);
immVertex2i(pos, x, y);
- immVertex2i(pos, pop->startmouse[0] + ar->winrct.xmin, pop->startmouse[1] + ar->winrct.ymin);
+ immVertex2i(
+ pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin);
immEnd();
GPU_line_width(2.0);
@@ -457,7 +462,8 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
immBegin(GPU_PRIM_LINES, 2);
immVertex2i(pos, x, y);
- immVertex2i(pos, pop->startmouse[0] + ar->winrct.xmin, pop->startmouse[1] + ar->winrct.ymin);
+ immVertex2i(
+ pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin);
immEnd();
immUnbindProgram();
@@ -762,12 +768,12 @@ void PAINT_OT_image_paint(wmOperatorType *ot)
bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
{
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
+ ScrArea *area = CTX_wm_area(C);
+ if (area && area->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = area->spacedata.first;
if (sima->mode == SI_MODE_PAINT) {
- ARegion *ar = CTX_wm_region(C);
- ED_space_image_get_zoom(sima, ar, zoomx, zoomy);
+ ARegion *region = CTX_wm_region(C);
+ ED_space_image_get_zoom(sima, region, zoomx, zoomy);
return 1;
}
}
@@ -806,12 +812,12 @@ void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene)
ImagePaintSettings *imapaint = &settings->imapaint;
bool enabled = false;
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
bScreen *screen = WM_window_get_active_screen(win);
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_IMAGE) {
- if (((SpaceImage *)sa->spacedata.first)->mode == SI_MODE_PAINT) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area->spacetype == SPACE_IMAGE) {
+ if (((SpaceImage *)area->spacedata.first)->mode == SI_MODE_PAINT) {
enabled = true;
}
}
@@ -871,10 +877,10 @@ static int grab_clone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Brush *brush = image_paint_brush(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
GrabClone *cmv = op->customdata;
float startfx, startfy, fx, fy, delta[2];
- int xmin = ar->winrct.xmin, ymin = ar->winrct.ymin;
+ int xmin = region->winrct.xmin, ymin = region->winrct.ymin;
switch (event->type) {
case LEFTMOUSE:
@@ -885,8 +891,8 @@ static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEMOVE:
/* mouse moved, so move the clone image */
UI_view2d_region_to_view(
- &ar->v2d, cmv->startx - xmin, cmv->starty - ymin, &startfx, &startfy);
- UI_view2d_region_to_view(&ar->v2d, event->x - xmin, event->y - ymin, &fx, &fy);
+ &region->v2d, cmv->startx - xmin, cmv->starty - ymin, &startfx, &startfy);
+ UI_view2d_region_to_view(&region->v2d, event->x - xmin, event->y - ymin, &fx, &fy);
delta[0] = fx - startfx;
delta[1] = fy - startfy;
@@ -947,9 +953,9 @@ typedef struct {
static void sample_color_update_header(SampleColorData *data, bContext *C)
{
char msg[UI_MAX_DRAW_STR];
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- if (sa) {
+ if (area) {
BLI_snprintf(msg,
sizeof(msg),
TIP_("Sample color for %s"),
@@ -965,14 +971,14 @@ static int sample_color_exec(bContext *C, wmOperator *op)
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
wmWindow *win = CTX_wm_window(C);
const bool show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
int location[2];
paint->flags &= ~PAINT_SHOW_BRUSH;
/* force redraw without cursor */
- WM_paint_cursor_tag_redraw(win, ar);
+ WM_paint_cursor_tag_redraw(win, region);
WM_redraw_windows(C);
RNA_int_get_array(op->ptr, "location", location);
@@ -980,7 +986,7 @@ static int sample_color_exec(bContext *C, wmOperator *op)
const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) &&
!RNA_boolean_get(op->ptr, "merged");
- paint_sample_color(C, ar, location[0], location[1], use_sample_texture, use_palette);
+ paint_sample_color(C, region, location[0], location[1], use_sample_texture, use_palette);
if (show_cursor) {
paint->flags |= PAINT_SHOW_BRUSH;
@@ -997,7 +1003,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
SampleColorData *data = MEM_mallocN(sizeof(SampleColorData), "sample color custom data");
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
wmWindow *win = CTX_wm_window(C);
data->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
@@ -1012,7 +1018,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
WM_event_add_modal_handler(C, op);
/* force redraw without cursor */
- WM_paint_cursor_tag_redraw(win, ar);
+ WM_paint_cursor_tag_redraw(win, region);
WM_redraw_windows(C);
RNA_int_set_array(op->ptr, "location", event->mval);
@@ -1021,7 +1027,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) &&
!RNA_boolean_get(op->ptr, "merged");
- paint_sample_color(C, ar, event->mval[0], event->mval[1], use_sample_texture, false);
+ paint_sample_color(C, region, event->mval[0], event->mval[1], use_sample_texture, false);
WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
@@ -1058,18 +1064,18 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case MOUSEMOVE: {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1], use_sample_texture, false);
+ paint_sample_color(C, region, event->mval[0], event->mval[1], use_sample_texture, false);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
break;
}
case LEFTMOUSE:
if (event->val == KM_PRESS) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1], use_sample_texture, true);
+ paint_sample_color(C, region, event->mval[0], event->mval[1], use_sample_texture, true);
if (!data->sample_palette) {
data->sample_palette = true;
sample_color_update_header(data, C);
@@ -1157,7 +1163,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
toggle_paint_cursor(C, 0);
}
else {
- bScreen *sc;
+ bScreen *screen;
Image *ima = NULL;
ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
@@ -1170,7 +1176,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
/* entering paint mode also sets image to editors */
if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
/* set the current material active paint slot on image editor */
- Material *ma = give_current_material(ob, ob->actcol);
+ Material *ma = BKE_object_material_get(ob, ob->actcol);
if (ma && ma->texpaintslot) {
ima = ma->texpaintslot[ma->paint_active_slot].ima;
@@ -1181,11 +1187,11 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
}
if (ima) {
- for (sc = bmain->screens.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
+ for (screen = bmain->screens.first; screen; screen = screen->id.next) {
+ ScrArea *area;
+ for (area = screen->areabase.first; area; area = area->next) {
SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ for (sl = area->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
@@ -1286,9 +1292,9 @@ static bool brush_colors_flip_poll(bContext *C)
void PAINT_OT_brush_colors_flip(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Brush Colors Flip";
+ ot->name = "Swap Colors";
ot->idname = "PAINT_OT_brush_colors_flip";
- ot->description = "Toggle foreground and background brush colors";
+ ot->description = "Swap primary and secondary brush colors";
/* api callbacks */
ot->exec = brush_colors_flip_exec;
@@ -1303,20 +1309,20 @@ void ED_imapaint_bucket_fill(struct bContext *C,
wmOperator *op,
const int mouse[2])
{
- wmWindowManager *wm = CTX_wm_manager(C);
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = sima->image;
- BKE_undosys_step_push_init_with_type(wm->undo_stack, C, op->type->name, BKE_UNDOSYS_TYPE_IMAGE);
+ if (sima && sima->image) {
+ Image *ima = sima->image;
- ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
+ ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
- float mouse_init[2] = {mouse[0], mouse[1]};
- paint_2d_bucket_fill(C, color, NULL, mouse_init, NULL, NULL);
+ float mouse_init[2] = {mouse[0], mouse[1]};
+ paint_2d_bucket_fill(C, color, NULL, mouse_init, NULL, NULL);
- BKE_undosys_step_push(wm->undo_stack, C, op->type->name);
+ ED_image_undo_push_end();
- DEG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
+ }
}
static bool texture_paint_poll(bContext *C)
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 7f71110b360..16ccfaf8286 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -26,19 +26,19 @@
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
-#include "DNA_object_types.h"
+#include "BLI_bitmap.h"
#include "BLI_listbase.h"
#include "BLI_math_color_blend.h"
#include "BLI_stack.h"
-#include "BLI_bitmap.h"
#include "BLI_task.h"
+#include "BKE_brush.h"
#include "BKE_colorband.h"
#include "BKE_context.h"
-#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_paint.h"
#include "BKE_report.h"
@@ -48,9 +48,9 @@
#include "ED_paint.h"
#include "ED_screen.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "IMB_colormanagement.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -80,11 +80,11 @@ typedef struct BrushPainterCache {
ImBuf *ibuf;
ImBuf *texibuf;
- unsigned short *curve_mask;
- unsigned short *tex_mask;
- unsigned short *tex_mask_old;
- unsigned int tex_mask_old_w;
- unsigned int tex_mask_old_h;
+ ushort *curve_mask;
+ ushort *tex_mask;
+ ushort *tex_mask_old;
+ uint tex_mask_old_w;
+ uint tex_mask_old_h;
int image_size[2];
} BrushPainterCache;
@@ -228,7 +228,7 @@ static void brush_imbuf_tex_co(rctf *mapping, int x, int y, float texco[3])
}
/* create a mask with the mask texture */
-static unsigned short *brush_painter_mask_ibuf_new(BrushPainter *painter, const int size)
+static ushort *brush_painter_mask_ibuf_new(BrushPainter *painter, const int size)
{
Scene *scene = painter->scene;
Brush *brush = painter->brush;
@@ -236,10 +236,10 @@ static unsigned short *brush_painter_mask_ibuf_new(BrushPainter *painter, const
struct ImagePool *pool = painter->pool;
float texco[3];
- unsigned short *mask, *m;
+ ushort *mask, *m;
int x, y, thread = 0;
- mask = MEM_mallocN(sizeof(unsigned short) * size * size, "brush_painter_mask");
+ mask = MEM_mallocN(sizeof(ushort) * size * size, "brush_painter_mask");
m = mask;
for (y = 0; y < size; y++) {
@@ -247,7 +247,7 @@ static unsigned short *brush_painter_mask_ibuf_new(BrushPainter *painter, const
float res;
brush_imbuf_tex_co(&mask_mapping, x, y, texco);
res = BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
- *m = (unsigned short)(65535.0f * res);
+ *m = (ushort)(65535.0f * res);
}
}
@@ -257,7 +257,7 @@ static unsigned short *brush_painter_mask_ibuf_new(BrushPainter *painter, const
/* update rectangular section of the brush image */
static void brush_painter_mask_imbuf_update(BrushPainter *painter,
ImagePaintTile *tile,
- unsigned short *tex_mask_old,
+ ushort *tex_mask_old,
int origx,
int origy,
int w,
@@ -271,14 +271,14 @@ static void brush_painter_mask_imbuf_update(BrushPainter *painter,
BrushPainterCache *cache = &tile->cache;
rctf tex_mapping = painter->mask_mapping;
struct ImagePool *pool = painter->pool;
- unsigned short res;
+ ushort res;
bool use_texture_old = (tex_mask_old != NULL);
int x, y, thread = 0;
- unsigned short *tex_mask = cache->tex_mask;
- unsigned short *tex_mask_cur = cache->tex_mask_old;
+ ushort *tex_mask = cache->tex_mask;
+ ushort *tex_mask_cur = cache->tex_mask_old;
/* fill pixels */
for (y = origy; y < h; y++) {
@@ -287,13 +287,12 @@ static void brush_painter_mask_imbuf_update(BrushPainter *painter,
float texco[3];
/* handle byte pixel */
- unsigned short *b = tex_mask + (y * diameter + x);
- unsigned short *t = tex_mask_cur + (y * diameter + x);
+ ushort *b = tex_mask + (y * diameter + x);
+ ushort *t = tex_mask_cur + (y * diameter + x);
if (!use_texture_old) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
- res = (unsigned short)(65535.0f *
- BKE_brush_sample_masktex(scene, brush, texco, thread, pool));
+ res = (ushort)(65535.0f * BKE_brush_sample_masktex(scene, brush, texco, thread, pool));
}
/* read from old texture buffer */
@@ -320,19 +319,17 @@ static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
const int diameter)
{
BrushPainterCache *cache = &tile->cache;
- unsigned short *tex_mask_old;
+ ushort *tex_mask_old;
int destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
/* create brush image buffer if it didn't exist yet */
if (!cache->tex_mask) {
- cache->tex_mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter,
- "brush_painter_mask");
+ cache->tex_mask = MEM_mallocN(sizeof(ushort) * diameter * diameter, "brush_painter_mask");
}
/* create new texture image buffer with coordinates relative to old */
tex_mask_old = cache->tex_mask_old;
- cache->tex_mask_old = MEM_mallocN(sizeof(unsigned short) * diameter * diameter,
- "brush_painter_mask");
+ cache->tex_mask_old = MEM_mallocN(sizeof(ushort) * diameter * diameter, "brush_painter_mask");
if (tex_mask_old) {
ImBuf maskibuf;
@@ -393,18 +390,18 @@ static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
}
/* create a mask with the falloff strength */
-static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter,
- int diameter,
- float radius,
- const float pos[2])
+static ushort *brush_painter_curve_mask_new(BrushPainter *painter,
+ int diameter,
+ float radius,
+ const float pos[2])
{
Brush *brush = painter->brush;
int offset = (int)floorf(diameter / 2.0f);
- unsigned short *mask, *m;
+ ushort *mask, *m;
- mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
+ mask = MEM_mallocN(sizeof(ushort) * diameter * diameter, "brush_painter_mask");
m = mask;
int aa_samples = 1.0f / (radius * 0.20f);
@@ -446,9 +443,9 @@ static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter,
float len = len_v2(xy_rot);
float p = len / radius;
if (hardness < 1.0f) {
- p = (p - hardness) / (1 - hardness);
+ p = (p - hardness) / (1.0f - hardness);
p = 1.0f - p;
- CLAMP(p, 0, 1);
+ CLAMP(p, 0.0f, 1.0f);
}
else {
p = 1.0;
@@ -458,7 +455,7 @@ static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter,
total_samples += curve * hardness_factor;
}
}
- *m = (unsigned short)(total_samples * norm_factor);
+ *m = (ushort)(total_samples * norm_factor);
}
}
@@ -528,7 +525,7 @@ static ImBuf *brush_painter_imbuf_new(
}
else {
/* write to byte pixel */
- unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4;
+ uchar *dst = (uchar *)ibuf->rect + (y * size + x) * 4;
rgb_float_to_uchar(dst, rgba);
dst[3] = unit_float_to_uchar_clamp(rgba[3]);
@@ -574,7 +571,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
/* get brush color */
if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
paint_brush_color_get(
- scene, brush, use_color_correction, cache->invert, 0.0, 1.0, brush_rgb, display);
+ scene, brush, use_color_correction, cache->invert, 0.0f, 1.0f, brush_rgb, display);
}
else {
brush_rgb[0] = 1.0f;
@@ -624,16 +621,16 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
bf[3] = rgba[3];
}
else {
- unsigned char crgba[4];
+ uchar crgba[4];
/* handle byte pixel */
- unsigned char *b = (unsigned char *)ibuf->rect + (y * ibuf->x + x) * 4;
- unsigned char *t = (unsigned char *)texibuf->rect + (y * texibuf->x + x) * 4;
+ uchar *b = (uchar *)ibuf->rect + (y * ibuf->x + x) * 4;
+ uchar *t = (uchar *)texibuf->rect + (y * texibuf->x + x) * 4;
/* read from old texture buffer */
if (use_texture_old) {
- unsigned char *ot = (unsigned char *)oldtexibuf->rect +
- ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
+ uchar *ot = (uchar *)oldtexibuf->rect +
+ ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
crgba[0] = ot[0];
crgba[1] = ot[1];
crgba[2] = ot[2];
@@ -975,7 +972,7 @@ static void paint_2d_ibuf_rgb_get(ImBuf *ibuf, int x, int y, float r_rgb[4])
copy_v4_v4(r_rgb, rrgbf);
}
else {
- unsigned char *rrgb = (unsigned char *)ibuf->rect + (ibuf->x * y + x) * 4;
+ uchar *rrgb = (uchar *)ibuf->rect + (ibuf->x * y + x) * 4;
straight_uchar_to_premul_float(r_rgb, rrgb);
}
}
@@ -1001,8 +998,8 @@ static void paint_2d_ibuf_rgb_set(
rrgbf[3] = rgb[3];
}
else {
- unsigned char straight[4];
- unsigned char *rrgb = (unsigned char *)ibuf->rect + (ibuf->x * y + x) * 4;
+ uchar straight[4];
+ uchar *rrgb = (uchar *)ibuf->rect + (ibuf->x * y + x) * 4;
premul_float_to_straight_uchar(straight, rgb);
rrgb[0] = straight[0];
@@ -1329,17 +1326,17 @@ static void paint_2d_do_making_brush(ImagePaintState *s,
for (int ty = tiley; ty <= tileh; ty++) {
for (int tx = tilex; tx <= tilew; tx++) {
/* retrieve original pixels + mask from undo buffer */
- unsigned short *mask;
+ ushort *mask;
int origx = region->destx - tx * ED_IMAGE_UNDO_TILE_SIZE;
int origy = region->desty - ty * ED_IMAGE_UNDO_TILE_SIZE;
if (tile->canvas->rect_float) {
tmpbuf.rect_float = ED_image_paint_tile_find(
- undo_tiles, s->image, tile->canvas, tile->iuser.tile, tx, ty, &mask, false);
+ undo_tiles, s->image, tile->canvas, &tile->iuser, tx, ty, &mask, false);
}
else {
tmpbuf.rect = ED_image_paint_tile_find(
- undo_tiles, s->image, tile->canvas, tile->iuser.tile, tx, ty, &mask, false);
+ undo_tiles, s->image, tile->canvas, &tile->iuser, tx, ty, &mask, false);
}
IMB_rectblend(tile->canvas,
@@ -1448,7 +1445,7 @@ static int paint_2d_op(void *state,
for (a = 0; a < tot; a++) {
ED_imapaint_dirty_region(s->image,
canvas,
- tile->iuser.tile,
+ &tile->iuser,
region[a].destx,
region[a].desty,
region[a].width,
@@ -1609,7 +1606,9 @@ void paint_2d_stroke(void *ps,
copy_v2_v2(last_uv, old_uv);
}
- float uv_brush_size[2] = {base_size / s->tiles[0].size[0], base_size / s->tiles[0].size[1]};
+ const float uv_brush_size[2] = {
+ (s->symmetry & PAINT_TILE_X) ? FLT_MAX : base_size / s->tiles[0].size[0],
+ (s->symmetry & PAINT_TILE_Y) ? FLT_MAX : base_size / s->tiles[0].size[1]};
for (int i = 0; i < s->num_tiles; i++) {
ImagePaintTile *tile = &s->tiles[i];
@@ -1640,13 +1639,14 @@ void paint_2d_stroke(void *ps,
paint_2d_uv_to_coord(tile, last_uv, tile->last_paintpos);
/* Second check in pixel coordinates. */
- const float pixel_brush_size[] = {size, size};
+ const float pixel_brush_size[] = {(s->symmetry & PAINT_TILE_X) ? FLT_MAX : size,
+ (s->symmetry & PAINT_TILE_Y) ? FLT_MAX : size};
if (!(is_inside_tile(tile->size, new_coord, pixel_brush_size) ||
is_inside_tile(tile->size, old_coord, pixel_brush_size))) {
continue;
}
- ImBuf *ibuf = BKE_image_acquire_ibuf(s->image, &tile->iuser, NULL);
+ ImBuf *ibuf = tile->canvas;
/* OCIO_TODO: float buffers are now always linear, so always use color correction
* this should probably be changed when texture painting color space is supported
@@ -1667,6 +1667,7 @@ void paint_2d_stroke(void *ps,
void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
{
Scene *scene = CTX_data_scene(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
ToolSettings *settings = scene->toolsettings;
Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
@@ -1697,7 +1698,7 @@ void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
s->num_tiles = BLI_listbase_count(&s->image->tiles);
s->tiles = MEM_callocN(sizeof(ImagePaintTile) * s->num_tiles, "ImagePaintTile");
for (int i = 0; i < s->num_tiles; i++) {
- BKE_imageuser_default(&s->tiles[i].iuser);
+ s->tiles[i].iuser = sima->iuser;
}
s->tiles[0].iuser.ok = true;
@@ -1711,6 +1712,7 @@ void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
}
if (ibuf->channels != 4) {
+ BKE_image_release_ibuf(s->image, ibuf, NULL);
BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
MEM_freeN(s->tiles);
MEM_freeN(s);
@@ -1824,7 +1826,7 @@ static void paint_2d_fill_add_pixel_byte(const int x_px,
if (!BLI_BITMAP_TEST(touched, coordinate)) {
float color_f[4];
- unsigned char *color_b = (unsigned char *)(ibuf->rect + coordinate);
+ uchar *color_b = (uchar *)(ibuf->rect + coordinate);
rgba_uchar_to_float(color_f, color_b);
straight_to_premul_v4(color_f);
@@ -1890,9 +1892,9 @@ void paint_2d_bucket_fill(const bContext *C,
ImBuf *ibuf;
int x_px, y_px;
- unsigned int color_b;
+ uint color_b;
float color_f[4];
- float strength = br ? br->alpha : 1.0f;
+ float strength = (s && br) ? BKE_brush_alpha_get(s->scene, br) : 1.0f;
bool do_float;
@@ -1930,7 +1932,7 @@ void paint_2d_bucket_fill(const bContext *C,
* be in gamma space. strictly speaking this is not correct, but blender does not paint
* byte images in linear space */
if (!do_float) {
- linearrgb_to_srgb_uchar3((unsigned char *)&color_b, color);
+ linearrgb_to_srgb_uchar3((uchar *)&color_b, color);
*(((char *)&color_b) + 3) = strength * 255;
}
else {
@@ -1940,7 +1942,7 @@ void paint_2d_bucket_fill(const bContext *C,
if (!mouse_final || !br) {
/* first case, no image UV, fill the whole image */
- ED_imapaint_dirty_region(ima, ibuf, tile_number, 0, 0, ibuf->x, ibuf->y, false);
+ ED_imapaint_dirty_region(ima, ibuf, iuser, 0, 0, ibuf->x, ibuf->y, false);
if (do_float) {
for (x_px = 0; x_px < ibuf->x; x_px++) {
@@ -1954,9 +1956,9 @@ void paint_2d_bucket_fill(const bContext *C,
else {
for (x_px = 0; x_px < ibuf->x; x_px++) {
for (y_px = 0; y_px < ibuf->y; y_px++) {
- blend_color_mix_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
- (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
- (unsigned char *)&color_b);
+ blend_color_mix_byte((uchar *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
+ (uchar *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
+ (uchar *)&color_b);
}
}
}
@@ -1983,7 +1985,7 @@ void paint_2d_bucket_fill(const bContext *C,
}
/* change image invalidation method later */
- ED_imapaint_dirty_region(ima, ibuf, tile_number, 0, 0, ibuf->x, ibuf->y, false);
+ ED_imapaint_dirty_region(ima, ibuf, iuser, 0, 0, ibuf->x, ibuf->y, false);
stack = BLI_stack_new(sizeof(size_t), __func__);
touched = BLI_BITMAP_NEW(((size_t)ibuf->x) * ibuf->y, "bucket_fill_bitmap");
@@ -1995,7 +1997,7 @@ void paint_2d_bucket_fill(const bContext *C,
}
else {
int pixel_color_b = *(ibuf->rect + coordinate);
- rgba_uchar_to_float(pixel_color, (unsigned char *)&pixel_color_b);
+ rgba_uchar_to_float(pixel_color, (uchar *)&pixel_color_b);
straight_to_premul_v4(pixel_color);
}
@@ -2050,9 +2052,9 @@ void paint_2d_bucket_fill(const bContext *C,
while (!BLI_stack_is_empty(stack)) {
BLI_stack_pop(stack, &coordinate);
- IMB_blend_color_byte((unsigned char *)(ibuf->rect + coordinate),
- (unsigned char *)(ibuf->rect + coordinate),
- (unsigned char *)&color_b,
+ IMB_blend_color_byte((uchar *)(ibuf->rect + coordinate),
+ (uchar *)(ibuf->rect + coordinate),
+ (uchar *)&color_b,
br->blend);
/* reconstruct the coordinates here */
@@ -2112,11 +2114,12 @@ void paint_2d_gradient_fill(
ImBuf *ibuf;
int x_px, y_px;
- unsigned int color_b;
+ uint color_b;
float color_f[4];
float image_init[2], image_final[2];
float tangent[2];
float line_len_sq_inv, line_len;
+ const float brush_alpha = BKE_brush_alpha_get(s->scene, br);
bool do_float;
@@ -2156,7 +2159,7 @@ void paint_2d_gradient_fill(
do_float = (ibuf->rect_float != NULL);
/* this will be substituted by something else when selection is available */
- ED_imapaint_dirty_region(ima, ibuf, tile_number, 0, 0, ibuf->x, ibuf->y, false);
+ ED_imapaint_dirty_region(ima, ibuf, iuser, 0, 0, ibuf->x, ibuf->y, false);
if (do_float) {
for (x_px = 0; x_px < ibuf->x; x_px++) {
@@ -2178,7 +2181,7 @@ void paint_2d_gradient_fill(
BKE_colorband_evaluate(br->gradient, f, color_f);
/* convert to premultiplied */
mul_v3_fl(color_f, color_f[3]);
- color_f[3] *= br->alpha;
+ color_f[3] *= brush_alpha;
IMB_blend_color_float(ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px),
ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px),
color_f,
@@ -2206,11 +2209,11 @@ void paint_2d_gradient_fill(
BKE_colorband_evaluate(br->gradient, f, color_f);
linearrgb_to_srgb_v3_v3(color_f, color_f);
- rgba_float_to_uchar((unsigned char *)&color_b, color_f);
- ((unsigned char *)&color_b)[3] *= br->alpha;
- IMB_blend_color_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
- (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
- (unsigned char *)&color_b,
+ rgba_float_to_uchar((uchar *)&color_b, color_f);
+ ((uchar *)&color_b)[3] *= brush_alpha;
+ IMB_blend_color_byte((uchar *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
+ (uchar *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
+ (uchar *)&color_b,
br->blend);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index d649f5017eb..5e3204b6d5a 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -24,9 +24,9 @@
*/
#include <float.h>
-#include <string.h>
-#include <stdio.h>
#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -61,12 +61,13 @@
#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_colorband.h"
-#include "BKE_context.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
#include "BKE_customdata.h"
+#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -81,12 +82,13 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "ED_object.h"
#include "ED_node.h"
+#include "ED_object.h"
#include "ED_paint.h"
#include "ED_screen.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
+#include "ED_view3d_offscreen.h"
#include "GPU_extensions.h"
#include "GPU_init_exit.h"
@@ -110,7 +112,7 @@ static void partial_redraw_array_init(ImagePaintPartialRedraw *pr);
/* Defines and Structs */
/* unit_float_to_uchar_clamp as inline function */
-BLI_INLINE unsigned char f_to_char(const float val)
+BLI_INLINE uchar f_to_char(const float val)
{
return unit_float_to_uchar_clamp(val);
}
@@ -204,7 +206,7 @@ typedef struct ProjPaintImage {
volatile void **undoRect;
/** The mask accumulation must happen on canvas, not on space screen bucket.
* Here we store the mask rectangle. */
- unsigned short **maskRect;
+ ushort **maskRect;
/** Store flag to enforce validation of undo rectangle. */
bool **valid;
bool touch;
@@ -243,7 +245,7 @@ typedef struct LoopSeamData {
typedef struct ProjPaintState {
View3D *v3d;
RegionView3D *rv3d;
- ARegion *ar;
+ ARegion *region;
Depsgraph *depsgraph;
Scene *scene;
/* PROJ_SRC_**** */
@@ -277,7 +279,7 @@ typedef struct ProjPaintState {
/** bucketRect aligned array linkList of faces overlapping each bucket. */
LinkNode **bucketFaces;
/** store if the bucks have been initialized. */
- unsigned char *bucketFlags;
+ uchar *bucketFlags;
/** store options per vert, now only store if the vert is pointing away from the view. */
char *vertFlags;
@@ -441,13 +443,13 @@ typedef union pixelPointer {
/** float buffer. */
float *f_pt;
/** 2 ways to access a char buffer. */
- unsigned int *uint_pt;
- unsigned char *ch_pt;
+ uint *uint_pt;
+ uchar *ch_pt;
} PixelPointer;
typedef union pixelStore {
- unsigned char ch[4];
- unsigned int uint;
+ uchar ch[4];
+ uint uint;
float f[4];
} PixelStore;
@@ -459,17 +461,17 @@ typedef struct ProjPixel {
short x_px, y_px;
/** if anyone wants to paint onto more than 65535 images they can bite me. */
- unsigned short image_index;
- unsigned char bb_cell_index;
+ ushort image_index;
+ uchar bb_cell_index;
/* for various reasons we may want to mask out painting onto this pixel */
- unsigned short mask;
+ ushort mask;
/* Only used when the airbrush is disabled.
* Store the max mask value to avoid painting over an area with a lower opacity
* with an advantage that we can avoid touching the pixel at all, if the
* new mask value is lower then mask_accum */
- unsigned short *mask_accum;
+ ushort *mask_accum;
/* horrible hack, store tile valid flag pointer here to re-validate tiles
* used for anchored and drag-dot strokes */
@@ -489,7 +491,7 @@ typedef struct ProjPixelClone {
typedef struct {
SpinLock *lock;
bool masked;
- unsigned short tile_width;
+ ushort tile_width;
ImBuf **tmpibuf;
ProjPaintImage *pjima;
} TileInfo;
@@ -715,11 +717,8 @@ static void uvco_to_wrapped_pxco(const float uv[2], int ibuf_x, int ibuf_y, floa
/* Set the top-most face color that the screen space coord 'pt' touches
* (or return 0 if none touch) */
-static bool project_paint_PickColor(const ProjPaintState *ps,
- const float pt[2],
- float *rgba_fp,
- unsigned char *rgba,
- const bool interp)
+static bool project_paint_PickColor(
+ const ProjPaintState *ps, const float pt[2], float *rgba_fp, uchar *rgba, const bool interp)
{
const MLoopTri *lt;
const float *lt_tri_uv[3];
@@ -732,7 +731,7 @@ static bool project_paint_PickColor(const ProjPaintState *ps,
tri_index = project_paint_PickFace(ps, pt, w);
if (tri_index == -1) {
- return 0;
+ return false;
}
lt = &ps->mlooptri_eval[tri_index];
@@ -743,9 +742,11 @@ static bool project_paint_PickColor(const ProjPaintState *ps,
ima = project_paint_face_paint_image(ps, tri_index);
/** we must have got the imbuf before getting here. */
int tile_number = project_paint_face_paint_tile(ima, lt_tri_uv[0]);
+ /* XXX get appropriate ImageUser instead */
ImageUser iuser;
BKE_imageuser_default(&iuser);
iuser.tile = tile_number;
+ iuser.framenr = ima->lastframe;
ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
if (ibuf == NULL) {
return false;
@@ -770,7 +771,7 @@ static bool project_paint_PickColor(const ProjPaintState *ps,
bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y);
}
else {
- unsigned char rgba_tmp[4];
+ uchar rgba_tmp[4];
bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y);
straight_uchar_to_premul_float(rgba_fp, rgba_tmp);
}
@@ -791,8 +792,7 @@ static bool project_paint_PickColor(const ProjPaintState *ps,
premul_float_to_straight_uchar(rgba, rgba_tmp_fp);
}
else {
- *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) +
- ((xi + yi * ibuf->x) * 4));
+ *((uint *)rgba) = *(uint *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4));
}
}
@@ -801,13 +801,13 @@ static bool project_paint_PickColor(const ProjPaintState *ps,
copy_v4_v4(rgba_fp, (ibuf->rect_float + ((xi + yi * ibuf->x) * 4)));
}
else {
- unsigned char *tmp_ch = ((unsigned char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
+ uchar *tmp_ch = ((uchar *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
straight_uchar_to_premul_float(rgba_fp, tmp_ch);
}
}
}
BKE_image_release_ibuf(ima, ibuf, NULL);
- return 1;
+ return true;
}
/**
@@ -1052,8 +1052,9 @@ static bool cmp_uv(const float vec2a[2], const float vec2b[2])
yb += 1.0f;
}
- return ((fabsf(xa - xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya - yb) < PROJ_GEOM_TOLERANCE)) ? 1 :
- 0;
+ return ((fabsf(xa - xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya - yb) < PROJ_GEOM_TOLERANCE)) ?
+ true :
+ false;
}
#endif
@@ -1084,7 +1085,7 @@ static bool pixel_bounds_uv(const float uv_quad[4][2],
/*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
/* face uses no UV area when quantized to pixels? */
- return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
+ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? false : true;
}
#endif
@@ -1095,7 +1096,7 @@ static bool pixel_bounds_array(
float min_uv[2], max_uv[2];
if (tot == 0) {
- return 0;
+ return false;
}
INIT_MINMAX2(min_uv, max_uv);
@@ -1114,7 +1115,7 @@ static bool pixel_bounds_array(
/*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
/* face uses no UV area when quantized to pixels? */
- return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
+ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? false : true;
}
#ifndef PROJ_DEBUG_NOSEAMBLEED
@@ -1145,8 +1146,8 @@ static bool check_seam(const ProjPaintState *ps,
const MLoopTri *orig_lt = &ps->mlooptri_eval[orig_face];
const float *orig_lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt)};
/* vert indices from face vert order indices */
- const unsigned int i1 = ps->mloop_eval[orig_lt->tri[orig_i1_fidx]].v;
- const unsigned int i2 = ps->mloop_eval[orig_lt->tri[orig_i2_fidx]].v;
+ const uint i1 = ps->mloop_eval[orig_lt->tri[orig_i1_fidx]].v;
+ const uint i2 = ps->mloop_eval[orig_lt->tri[orig_i2_fidx]].v;
LinkNode *node;
/* index in face */
int i1_fidx = -1, i2_fidx = -1;
@@ -1197,22 +1198,22 @@ static bool check_seam(const ProjPaintState *ps,
* they are on the same side so edge is boundary */
if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_CW) !=
(ps->faceWindingFlags[orig_face] & PROJ_FACE_WINDING_CW)) {
- return 1;
+ return true;
}
// printf("SEAM (NONE)\n");
- return 0;
+ return false;
}
else {
// printf("SEAM (UV GAP)\n");
- return 1;
+ return true;
}
}
}
}
// printf("SEAM (NO FACE)\n");
*other_face = -1;
- return 1;
+ return true;
}
static VertSeam *find_adjacent_seam(const ProjPaintState *ps,
@@ -1348,7 +1349,7 @@ static void uv_image_outset(const ProjPaintState *ps,
if (tri_ang > 0.0f) {
const float dist = ps->seam_bleed_px * tanf(tri_ang);
- seam_data->corner_dist_sq[i] = SQUARE(dist);
+ seam_data->corner_dist_sq[i] = square_f(dist);
}
else {
seam_data->corner_dist_sq[i] = 0.0f;
@@ -1636,7 +1637,7 @@ static float screen_px_line_point_factor_v2_persp(const ProjPaintState *ps,
static void project_face_pixel(const float *lt_tri_uv[3],
ImBuf *ibuf_other,
const float w[3],
- unsigned char rgba_ub[4],
+ uchar rgba_ub[4],
float rgba_f[4])
{
float uv_other[2], x, y;
@@ -1672,7 +1673,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
const float *lt_other_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt_other)};
/* BKE_image_acquire_ibuf - TODO - this may be slow */
- unsigned char rgba_ub[4];
+ uchar rgba_ub[4];
float rgba_f[4];
project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, rgba_f);
@@ -1837,7 +1838,7 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
pjIma->ima,
pjIma->ibuf,
tinf->tmpibuf,
- pjIma->iuser.tile,
+ &pjIma->iuser,
tx,
ty,
&pjIma->maskRect[tile_index],
@@ -1850,7 +1851,7 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
pjIma->ima,
pjIma->ibuf,
tinf->tmpibuf,
- pjIma->iuser.tile,
+ &pjIma->iuser,
tx,
ty,
NULL,
@@ -1932,8 +1933,8 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
zero_v4(projPixel->newColor.f);
}
else {
- projPixel->pixel.ch_pt = (unsigned char *)(ibuf->rect + (x_px + y_px * ibuf->x));
- projPixel->origColor.uint_pt = (unsigned int *)projima->undoRect[tile_index] + tile_offset;
+ projPixel->pixel.ch_pt = (uchar *)(ibuf->rect + (x_px + y_px * ibuf->x));
+ projPixel->origColor.uint_pt = (uint *)projima->undoRect[tile_index] + tile_offset;
projPixel->newColor.uint = 0;
}
@@ -1947,7 +1948,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
projPixel->x_px = x_px;
projPixel->y_px = y_px;
- projPixel->mask = (unsigned short)(mask * 65535);
+ projPixel->mask = (ushort)(mask * 65535);
if (ps->do_masking) {
projPixel->mask_accum = projima->maskRect[tile_index] + tile_offset;
}
@@ -1979,7 +1980,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
lt_other_tri_uv, ibuf_other, w, NULL, ((ProjPixelClone *)projPixel)->clonepx.f);
}
else { /* from char to float */
- unsigned char rgba_ub[4];
+ uchar rgba_ub[4];
float rgba[4];
project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, NULL);
if (ps->use_colormanagement) {
@@ -2068,11 +2069,11 @@ static bool line_clip_rect2f(const rctf *cliprect,
if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) {
/* is the line out of range on its Y axis? */
if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
- return 0;
+ return false;
}
/* line is out of range on its X axis */
if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) {
- return 0;
+ return false;
}
/* this is a single point (or close to)*/
@@ -2080,10 +2081,10 @@ static bool line_clip_rect2f(const rctf *cliprect,
if (BLI_rctf_isect_pt_v(rect, l1)) {
copy_v2_v2(l1_clip, l1);
copy_v2_v2(l2_clip, l2);
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
@@ -2091,7 +2092,7 @@ static bool line_clip_rect2f(const rctf *cliprect,
copy_v2_v2(l2_clip, l2);
CLAMP(l1_clip[0], rect->xmin, rect->xmax);
CLAMP(l2_clip[0], rect->xmin, rect->xmax);
- return 1;
+ return true;
}
else if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) {
/* is the line out of range on its X axis? */
@@ -2109,10 +2110,10 @@ static bool line_clip_rect2f(const rctf *cliprect,
if (BLI_rctf_isect_pt_v(rect, l1)) {
copy_v2_v2(l1_clip, l1);
copy_v2_v2(l2_clip, l2);
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
@@ -2120,7 +2121,7 @@ static bool line_clip_rect2f(const rctf *cliprect,
copy_v2_v2(l2_clip, l2);
CLAMP(l1_clip[1], rect->ymin, rect->ymax);
CLAMP(l2_clip[1], rect->ymin, rect->ymax);
- return 1;
+ return true;
}
else {
float isect;
@@ -2161,7 +2162,7 @@ static bool line_clip_rect2f(const rctf *cliprect,
}
if (ok1 && ok2) {
- return 1;
+ return true;
}
if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= cliprect->xmin) &&
@@ -2179,7 +2180,7 @@ static bool line_clip_rect2f(const rctf *cliprect,
}
if (ok1 && ok2) {
- return 1;
+ return true;
}
/* left/right */
@@ -2198,7 +2199,7 @@ static bool line_clip_rect2f(const rctf *cliprect,
}
if (ok1 && ok2) {
- return 1;
+ return true;
}
if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= cliprect->ymin) &&
@@ -2216,10 +2217,10 @@ static bool line_clip_rect2f(const rctf *cliprect,
}
if (ok1 && ok2) {
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
}
@@ -2279,13 +2280,13 @@ static bool project_bucket_isect_circle(const float cent[2],
*/
#if 0
if (BLI_rctf_isect_pt_v(bucket_bounds, cent)) {
- return 1;
+ return true;
}
#endif
if ((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) ||
(bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1])) {
- return 1;
+ return true;
}
/* out of bounds left */
@@ -2294,15 +2295,15 @@ static bool project_bucket_isect_circle(const float cent[2],
if (cent[1] < bucket_bounds->ymin) {
return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymin) <
radius_squared) ?
- 1 :
- 0;
+ true :
+ false;
}
/* top left test */
else if (cent[1] > bucket_bounds->ymax) {
return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymax) <
radius_squared) ?
- 1 :
- 0;
+ true :
+ false;
}
}
else if (cent[0] > bucket_bounds->xmax) {
@@ -2310,19 +2311,19 @@ static bool project_bucket_isect_circle(const float cent[2],
if (cent[1] < bucket_bounds->ymin) {
return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymin) <
radius_squared) ?
- 1 :
- 0;
+ true :
+ false;
}
/* top right test */
else if (cent[1] > bucket_bounds->ymax) {
return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymax) <
radius_squared) ?
- 1 :
- 0;
+ true :
+ false;
}
}
- return 0;
+ return false;
}
/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp()
@@ -2951,29 +2952,28 @@ static bool IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
{
int i;
if (line_point_side_v2(uv[tot - 1], uv[0], pt) < 0.0f) {
- return 0;
+ return false;
}
for (i = 1; i < tot; i++) {
if (line_point_side_v2(uv[i - 1], uv[i], pt) < 0.0f) {
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot)
{
- int i;
- bool side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f);
+ const bool side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f);
- for (i = 1; i < tot; i++) {
+ for (int i = 1; i < tot; i++) {
if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side) {
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
/* One of the most important function for projection painting,
@@ -3600,7 +3600,7 @@ static bool project_bucket_face_isect(ProjPaintState *ps,
do {
v = ps->screenCoords[lt_vtri[fidx]];
if (BLI_rctf_isect_pt_v(&bucket_bounds, v)) {
- return 1;
+ return true;
}
} while (fidx--);
@@ -3624,10 +3624,10 @@ static bool project_bucket_face_isect(ProjPaintState *ps,
(isect_seg_seg_v2(p2, p3, v1, v2) || isect_seg_seg_v2(p2, p3, v2, v3)) ||
(isect_seg_seg_v2(p3, p4, v1, v2) || isect_seg_seg_v2(p3, p4, v2, v3)) ||
(isect_seg_seg_v2(p4, p1, v1, v2) || isect_seg_seg_v2(p4, p1, v2, v3))) {
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Add faces to the bucket but don't initialize its pixels
@@ -3718,8 +3718,8 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps, const char symmet
if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
/* normal drawing */
- ps->winx = ps->ar->winx;
- ps->winy = ps->ar->winy;
+ ps->winx = ps->region->winx;
+ ps->winy = ps->region->winy;
copy_m4_m4(viewmat, ps->rv3d->viewmat);
copy_m4_m4(viewinv, ps->rv3d->viewinv);
@@ -3939,8 +3939,6 @@ static void proj_paint_state_seam_bleed_init(ProjPaintState *ps)
static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_threads)
{
- int a;
-
/* Thread stuff
*
* very small brushes run a lot slower multi-threaded since the advantage with
@@ -3964,7 +3962,7 @@ static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_th
ED_image_paint_tile_lock_init();
}
- for (a = 0; a < ps->thread_tot; a++) {
+ for (int a = 0; a < ps->thread_tot; a++) {
ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena");
}
}
@@ -4024,7 +4022,7 @@ static void project_paint_bleed_add_face_user(const ProjPaintState *ps,
* Ideally this would be checked later, not to add to the cost of computing non-degenerate
* triangles, but that would allow other triangles to still find adjacent seams on degenerate
* triangles, potentially causing incorrect results. */
- if (area_tri_v2(UNPACK3(lt_tri_uv)) > FLT_EPSILON) {
+ if (area_tri_v2(UNPACK3(lt_tri_uv)) > 0.0f) {
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
void *tri_index_p = POINTER_FROM_INT(tri_index);
@@ -4088,7 +4086,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
* the materials by using the mf->mat_nr directly and leaving the last
* material as NULL in case no materials exist on mesh, so indexing will not fail. */
for (int i = 0; i < totmat - 1; i++) {
- ps->mat_array[i] = give_current_material(ob, i + 1);
+ ps->mat_array[i] = BKE_object_material_get(ob, i + 1);
}
ps->mat_array[totmat - 1] = NULL;
@@ -4266,7 +4264,7 @@ static bool project_paint_winclip(const ProjPaintState *ps, const ProjPaintFaceC
typedef struct PrepareImageEntry {
struct PrepareImageEntry *next, *prev;
Image *ima;
- int tile;
+ ImageUser iuser;
} PrepareImageEntry;
static void project_paint_build_proj_ima(ProjPaintState *ps,
@@ -4281,9 +4279,7 @@ static void project_paint_build_proj_ima(ProjPaintState *ps,
projIma = ps->projImages = BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
for (entry = used_images->first, i = 0; entry; entry = entry->next, i++, projIma++) {
- memset(&projIma->iuser, 0, sizeof(ImageUser));
- BKE_imageuser_default(&projIma->iuser);
- projIma->iuser.tile = entry->tile;
+ projIma->iuser = entry->iuser;
int size;
projIma->ima = entry->ima;
projIma->touch = 0;
@@ -4435,19 +4431,21 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
if (tpage_last != tpage || tile_last != tile) {
image_index = 0;
for (PrepareImageEntry *e = used_images.first; e; e = e->next, image_index++) {
- if (e->ima == tpage && e->tile == tile) {
+ if (e->ima == tpage && e->iuser.tile == tile) {
break;
}
}
if (image_index == ps->image_tot) {
+ /* XXX get appropriate ImageUser instead */
ImageUser iuser;
BKE_imageuser_default(&iuser);
iuser.tile = tile;
+ iuser.framenr = tpage->lastframe;
if (BKE_image_has_ibuf(tpage, &iuser)) {
PrepareImageEntry *e = MEM_callocN(sizeof(PrepareImageEntry), "PrepareImageEntry");
e->ima = tpage;
- e->tile = tile;
+ e->iuser = iuser;
BLI_addtail(&used_images, e);
ps->image_tot++;
}
@@ -4842,15 +4840,15 @@ typedef struct ProjectHandle {
static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float mask)
{
- const unsigned char *clone_pt = ((ProjPixelClone *)projPixel)->clonepx.ch;
+ const uchar *clone_pt = ((ProjPixelClone *)projPixel)->clonepx.ch;
if (clone_pt[3]) {
- unsigned char clone_rgba[4];
+ uchar clone_rgba[4];
clone_rgba[0] = clone_pt[0];
clone_rgba[1] = clone_pt[1];
clone_rgba[2] = clone_pt[2];
- clone_rgba[3] = (unsigned char)(clone_pt[3] * mask);
+ clone_rgba[3] = (uchar)(clone_pt[3] * mask);
if (ps->do_masking) {
IMB_blend_color_byte(
@@ -4893,7 +4891,7 @@ static void do_projectpaint_smear(ProjPaintState *ps,
LinkNode **smearPixels,
const float co[2])
{
- unsigned char rgba_ub[4];
+ uchar rgba_ub[4];
if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1) == 0) {
return;
@@ -5014,7 +5012,7 @@ static void do_projectpaint_soften(ProjPaintState *ps,
}
if (LIKELY(accum_tot != 0)) {
- unsigned char *rgba_ub = projPixel->newColor.ch;
+ uchar *rgba_ub = projPixel->newColor.ch;
mul_v4_fl(rgba, 1.0f / (float)accum_tot);
@@ -5059,7 +5057,7 @@ static void do_projectpaint_draw(ProjPaintState *ps,
float v)
{
float rgb[3];
- unsigned char rgba_ub[4];
+ uchar rgba_ub[4];
if (ps->is_texbrush) {
mul_v3_v3v3(rgb, texrgb, ps->paint_color_linear);
@@ -5117,7 +5115,7 @@ static void do_projectpaint_draw_f(ProjPaintState *ps,
static void do_projectpaint_mask(ProjPaintState *ps, ProjPixel *projPixel, float mask)
{
- unsigned char rgba_ub[4];
+ uchar rgba_ub[4];
rgba_ub[0] = rgba_ub[1] = rgba_ub[2] = ps->stencil_value * 255.0f;
rgba_ub[3] = f_to_char(mask);
@@ -5170,9 +5168,7 @@ static void copy_original_alpha_channel(ProjPixel *pixel, bool is_floatbuf)
}
/* Run this for single and multi-threaded painting. */
-static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool),
- void *ph_v,
- int UNUSED(threadid))
+static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v)
{
/* First unpack args from the struct */
ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps;
@@ -5202,7 +5198,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool),
/* for smear only */
float pos_ofs[2] = {0};
float co[2];
- unsigned short mask_short;
+ ushort mask_short;
const float brush_alpha = BKE_brush_alpha_get(ps->scene, brush);
const float brush_radius = ps->brush_size;
/* avoid a square root with every dist comparison */
@@ -5295,7 +5291,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool),
}
}
BKE_colorband_evaluate(brush->gradient, f, color_f);
- color_f[3] *= ((float)projPixel->mask) * (1.0f / 65535.0f) * brush->alpha;
+ color_f[3] *= ((float)projPixel->mask) * (1.0f / 65535.0f) * brush_alpha;
if (is_floatbuf) {
/* convert to premultipied */
@@ -5323,7 +5319,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool),
else {
if (is_floatbuf) {
float newColor_f[4];
- newColor_f[3] = ((float)projPixel->mask) * (1.0f / 65535.0f) * brush->alpha;
+ newColor_f[3] = ((float)projPixel->mask) * (1.0f / 65535.0f) * brush_alpha;
copy_v3_v3(newColor_f, ps->paint_color_linear);
IMB_blend_color_float(
@@ -5331,7 +5327,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool),
}
else {
float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
- projPixel->newColor.ch[3] = mask * 255 * brush->alpha;
+ projPixel->newColor.ch[3] = mask * 255 * brush_alpha;
rgb_float_to_uchar(projPixel->newColor.ch, ps->paint_color);
IMB_blend_color_byte(projPixel->pixel.ch_pt,
@@ -5466,7 +5462,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool),
}
mask = min_ff(mask, 65535.0f);
- mask_short = (unsigned short)mask;
+ mask_short = (ushort)mask;
if (mask_short > *projPixel->mask_accum) {
*projPixel->mask_accum = mask_short;
@@ -5607,7 +5603,6 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
bool touch_any = false;
ProjectHandle handles[BLENDER_MAX_THREADS];
- TaskScheduler *scheduler = NULL;
TaskPool *task_pool = NULL;
int a, i;
@@ -5618,8 +5613,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
}
if (ps->thread_tot > 1) {
- scheduler = BLI_task_scheduler_get();
- task_pool = BLI_task_pool_create_suspended(scheduler, NULL);
+ task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH);
}
image_pool = BKE_image_pool_new();
@@ -5654,8 +5648,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
handles[a].pool = image_pool;
if (task_pool != NULL) {
- BLI_task_pool_push(
- task_pool, do_projectpaint_thread, &handles[a], false, TASK_PRIORITY_HIGH);
+ BLI_task_pool_push(task_pool, do_projectpaint_thread, &handles[a], false, NULL);
}
}
@@ -5664,7 +5657,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
BLI_task_pool_free(task_pool);
}
else {
- do_projectpaint_thread(NULL, &handles[0], 0);
+ do_projectpaint_thread(NULL, &handles[0]);
}
BKE_image_pool_free(image_pool);
@@ -5684,7 +5677,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
}
}
- /* calculate pivot for rotation around seletion if needed */
+ /* Calculate pivot for rotation around selection if needed. */
if (U.uiflag & USER_ORBIT_SELECTION) {
float w[3];
int tri_index;
@@ -5783,18 +5776,18 @@ void paint_proj_stroke(const bContext *C,
Scene *scene = ps_handle->scene;
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float *cursor = scene->cursor.location;
int mval_i[2] = {(int)pos[0], (int)pos[1]};
view3d_operator_needs_opengl(C);
- if (!ED_view3d_autodist(depsgraph, ar, v3d, mval_i, cursor, false, NULL)) {
+ if (!ED_view3d_autodist(depsgraph, region, v3d, mval_i, cursor, false, NULL)) {
return;
}
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return;
}
@@ -5848,7 +5841,7 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
/* these can be NULL */
ps->v3d = CTX_wm_view3d(C);
ps->rv3d = CTX_wm_region_view3d(C);
- ps->ar = CTX_wm_region(C);
+ ps->region = CTX_wm_region(C);
ps->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ps->scene = scene;
@@ -5887,7 +5880,7 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
#ifndef PROJ_DEBUG_NOSEAMBLEED
/* pixel num to bleed */
ps->seam_bleed_px = settings->imapaint.seam_bleed;
- ps->seam_bleed_px_sq = SQUARE(settings->imapaint.seam_bleed);
+ ps->seam_bleed_px_sq = square_s(settings->imapaint.seam_bleed);
#endif
if (ps->do_mask_normal) {
@@ -6041,14 +6034,13 @@ void paint_proj_stroke_done(void *ps_handle_p)
{
ProjStrokeHandle *ps_handle = ps_handle_p;
Scene *scene = ps_handle->scene;
- int i;
if (ps_handle->is_clone_cursor_pick) {
MEM_freeN(ps_handle);
return;
}
- for (i = 1; i < ps_handle->ps_views_tot; i++) {
+ for (int i = 1; i < ps_handle->ps_views_tot; i++) {
PROJ_PAINT_STATE_SHARED_CLEAR(ps_handle->ps_views[i]);
}
@@ -6056,7 +6048,7 @@ void paint_proj_stroke_done(void *ps_handle_p)
paint_brush_exit_tex(ps_handle->brush);
- for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ for (int i = 0; i < ps_handle->ps_views_tot; i++) {
ProjPaintState *ps;
ps = ps_handle->ps_views[i];
project_paint_end(ps);
@@ -6068,7 +6060,8 @@ void paint_proj_stroke_done(void *ps_handle_p)
/* use project paint to re-apply an image */
static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
{
- Image *image = BLI_findlink(&CTX_data_main(C)->images, RNA_enum_get(op->ptr, "image"));
+ Main *bmain = CTX_data_main(C);
+ Image *image = BLI_findlink(&bmain->images, RNA_enum_get(op->ptr, "image"));
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
ProjPaintState ps = {NULL};
@@ -6200,11 +6193,12 @@ void PAINT_OT_project_image(wmOperatorType *ot)
static bool texture_paint_image_from_view_poll(bContext *C)
{
- if (BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0) == NULL) {
+ bScreen *screen = CTX_wm_screen(C);
+ if (!(screen && BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0))) {
CTX_wm_operator_poll_msg_set(C, "No 3D viewport found to create image from");
return false;
}
- if (!GPU_is_initialized()) {
+ if (G.background || !GPU_is_initialized()) {
return false;
}
return true;
@@ -6225,18 +6219,18 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
int maxsize;
char err_out[256] = "unknown";
- ScrArea *sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0);
- if (!sa) {
+ ScrArea *area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0);
+ if (!area) {
BKE_report(op->reports, RPT_ERROR, "No 3D viewport found to create image from");
return OPERATOR_CANCELLED;
}
- ARegion *ar = BKE_area_find_region_active_win(sa);
- if (!ar) {
+ ARegion *region = BKE_area_find_region_active_win(area);
+ if (!region) {
BKE_report(op->reports, RPT_ERROR, "No 3D viewport found to create image from");
return OPERATOR_CANCELLED;
}
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
RNA_string_get(op->ptr, "filepath", filename);
@@ -6251,7 +6245,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
/* Create a copy of the overlays where they are all turned off, except the
* texture paint overlay opacity */
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
View3D v3d_copy = *v3d;
v3d_copy.gridflag = 0;
v3d_copy.flag2 = 0;
@@ -6268,7 +6262,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
scene,
v3d_copy.shading.type,
&v3d_copy,
- ar,
+ region,
w,
h,
IB_rect,
@@ -6376,12 +6370,11 @@ bool BKE_paint_proj_mesh_data_check(
}
else {
/* there may be material slots but they may be empty, check */
- int i;
hasmat = false;
hastex = false;
- for (i = 1; i < ob->totcol + 1; i++) {
- Material *ma = give_current_material(ob, i);
+ for (int i = 1; i < ob->totcol + 1; i++) {
+ Material *ma = BKE_object_material_get(ob, i);
if (ma) {
hasmat = true;
@@ -6573,7 +6566,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
return false;
}
- ma = give_current_material(ob, ob->actcol);
+ ma = BKE_object_material_get(ob, ob->actcol);
if (ma) {
Main *bmain = CTX_data_main(C);
@@ -6686,11 +6679,11 @@ static int get_texture_layer_type(wmOperator *op, const char *prop_name)
static Material *get_or_create_current_material(bContext *C, Object *ob)
{
- Material *ma = give_current_material(ob, ob->actcol);
+ Material *ma = BKE_object_material_get(ob, ob->actcol);
if (!ma) {
Main *bmain = CTX_data_main(C);
ma = BKE_material_add(bmain, "Material");
- assign_material(bmain, ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF);
+ BKE_object_material_assign(bmain, ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF);
}
return ma;
}
@@ -6716,7 +6709,7 @@ static void get_default_texture_layer_name_for_object(Object *ob,
char *dst,
int dst_length)
{
- Material *ma = give_current_material(ob, ob->actcol);
+ Material *ma = BKE_object_material_get(ob, ob->actcol);
const char *base_name = ma ? &ma->id.name[2] : &ob->id.name[2];
BLI_snprintf(dst, dst_length, "%s %s", base_name, layer_type_items[texture_type].name);
}
@@ -6736,7 +6729,7 @@ static int texture_paint_add_texture_paint_slot_invoke(bContext *C,
get_default_texture_layer_name_for_object(ob, type, (char *)&imagename, sizeof(imagename));
RNA_string_set(op->ptr, "name", imagename);
- return WM_operator_props_dialog_popup(C, op, 300, 100);
+ return WM_operator_props_dialog_popup(C, op, 300);
}
#define IMA_DEF_NAME N_("Untitled")
@@ -6754,7 +6747,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
/* api callbacks */
ot->invoke = texture_paint_add_texture_paint_slot_invoke;
ot->exec = texture_paint_add_texture_paint_slot_exec;
- ot->poll = ED_operator_object_active;
+ ot->poll = ED_operator_object_active_editable_mesh;
/* flags */
ot->flag = OPTYPE_UNDO;
@@ -6771,7 +6764,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
RNA_def_property_float_array_default(prop, default_color);
- RNA_def_boolean(ot->srna, "alpha", 1, "Alpha", "Create an image with an alpha channel");
+ RNA_def_boolean(ot->srna, "alpha", true, "Alpha", "Create an image with an alpha channel");
RNA_def_enum(ot->srna,
"generated_type",
rna_enum_image_generated_type_items,
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 6f2e4a0055d..018d7f72bb6 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -41,6 +41,7 @@ struct ViewContext;
struct bContext;
struct rcti;
struct wmEvent;
+struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
struct wmWindowManager;
@@ -173,7 +174,7 @@ struct VertProjHandle *ED_vpaint_proj_handle_create(struct Depsgraph *depsgraph,
void ED_vpaint_proj_handle_update(struct Depsgraph *depsgraph,
struct VertProjHandle *vp_handle,
/* runtime vars */
- struct ARegion *ar,
+ struct ARegion *region,
const float mval_fl[2]);
void ED_vpaint_proj_handle_free(struct VertProjHandle *vp_handle);
@@ -260,7 +261,7 @@ void SCULPT_OT_uv_sculpt_stroke(struct wmOperatorType *ot);
bool paint_convert_bb_to_rect(struct rcti *rect,
const float bb_min[3],
const float bb_max[3],
- const struct ARegion *ar,
+ const struct ARegion *region,
struct RegionView3D *rv3d,
struct Object *ob);
@@ -268,7 +269,7 @@ bool paint_convert_bb_to_rect(struct rcti *rect,
* screen_rect from screen into object-space (essentially converting a
* 2D screens-space bounding box into four 3D planes) */
void paint_calc_redraw_planes(float planes[4][4],
- const struct ARegion *ar,
+ const struct ARegion *region,
struct Object *ob,
const struct rcti *screen_rect);
@@ -287,7 +288,7 @@ void paint_get_tex_pixel_col(const struct MTex *mtex,
struct ColorSpace *colorspace);
void paint_sample_color(
- struct bContext *C, struct ARegion *ar, int x, int y, bool texpaint_proj, bool palette);
+ struct bContext *C, struct ARegion *region, int x, int y, bool texpaint_proj, bool palette);
void paint_stroke_operator_properties(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index d160fba4013..c32e496f4f5 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2012 by Nicholas Bishop
@@ -27,17 +27,17 @@
#include "DNA_object_types.h"
#include "BLI_bitmap_draw_2d.h"
-#include "BLI_math_matrix.h"
-#include "BLI_math_geom.h"
-#include "BLI_utildefines.h"
#include "BLI_lasso_2d.h"
+#include "BLI_math_geom.h"
+#include "BLI_math_matrix.h"
#include "BLI_task.h"
+#include "BLI_utildefines.h"
-#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
#include "BKE_multires.h"
#include "BKE_paint.h"
+#include "BKE_pbvh.h"
#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
@@ -55,7 +55,9 @@
#include "bmesh.h"
#include "paint_intern.h"
-#include "sculpt_intern.h" /* for undo push */
+
+/* For undo push. */
+#include "sculpt_intern.h"
#include <stdlib.h>
@@ -113,7 +115,7 @@ static void mask_flood_fill_task_cb(void *__restrict userdata,
PBVHVertexIter vi;
- sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_MASK);
+ SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_MASK);
BKE_pbvh_vertex_iter_begin(data->pbvh, node, vi, PBVH_ITER_UNIQUE)
{
@@ -135,7 +137,7 @@ static void mask_flood_fill_task_cb(void *__restrict userdata,
static int mask_flood_fill_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Object *ob = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
PaintMaskFloodMode mode;
@@ -155,7 +157,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
- sculpt_undo_push_begin("Mask flood fill");
+ SCULPT_undo_push_begin("Mask flood fill");
MaskTaskData data = {
.ob = ob,
@@ -166,9 +168,9 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
.value = value,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings);
if (multires) {
multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
@@ -176,13 +178,13 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask);
- sculpt_undo_push_end();
+ SCULPT_undo_push_end();
if (nodes) {
MEM_freeN(nodes);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -191,32 +193,32 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Mask Flood Fill";
ot->idname = "PAINT_OT_mask_flood_fill";
ot->description = "Fill the whole mask with a given value, or invert its values";
- /* api callbacks */
+ /* API callbacks. */
ot->exec = mask_flood_fill_exec;
- ot->poll = sculpt_mode_poll;
+ ot->poll = SCULPT_mode_poll;
ot->flag = OPTYPE_REGISTER;
- /* rna */
+ /* RNA. */
RNA_def_enum(ot->srna, "mode", mode_items, PAINT_MASK_FLOOD_VALUE, "Mode", NULL);
RNA_def_float(
ot->srna,
"value",
- 0,
- 0,
- 1,
+ 0.0f,
+ 0.0f,
+ 1.0f,
"Value",
"Mask level to use when mode is 'Value'; zero means no masking and one is fully masked",
- 0,
- 1);
+ 0.0f,
+ 1.0f);
}
-/* Box select, operator is VIEW3D_OT_select_box, defined in view3d_select.c */
+/* Box select, operator is VIEW3D_OT_select_box, defined in view3d_select.c. */
static bool is_effected(float planes[4][4], const float co[3])
{
@@ -270,7 +272,7 @@ static void mask_box_select_task_cb(void *__restrict userdata,
if (!any_masked) {
any_masked = true;
- sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_MASK);
+ SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_MASK);
if (data->multires) {
BKE_pbvh_node_mark_normals_update(node);
@@ -296,35 +298,33 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *
BoundBox bb;
float clip_planes[4][4];
float clip_planes_final[4][4];
- ARegion *ar = vc->ar;
+ ARegion *region = vc->region;
Object *ob = vc->obact;
PaintMaskFloodMode mode;
- float value;
bool multires;
PBVH *pbvh;
PBVHNode **nodes;
- int totnode, symmpass;
+ int totnode;
int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
mode = PAINT_MASK_FLOOD_VALUE;
- value = select ? 1.0 : 0.0;
+ float value = select ? 1.0f : 0.0f;
- /* transform the clip planes in object space */
- ED_view3d_clipping_calc(&bb, clip_planes, vc->ar, vc->obact, rect);
+ /* Transform the clip planes in object space. */
+ ED_view3d_clipping_calc(&bb, clip_planes, vc->region, vc->obact, rect);
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true);
pbvh = ob->sculpt->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
- sculpt_undo_push_begin("Mask box fill");
+ SCULPT_undo_push_begin("Mask box fill");
- for (symmpass = 0; symmpass <= symm; symmpass++) {
+ for (int symmpass = 0; symmpass <= symm; symmpass++) {
if (symmpass == 0 || (symm & symmpass && (symm != 5 || symmpass != 3) &&
(symm != 6 || (symmpass != 3 && symmpass != 5)))) {
- int j = 0;
- /* flip the planes symmetrically as needed */
- for (; j < 4; j++) {
+ /* Flip the planes symmetrically as needed. */
+ for (int j = 0; j < 4; j++) {
flip_plane(clip_planes_final[j], clip_planes[j], symmpass);
}
@@ -343,9 +343,9 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *
.clip_planes_final = clip_planes_final,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings);
if (nodes) {
MEM_freeN(nodes);
@@ -359,9 +359,9 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *
BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask);
- sculpt_undo_push_end();
+ SCULPT_undo_push_end();
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -373,7 +373,8 @@ typedef struct LassoMaskData {
float projviewobjmat[4][4];
BLI_bitmap *px;
int width;
- rcti rect; /* bounding box for scanfilling */
+ /* Bounding box for scanfilling. */
+ rcti rect;
int symmpass;
MaskTaskData task_data;
@@ -390,13 +391,13 @@ static bool is_effected_lasso(LassoMaskData *data, float co[3])
float co_final[3];
flip_v3_v3(co_final, co, data->symmpass);
- /* first project point to 2d space */
- ED_view3d_project_float_v2_m4(data->vc->ar, co_final, scr_co_f, data->projviewobjmat);
+ /* First project point to 2d space. */
+ ED_view3d_project_float_v2_m4(data->vc->region, co_final, scr_co_f, data->projviewobjmat);
scr_co_s[0] = scr_co_f[0];
scr_co_s[1] = scr_co_f[1];
- /* clip against screen, because lasso is limited to screen only */
+ /* Clip against screen, because lasso is limited to screen only. */
if ((scr_co_s[0] < data->rect.xmin) || (scr_co_s[1] < data->rect.ymin) ||
(scr_co_s[0] >= data->rect.xmax) || (scr_co_s[1] >= data->rect.ymax)) {
return false;
@@ -439,7 +440,7 @@ static void mask_gesture_lasso_task_cb(void *__restrict userdata,
if (!any_masked) {
any_masked = true;
- sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_MASK);
+ SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_MASK);
BKE_pbvh_node_mark_redraw(node);
if (data->multires) {
@@ -455,10 +456,10 @@ static void mask_gesture_lasso_task_cb(void *__restrict userdata,
static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
{
- int mcords_tot;
- const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+ int mcoords_len;
+ const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len);
- if (mcords) {
+ if (mcoords) {
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
float clip_planes[4][4], clip_planes_final[4][4];
BoundBox bb;
@@ -469,22 +470,22 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
PBVH *pbvh;
PBVHNode **nodes;
- int totnode, symmpass;
+ int totnode;
bool multires;
PaintMaskFloodMode mode = RNA_enum_get(op->ptr, "mode");
float value = RNA_float_get(op->ptr, "value");
/* Calculations of individual vertices are done in 2D screen space to diminish the amount of
* calculations done. Bounding box PBVH collision is not computed against enclosing rectangle
- * of lasso */
+ * of lasso. */
ED_view3d_viewcontext_init(C, &vc, depsgraph);
- /* lasso data calculations */
+ /* Lasso data calculations. */
data.vc = &vc;
ob = vc.obact;
ED_view3d_ob_project_mat_get(vc.rv3d, ob, data.projviewobjmat);
- BLI_lasso_boundbox(&data.rect, mcords, mcords_tot);
+ BLI_lasso_boundbox(&data.rect, mcoords, mcoords_len);
data.width = data.rect.xmax - data.rect.xmin;
data.px = BLI_BITMAP_NEW(data.width * (data.rect.ymax - data.rect.ymin), __func__);
@@ -492,33 +493,32 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
data.rect.ymin,
data.rect.xmax,
data.rect.ymax,
- mcords,
- mcords_tot,
+ mcoords,
+ mcoords_len,
mask_lasso_px_cb,
&data);
- ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, &data.rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc.region, vc.obact, &data.rect);
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true);
pbvh = ob->sculpt->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
- sculpt_undo_push_begin("Mask lasso fill");
+ SCULPT_undo_push_begin("Mask lasso fill");
- for (symmpass = 0; symmpass <= symm; symmpass++) {
+ for (int symmpass = 0; symmpass <= symm; symmpass++) {
if ((symmpass == 0) || (symm & symmpass && (symm != 5 || symmpass != 3) &&
(symm != 6 || (symmpass != 3 && symmpass != 5)))) {
- int j = 0;
- /* flip the planes symmetrically as needed */
- for (; j < 4; j++) {
+ /* Flip the planes symmetrically as needed. */
+ for (int j = 0; j < 4; j++) {
flip_plane(clip_planes_final[j], clip_planes[j], symmpass);
}
data.symmpass = symmpass;
- /* gather nodes inside lasso's enclosing rectangle
- * (should greatly help with bigger meshes) */
+ /* Gather nodes inside lasso's enclosing rectangle
+ * (should greatly help with bigger meshes). */
PBVHFrustumPlanes frustum = {.planes = clip_planes_final, .num_planes = 4};
BKE_pbvh_search_gather(
pbvh, BKE_pbvh_node_frustum_contain_AABB, &frustum, &nodes, &totnode);
@@ -532,9 +532,9 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
data.task_data.mode = mode;
data.task_data.value = value;
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings);
if (nodes) {
MEM_freeN(nodes);
@@ -548,10 +548,10 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask);
- sculpt_undo_push_end();
+ SCULPT_undo_push_end();
- ED_region_tag_redraw(vc.ar);
- MEM_freeN((void *)mcords);
+ ED_region_tag_redraw(vc.region);
+ MEM_freeN((void *)mcoords);
MEM_freeN(data.px);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -571,22 +571,22 @@ void PAINT_OT_mask_lasso_gesture(wmOperatorType *ot)
ot->modal = WM_gesture_lasso_modal;
ot->exec = paint_mask_gesture_lasso_exec;
- ot->poll = sculpt_mode_poll;
+ ot->poll = SCULPT_mode_poll;
ot->flag = OPTYPE_REGISTER;
- /* properties */
+ /* Properties. */
WM_operator_properties_gesture_lasso(ot);
RNA_def_enum(ot->srna, "mode", mode_items, PAINT_MASK_FLOOD_VALUE, "Mode", NULL);
RNA_def_float(
ot->srna,
"value",
- 1.0,
- 0,
- 1.0,
+ 1.0f,
+ 0.0f,
+ 1.0f,
"Value",
"Mask level to use when mode is 'Value'; zero means no masking and one is fully masked",
- 0,
- 1);
+ 0.0f,
+ 1.0f);
}
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 7863e18394c..d607b6a9d6f 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -20,30 +20,35 @@
#include "MEM_guardedalloc.h"
-#include <stdlib.h>
#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
+#include <stdlib.h>
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_brush_types.h"
#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_image.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_paint.h"
+#include "BKE_report.h"
+#include "ED_image.h"
#include "ED_paint.h"
#include "ED_screen.h"
-#include "ED_image.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -294,6 +299,293 @@ static void PALETTE_OT_color_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/* --- Extract Palette from Image. */
+static bool palette_extract_img_poll(bContext *C)
+{
+ SpaceLink *sl = CTX_wm_space_data(C);
+ if ((sl != NULL) && (sl->spacetype == SPACE_IMAGE)) {
+ return true;
+ }
+
+ return false;
+}
+
+static int palette_extract_img_exec(bContext *C, wmOperator *op)
+{
+ const int threshold = RNA_int_get(op->ptr, "threshold");
+
+ Main *bmain = CTX_data_main(C);
+ bool done = false;
+
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *image = sima->image;
+ ImageUser iuser = sima->iuser;
+ void *lock;
+ ImBuf *ibuf;
+ GHash *color_table = BLI_ghash_int_new(__func__);
+
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+ if (ibuf->rect) {
+ /* Extract all colors. */
+ for (int row = 0; row < ibuf->y; row++) {
+ for (int col = 0; col < ibuf->x; col++) {
+ float color[4];
+ IMB_sampleImageAtLocation(ibuf, (float)col, (float)row, false, color);
+ const float range = pow(10.0f, threshold);
+ color[0] = truncf(color[0] * range) / range;
+ color[1] = truncf(color[1] * range) / range;
+ color[2] = truncf(color[2] * range) / range;
+
+ uint key = rgb_to_cpack(color[0], color[1], color[2]);
+ if (!BLI_ghash_haskey(color_table, POINTER_FROM_INT(key))) {
+ BLI_ghash_insert(color_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
+ }
+ }
+ }
+
+ done = BKE_palette_from_hash(bmain, color_table, image->id.name + 2, false);
+ }
+
+ /* Free memory. */
+ BLI_ghash_free(color_table, NULL, NULL);
+ BKE_image_release_ibuf(image, ibuf, lock);
+
+ if (done) {
+ BKE_reportf(op->reports, RPT_INFO, "Palette created");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_extract_from_image(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Extract Palette from Image";
+ ot->idname = "PALETTE_OT_extract_from_image";
+ ot->description = "Extract all colors used in Image and create a Palette";
+
+ /* api callbacks */
+ ot->exec = palette_extract_img_exec;
+ ot->poll = palette_extract_img_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "threshold", 1, 1, 4, "Threshold", "", 1, 4);
+}
+
+/* Sort Palette color by Hue and Saturation. */
+static int palette_sort_exec(bContext *C, wmOperator *op)
+{
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Palette *palette = paint->palette;
+
+ if (palette == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ tPaletteColorHSV *color_array = NULL;
+ tPaletteColorHSV *col_elm = NULL;
+
+ const int totcol = BLI_listbase_count(&palette->colors);
+
+ if (totcol > 0) {
+ color_array = MEM_calloc_arrayN(totcol, sizeof(tPaletteColorHSV), __func__);
+ /* Put all colors in an array. */
+ int t = 0;
+ LISTBASE_FOREACH (PaletteColor *, color, &palette->colors) {
+ float h, s, v;
+ rgb_to_hsv(color->rgb[0], color->rgb[1], color->rgb[2], &h, &s, &v);
+ col_elm = &color_array[t];
+ copy_v3_v3(col_elm->rgb, color->rgb);
+ col_elm->value = color->value;
+ col_elm->h = h;
+ col_elm->s = s;
+ col_elm->v = v;
+ t++;
+ }
+ /* Sort */
+ if (type == 1) {
+ BKE_palette_sort_hsv(color_array, totcol);
+ }
+ else if (type == 2) {
+ BKE_palette_sort_svh(color_array, totcol);
+ }
+ else if (type == 3) {
+ BKE_palette_sort_vhs(color_array, totcol);
+ }
+ else {
+ BKE_palette_sort_luminance(color_array, totcol);
+ }
+
+ /* Clear old color swatches. */
+ PaletteColor *color_next = NULL;
+ for (PaletteColor *color = palette->colors.first; color; color = color_next) {
+ color_next = color->next;
+ BKE_palette_color_remove(palette, color);
+ }
+
+ /* Recreate swatches sorted. */
+ for (int i = 0; i < totcol; i++) {
+ col_elm = &color_array[i];
+ PaletteColor *palcol = BKE_palette_color_add(palette);
+ if (palcol) {
+ copy_v3_v3(palcol->rgb, col_elm->rgb);
+ }
+ }
+ }
+
+ /* Free memory. */
+ if (totcol > 0) {
+ MEM_SAFE_FREE(color_array);
+ }
+
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_sort(wmOperatorType *ot)
+{
+ static const EnumPropertyItem sort_type[] = {
+ {1, "HSV", 0, "Hue, Saturation, Value", ""},
+ {2, "SVH", 0, "Saturation, Value, Hue", ""},
+ {3, "VHS", 0, "Value, Hue, Saturation", ""},
+ {4, "LUMINANCE", 0, "Luminance", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Sort Palette";
+ ot->idname = "PALETTE_OT_sort";
+ ot->description = "Sort Palette Colors";
+
+ /* api callbacks */
+ ot->exec = palette_sort_exec;
+ ot->poll = palette_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", sort_type, 1, "Type", "");
+}
+
+/* Move colors in palette. */
+static int palette_color_move_exec(bContext *C, wmOperator *op)
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Palette *palette = paint->palette;
+ PaletteColor *palcolor = BLI_findlink(&palette->colors, palette->active_color);
+
+ if (palcolor == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const int direction = RNA_enum_get(op->ptr, "type");
+
+ BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
+ if (BLI_listbase_link_move(&palette->colors, palcolor, direction)) {
+ palette->active_color += direction;
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_color_move(wmOperatorType *ot)
+{
+ static const EnumPropertyItem slot_move[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Palette Color";
+ ot->idname = "PALETTE_OT_color_move";
+ ot->description = "Move the active Color up/down in the list";
+
+ /* api callbacks */
+ ot->exec = palette_color_move_exec;
+ ot->poll = palette_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
+}
+
+/* Join Palette swatches. */
+static int palette_join_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Palette *palette = paint->palette;
+ Palette *palette_join = NULL;
+ bool done = false;
+
+ char name[MAX_ID_NAME - 2];
+ RNA_string_get(op->ptr, "palette", name);
+
+ if ((palette == NULL) || (name[0] == '\0')) {
+ return OPERATOR_CANCELLED;
+ }
+
+ palette_join = (Palette *)BKE_libblock_find_name(bmain, ID_PAL, name);
+ if (palette_join == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const int totcol = BLI_listbase_count(&palette_join->colors);
+
+ if (totcol > 0) {
+ LISTBASE_FOREACH (PaletteColor *, color, &palette_join->colors) {
+ PaletteColor *palcol = BKE_palette_color_add(palette);
+ if (palcol) {
+ copy_v3_v3(palcol->rgb, color->rgb);
+ palcol->value = color->value;
+ done = true;
+ }
+ }
+ }
+
+ if (done) {
+ /* Clear old color swatches. */
+ PaletteColor *color_next = NULL;
+ for (PaletteColor *color = palette_join->colors.first; color; color = color_next) {
+ color_next = color->next;
+ BKE_palette_color_remove(palette_join, color);
+ }
+
+ /* Notifier. */
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_join(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Join Palette Swatches";
+ ot->idname = "PALETTE_OT_join";
+ ot->description = "Join Palette Swatches";
+
+ /* api callbacks */
+ ot->exec = palette_join_exec;
+ ot->poll = palette_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string(ot->srna, "palette", NULL, MAX_ID_NAME - 2, "Palette", "Name of the Palette");
+}
+
static int brush_reset_exec(bContext *C, wmOperator *UNUSED(op))
{
Paint *paint = BKE_paint_get_active_from_context(C);
@@ -424,7 +716,8 @@ static bool brush_generic_tool_set(bContext *C,
brush = brush_tool_cycle(bmain, paint, brush_orig, tool);
}
- if (!brush && brush_tool(brush_orig, paint->runtime.tool_offset) != tool && create_missing) {
+ if (((brush == NULL) && create_missing) &&
+ ((brush_orig == NULL) || brush_tool(brush_orig, paint->runtime.tool_offset) != tool)) {
brush = BKE_brush_add(bmain, tool_name, paint->runtime.ob_mode);
id_us_min(&brush->id); /* fake user only */
brush_tool_set(brush, paint->runtime.tool_offset, tool);
@@ -456,6 +749,9 @@ static const ePaintMode brush_select_paint_modes[] = {
PAINT_MODE_WEIGHT,
PAINT_MODE_TEXTURE_3D,
PAINT_MODE_GPENCIL,
+ PAINT_MODE_VERTEX_GPENCIL,
+ PAINT_MODE_SCULPT_GPENCIL,
+ PAINT_MODE_WEIGHT_GPENCIL,
};
static int brush_select_exec(bContext *C, wmOperator *op)
@@ -483,6 +779,9 @@ static int brush_select_exec(bContext *C, wmOperator *op)
}
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
+ if (paint == NULL) {
+ return OPERATOR_CANCELLED;
+ }
const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
RNA_enum_name_from_value(items, tool, &tool_name);
@@ -602,7 +901,7 @@ static int stencil_control_invoke(bContext *C, wmOperator *op, const wmEvent *ev
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *br = BKE_paint_brush(paint);
float mvalf[2] = {event->mval[0], event->mval[1]};
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
StencilControlData *scd;
int mask = RNA_enum_get(op->ptr, "texmode");
@@ -627,8 +926,8 @@ static int stencil_control_invoke(bContext *C, wmOperator *op, const wmEvent *ev
scd->mode = RNA_enum_get(op->ptr, "mode");
scd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
- scd->area_size[0] = ar->winx;
- scd->area_size[1] = ar->winy;
+ scd->area_size[0] = region->winx;
+ scd->area_size[1] = region->winy;
op->customdata = scd;
WM_event_add_modal_handler(C, op);
@@ -682,8 +981,7 @@ static void stencil_control_calculate(StencilControlData *scd, const int mval[2]
if (scd->constrain_mode != STENCIL_CONSTRAINT_X) {
mdiff[1] = factor * scd->init_sdim[1];
}
- CLAMP(mdiff[0], 5.0f, 10000.0f);
- CLAMP(mdiff[1], 5.0f, 10000.0f);
+ clamp_v2(mdiff, 5.0f, 10000.0f);
copy_v2_v2(scd->dim_target, mdiff);
break;
}
@@ -719,14 +1017,14 @@ static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *eve
case MOUSEMOVE:
stencil_control_calculate(scd, event->mval);
break;
- case ESCKEY:
+ case EVT_ESCKEY:
if (event->val == KM_PRESS) {
stencil_control_cancel(C, op);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_CANCELLED;
}
break;
- case XKEY:
+ case EVT_XKEY:
if (event->val == KM_PRESS) {
if (scd->constrain_mode == STENCIL_CONSTRAINT_X) {
@@ -739,7 +1037,7 @@ static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *eve
stencil_control_calculate(scd, event->mval);
}
break;
- case YKEY:
+ case EVT_YKEY:
if (event->val == KM_PRESS) {
if (scd->constrain_mode == STENCIL_CONSTRAINT_Y) {
scd->constrain_mode = 0;
@@ -966,6 +1264,11 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PALETTE_OT_color_add);
WM_operatortype_append(PALETTE_OT_color_delete);
+ WM_operatortype_append(PALETTE_OT_extract_from_image);
+ WM_operatortype_append(PALETTE_OT_sort);
+ WM_operatortype_append(PALETTE_OT_color_move);
+ WM_operatortype_append(PALETTE_OT_join);
+
/* paint curve */
WM_operatortype_append(PAINTCURVE_OT_new);
WM_operatortype_append(PAINTCURVE_OT_add_point);
@@ -1051,7 +1354,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
/* Sculpt mode */
keymap = WM_keymap_ensure(keyconf, "Sculpt", 0, 0);
- keymap->poll = sculpt_mode_poll;
+ keymap->poll = SCULPT_mode_poll;
/* Vertex Paint mode */
keymap = WM_keymap_ensure(keyconf, "Vertex Paint", 0, 0);
@@ -1062,7 +1365,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
keymap->poll = weight_paint_mode_poll;
/*Weight paint's Vertex Selection Mode */
- keymap = WM_keymap_ensure(keyconf, "Weight Paint Vertex Selection", 0, 0);
+ keymap = WM_keymap_ensure(keyconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0);
keymap->poll = vert_paint_poll;
/* Image/Texture Paint mode */
@@ -1070,7 +1373,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
keymap->poll = image_texture_paint_poll;
/* face-mask mode */
- keymap = WM_keymap_ensure(keyconf, "Face Mask", 0, 0);
+ keymap = WM_keymap_ensure(keyconf, "Paint Face Mask (Weight, Vertex, Texture)", 0, 0);
keymap->poll = facemask_paint_poll;
/* paint stroke */
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 372ea954630..458c24e5194 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2009 by Nicholas Bishop
@@ -23,26 +23,26 @@
#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_rand.h"
-#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "PIL_time.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "RNA_access.h"
-#include "BKE_context.h"
-#include "BKE_paint.h"
#include "BKE_brush.h"
-#include "BKE_curve.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
#include "BKE_image.h"
+#include "BKE_paint.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -118,6 +118,8 @@ typedef struct PaintStroke {
float last_pressure;
int stroke_mode;
+ float last_tablet_event_pressure;
+
float zoom_2d;
int pen_flip;
@@ -143,7 +145,7 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata
GPU_line_smooth(true);
GPU_blend(true);
- ARegion *ar = stroke->vc.ar;
+ ARegion *region = stroke->vc.region;
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -152,8 +154,8 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata
immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, x, y);
immVertex2f(pos,
- stroke->last_mouse_position[0] + ar->winrct.xmin,
- stroke->last_mouse_position[1] + ar->winrct.ymin);
+ stroke->last_mouse_position[0] + region->winrct.xmin,
+ stroke->last_mouse_position[1] + region->winrct.ymin);
immEnd();
@@ -189,21 +191,21 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
immBegin(GPU_PRIM_LINES, 2);
- ARegion *ar = stroke->vc.ar;
+ ARegion *region = stroke->vc.region;
if (stroke->constrain_line) {
immVertex2f(shdr_pos,
- stroke->last_mouse_position[0] + ar->winrct.xmin,
- stroke->last_mouse_position[1] + ar->winrct.ymin);
+ stroke->last_mouse_position[0] + region->winrct.xmin,
+ stroke->last_mouse_position[1] + region->winrct.ymin);
immVertex2f(shdr_pos,
- stroke->constrained_pos[0] + ar->winrct.xmin,
- stroke->constrained_pos[1] + ar->winrct.ymin);
+ stroke->constrained_pos[0] + region->winrct.xmin,
+ stroke->constrained_pos[1] + region->winrct.ymin);
}
else {
immVertex2f(shdr_pos,
- stroke->last_mouse_position[0] + ar->winrct.xmin,
- stroke->last_mouse_position[1] + ar->winrct.ymin);
+ stroke->last_mouse_position[0] + region->winrct.xmin,
+ stroke->last_mouse_position[1] + region->winrct.ymin);
immVertex2f(shdr_pos, x, y);
}
@@ -228,6 +230,10 @@ static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
SCULPT_TOOL_THUMB)) {
return false;
}
+ else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
+ brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
+ return false;
+ }
else {
return true;
}
@@ -259,6 +265,7 @@ static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode m
SCULPT_TOOL_THUMB,
SCULPT_TOOL_SNAKE_HOOK,
SCULPT_TOOL_ELASTIC_DEFORM,
+ SCULPT_TOOL_CLOTH,
SCULPT_TOOL_POSE)) {
return false;
}
@@ -553,7 +560,7 @@ static void paint_brush_stroke_add_step(bContext *C,
stroke->last_pressure = pressure;
if (paint_stroke_use_scene_spacing(brush, mode)) {
- sculpt_stroke_get_location(C, stroke->last_world_space_position, stroke->last_mouse_position);
+ SCULPT_stroke_get_location(C, stroke->last_world_space_position, stroke->last_mouse_position);
mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
}
@@ -632,7 +639,7 @@ static bool paint_smooth_stroke(PaintStroke *stroke,
/* If the mouse is moving within the radius of the last move,
* don't update the mouse position. This allows sharp turns. */
- if (len_squared_v2v2(stroke->last_mouse_position, sample->mouse) < SQUARE(radius)) {
+ if (len_squared_v2v2(stroke->last_mouse_position, sample->mouse) < square_f(radius)) {
return false;
}
@@ -789,7 +796,7 @@ static int paint_space_stroke(bContext *C,
float final_pressure)
{
const Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
PaintStroke *stroke = op->customdata;
UnifiedPaintSettings *ups = stroke->ups;
Paint *paint = BKE_paint_get_active_from_context(C);
@@ -810,7 +817,7 @@ static int paint_space_stroke(bContext *C,
if (use_scene_spacing) {
float world_space_position[3];
- bool hit = sculpt_stroke_get_location(C, world_space_position, final_mouse);
+ bool hit = SCULPT_stroke_get_location(C, world_space_position, final_mouse);
mul_m4_v3(stroke->vc.obact->obmat, world_space_position);
if (hit && stroke->stroke_over_mesh) {
sub_v3_v3v3(d_world_space_position, world_space_position, stroke->last_world_space_position);
@@ -840,7 +847,7 @@ static int paint_space_stroke(bContext *C,
add_v3_v3v3(final_world_space_position,
stroke->last_world_space_position,
final_world_space_position);
- ED_view3d_project(ar, final_world_space_position, mouse);
+ ED_view3d_project(region, final_world_space_position, mouse);
}
else {
mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
@@ -999,6 +1006,10 @@ bool paint_space_stroke_enabled(Brush *br, ePaintMode mode)
static bool sculpt_is_grab_tool(Brush *br)
{
+
+ if (br->sculpt_tool == SCULPT_TOOL_CLOTH && br->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
+ return true;
+ }
return ELEM(br->sculpt_tool,
SCULPT_TOOL_GRAB,
SCULPT_TOOL_ELASTIC_DEFORM,
@@ -1092,11 +1103,11 @@ struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf)
static const char *name = "Paint Stroke Modal";
- struct wmKeyMap *keymap = WM_modalkeymap_get(keyconf, name);
+ struct wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name);
/* this function is called for each spacetype, only needs to add map once */
if (!keymap) {
- keymap = WM_modalkeymap_add(keyconf, name, modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, name, modal_items);
}
return keymap;
@@ -1329,7 +1340,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
Paint *p = BKE_paint_get_active_from_context(C);
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
PaintStroke *stroke = op->customdata;
- Brush *br = stroke->brush;
+ Brush *br = stroke->brush = BKE_paint_brush(p);
PaintSample sample_average;
float mouse[2];
bool first_dab = false;
@@ -1346,6 +1357,15 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
1.0f :
WM_event_tablet_data(event, &stroke->pen_flip, NULL));
+ /* When processing a timer event the pressure from the event is 0, so use the last valid
+ * pressure. */
+ if (event->type == TIMER) {
+ pressure = stroke->last_tablet_event_pressure;
+ }
+ else {
+ stroke->last_tablet_event_pressure = pressure;
+ }
+
paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
paint_stroke_sample_average(stroke, &sample_average);
@@ -1383,7 +1403,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
stroke->last_pressure = sample_average.pressure;
copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
if (paint_stroke_use_scene_spacing(br, mode)) {
- stroke->stroke_over_mesh = sculpt_stroke_get_location(
+ stroke->stroke_over_mesh = SCULPT_stroke_get_location(
C, stroke->last_world_space_position, sample_average.mouse);
mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
}
@@ -1429,7 +1449,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
}
- else if (ELEM(event->type, RETKEY, SPACEKEY)) {
+ else if (ELEM(event->type, EVT_RETKEY, EVT_SPACEKEY)) {
paint_stroke_line_end(C, op, stroke, sample_average.mouse);
stroke_done(C, op);
return OPERATOR_FINISHED;
@@ -1491,11 +1511,11 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
* coming, so postpone potentially slow redraw updates until all are done */
if (event->type != INBETWEEN_MOUSEMOVE) {
wmWindow *window = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* At the very least, invalidate the cursor */
- if (ar && (p->flags & PAINT_SHOW_BRUSH)) {
- WM_paint_cursor_tag_redraw(window, ar);
+ if (region && (p->flags & PAINT_SHOW_BRUSH)) {
+ WM_paint_cursor_tag_redraw(window, region);
}
if (redraw && stroke->redraw) {
@@ -1577,13 +1597,14 @@ bool paint_poll(bContext *C)
{
Paint *p = BKE_paint_get_active_from_context(C);
Object *ob = CTX_data_active_object(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
- if (p && ob && BKE_paint_brush(p) && (sa && ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
- (ar && ar->regiontype == RGN_TYPE_WINDOW)) {
+ if (p && ob && BKE_paint_brush(p) &&
+ (area && ELEM(area->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
+ (region && region->regiontype == RGN_TYPE_WINDOW)) {
/* Check the current tool is a brush. */
- bToolRef *tref = sa->runtime.tool;
+ bToolRef *tref = area->runtime.tool;
if (tref && tref->runtime && tref->runtime->data_block[0]) {
return true;
}
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index db22729e8b0..c84a3b9cbfc 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -24,19 +24,19 @@
#include <math.h>
#include <stdlib.h>
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "DNA_material_types.h"
-#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
+#include "DNA_scene_types.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_color.h"
-#include "BLI_utildefines.h"
-#include "BLI_listbase.h"
#include "BLI_rect.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -60,13 +60,13 @@
#include "GPU_state.h"
#include "IMB_colormanagement.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "RE_render_ext.h"
-#include "ED_view3d.h"
#include "ED_screen.h"
+#include "ED_view3d.h"
#include "BLI_sys_types.h"
#include "ED_mesh.h" /* for face mask functions */
@@ -84,7 +84,7 @@
bool paint_convert_bb_to_rect(rcti *rect,
const float bb_min[3],
const float bb_max[3],
- const ARegion *ar,
+ const ARegion *region,
RegionView3D *rv3d,
Object *ob)
{
@@ -109,7 +109,7 @@ bool paint_convert_bb_to_rect(rcti *rect,
vec[1] = j ? bb_min[1] : bb_max[1];
vec[2] = k ? bb_min[2] : bb_max[2];
/* convert corner to screen space */
- ED_view3d_project_float_v2_m4(ar, vec, proj, projection_mat);
+ ED_view3d_project_float_v2_m4(region, vec, proj, projection_mat);
/* expand 2D rectangle */
/* we could project directly to int? */
@@ -129,7 +129,7 @@ bool paint_convert_bb_to_rect(rcti *rect,
* screen_rect from screen into object-space (essentially converting a
* 2D screens-space bounding box into four 3D planes) */
void paint_calc_redraw_planes(float planes[4][4],
- const ARegion *ar,
+ const ARegion *region,
Object *ob,
const rcti *screen_rect)
{
@@ -143,7 +143,7 @@ void paint_calc_redraw_planes(float planes[4][4],
rect.ymin -= 2;
rect.ymax += 2;
- ED_view3d_clipping_calc(&bb, planes, ar, ob, &rect);
+ ED_view3d_clipping_calc(&bb, planes, region, ob, &rect);
}
float paint_calc_object_space_radius(ViewContext *vc, const float center[3], float pixel_radius)
@@ -156,7 +156,7 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo
mul_v3_m4v3(loc, ob->obmat, center);
zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL);
- ED_view3d_win_to_delta(vc->ar, mval_f, delta, zfac);
+ ED_view3d_win_to_delta(vc->region, mval_f, delta, zfac);
scale = fabsf(mat4_to_scale(ob->obmat));
scale = (scale == 0.0f) ? 1.0f : scale;
@@ -166,10 +166,11 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo
float paint_get_tex_pixel(const MTex *mtex, float u, float v, struct ImagePool *pool, int thread)
{
- float intensity, rgba[4];
+ float intensity;
+ float rgba_dummy[4];
float co[3] = {u, v, 0.0f};
- externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false);
+ RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba_dummy);
return intensity;
}
@@ -184,11 +185,10 @@ void paint_get_tex_pixel_col(const MTex *mtex,
struct ColorSpace *colorspace)
{
float co[3] = {u, v, 0.0f};
- int hasrgb;
float intensity;
- hasrgb = externtex(
- mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false);
+ const bool hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba);
+
if (!hasrgb) {
rgba[0] = intensity;
rgba[1] = intensity;
@@ -202,10 +202,7 @@ void paint_get_tex_pixel_col(const MTex *mtex,
linearrgb_to_srgb_v3_v3(rgba, rgba);
- CLAMP(rgba[0], 0.0f, 1.0f);
- CLAMP(rgba[1], 0.0f, 1.0f);
- CLAMP(rgba[2], 0.0f, 1.0f);
- CLAMP(rgba[3], 0.0f, 1.0f);
+ clamp_v4(rgba, 0.0f, 1.0f);
}
void paint_stroke_operator_properties(wmOperatorType *ot)
@@ -297,12 +294,8 @@ static void imapaint_tri_weights(float matrix[4][4],
}
/* compute uv coordinates of mouse in face */
-static void imapaint_pick_uv(Mesh *me_eval,
- Scene *scene,
- Object *ob_eval,
- unsigned int faceindex,
- const int xy[2],
- float uv[2])
+static void imapaint_pick_uv(
+ Mesh *me_eval, Scene *scene, Object *ob_eval, uint faceindex, const int xy[2], float uv[2])
{
int i, findex;
float p[2], w[3], absw, minabsw;
@@ -348,7 +341,7 @@ static void imapaint_pick_uv(Mesh *me_eval,
const Material *ma;
const TexPaintSlot *slot;
- ma = give_current_material(ob_eval, mp->mat_nr + 1);
+ ma = BKE_object_material_get(ob_eval, mp->mat_nr + 1);
slot = &ma->texpaintslot[ma->paint_active_slot];
if (!(slot && slot->uvname &&
@@ -379,10 +372,7 @@ static void imapaint_pick_uv(Mesh *me_eval,
}
/* returns 0 if not found, otherwise 1 */
-static int imapaint_pick_face(ViewContext *vc,
- const int mval[2],
- unsigned int *r_index,
- unsigned int totpoly)
+static int imapaint_pick_face(ViewContext *vc, const int mval[2], uint *r_index, uint totpoly)
{
if (totpoly == 0) {
return 0;
@@ -390,9 +380,9 @@ static int imapaint_pick_face(ViewContext *vc,
/* sample only on the exact position */
ED_view3d_select_id_validate(vc);
- *r_index = DRW_select_buffer_sample_point(vc->depsgraph, vc->ar, vc->v3d, mval);
+ *r_index = DRW_select_buffer_sample_point(vc->depsgraph, vc->region, vc->v3d, mval);
- if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
+ if ((*r_index) == 0 || (*r_index) > (uint)totpoly) {
return 0;
}
@@ -405,7 +395,7 @@ static Image *imapaint_face_image(Object *ob, Mesh *me, int face_index)
{
Image *ima;
MPoly *mp = me->mpoly + face_index;
- Material *ma = give_current_material(ob, mp->mat_nr + 1);
+ Material *ma = BKE_object_material_get(ob, mp->mat_nr + 1);
ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
return ima;
@@ -459,7 +449,7 @@ void flip_qt_qt(float out[4], const float in[4], const ePaintSymmetryFlags symm)
/* used for both 3d view and image window */
void paint_sample_color(
- bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
+ bContext *C, ARegion *region, int x, int y, bool texpaint_proj, bool use_palette)
{
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
@@ -467,11 +457,11 @@ void paint_sample_color(
Palette *palette = BKE_paint_palette(paint);
PaletteColor *color = NULL;
Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
- unsigned int col;
- const unsigned char *cp;
+ uint col;
+ const uchar *cp;
- CLAMP(x, 0, ar->winx);
- CLAMP(y, 0, ar->winy);
+ CLAMP(x, 0, region->winx);
+ CLAMP(y, 0, region->winy);
if (use_palette) {
if (!palette) {
@@ -500,8 +490,8 @@ void paint_sample_color(
ViewContext vc;
const int mval[2] = {x, y};
- unsigned int faceindex;
- unsigned int totpoly = me->totpoly;
+ uint faceindex;
+ uint totpoly = me->totpoly;
if (CustomData_has_layer(&me_eval->ldata, CD_MLOOPUV)) {
ED_view3d_viewcontext_init(C, &vc, depsgraph);
@@ -521,8 +511,10 @@ void paint_sample_color(
if (image) {
float uv[2];
float u, v;
+ /* XXX get appropriate ImageUser instead */
ImageUser iuser;
BKE_imageuser_default(&iuser);
+ iuser.framenr = image->lastframe;
imapaint_pick_uv(me_eval, scene, ob_eval, faceindex, mval, uv);
@@ -545,7 +537,7 @@ void paint_sample_color(
}
ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, NULL);
- if (ibuf && ibuf->rect) {
+ if (ibuf && (ibuf->rect || ibuf->rect_float)) {
sample_success = true;
u = u * ibuf->x;
@@ -564,7 +556,7 @@ void paint_sample_color(
}
}
else {
- unsigned char rgba[4];
+ uchar rgba[4];
bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
if (use_palette) {
rgb_uchar_to_float(color->rgb, rgba);
@@ -586,7 +578,7 @@ void paint_sample_color(
if (!sample_success) {
glReadBuffer(GL_FRONT);
glReadPixels(
- x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ x + region->winrct.xmin, y + region->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
glReadBuffer(GL_BACK);
}
else {
@@ -595,10 +587,11 @@ void paint_sample_color(
}
else {
glReadBuffer(GL_FRONT);
- glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadPixels(
+ x + region->winrct.xmin, y + region->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
glReadBuffer(GL_BACK);
}
- cp = (unsigned char *)&col;
+ cp = (uchar *)&col;
if (use_palette) {
rgb_uchar_to_float(color->rgb, cp);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 7372ea6d44a..a18a0145faa 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -28,23 +28,24 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array_utils.h"
#include "BLI_listbase.h"
-#include "BLI_rect.h"
#include "BLI_math.h"
-#include "BLI_array_utils.h"
+#include "BLI_rect.h"
#include "BLI_task.h"
+#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_object_types.h"
#include "RNA_access.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
@@ -54,29 +55,28 @@
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_subsurf.h"
-#include "BKE_layer.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "ED_armature.h"
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
/* For IMB_BlendMode only. */
#include "IMB_imbuf.h"
-#include "bmesh.h"
#include "BKE_ccg.h"
+#include "bmesh.h"
-#include "sculpt_intern.h"
#include "paint_intern.h" /* own include */
+#include "sculpt_intern.h"
/* -------------------------------------------------------------------- */
/** \name Internal Utilities
@@ -172,7 +172,7 @@ static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev,
MDeformVert *dv_prev = &dvert_prev[index];
if (dv_prev->flag == 1) {
dv_prev->flag = 0;
- defvert_copy(dv_prev, dv_curr);
+ BKE_defvert_copy(dv_prev, dv_curr);
}
return dv_prev;
}
@@ -181,7 +181,7 @@ static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev,
* (without evaluating modifiers) */
static bool vertex_paint_use_fast_update_check(Object *ob)
{
- Mesh *me_eval = ob->runtime.mesh_eval;
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
if (me_eval != NULL) {
Mesh *me = BKE_mesh_from_object(ob);
@@ -214,10 +214,10 @@ bool vertex_paint_mode_poll(bContext *C)
static bool vertex_paint_poll_ex(bContext *C, bool check_tool)
{
if (vertex_paint_mode_poll(C) && BKE_paint_brush(&CTX_data_tool_settings(C)->vpaint->paint)) {
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = CTX_wm_region(C);
- if (ar->regiontype == RGN_TYPE_WINDOW) {
+ ScrArea *area = CTX_wm_area(C);
+ if (area && area->spacetype == SPACE_VIEW3D) {
+ ARegion *region = CTX_wm_region(C);
+ if (region->regiontype == RGN_TYPE_WINDOW) {
if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
return 1;
}
@@ -247,13 +247,13 @@ bool weight_paint_mode_poll(bContext *C)
static bool weight_paint_poll_ex(bContext *C, bool check_tool)
{
Object *ob = CTX_data_active_object(C);
- ScrArea *sa;
+ ScrArea *area;
if ((ob != NULL) && (ob->mode & OB_MODE_WEIGHT_PAINT) &&
(BKE_paint_brush(&CTX_data_tool_settings(C)->wpaint->paint) != NULL) &&
- (sa = CTX_wm_area(C)) && (sa->spacetype == SPACE_VIEW3D)) {
- ARegion *ar = CTX_wm_region(C);
- if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_HUD)) {
+ (area = CTX_wm_area(C)) && (area->spacetype == SPACE_VIEW3D)) {
+ ARegion *region = CTX_wm_region(C);
+ if (ELEM(region->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_HUD)) {
if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
return 1;
}
@@ -349,7 +349,7 @@ static void tex_color_alpha(VPaint *vp, const ViewContext *vc, const float co[3]
else {
float co_ss[2]; /* screenspace */
if (ED_view3d_project_float_object(
- vc->ar, co, co_ss, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) ==
+ vc->region, co, co_ss, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) ==
V3D_PROJ_RET_OK) {
const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f}; /* we need a 3rd empty value */
BKE_brush_sample_tex_3d(vc->scene, brush, co_ss_3d, r_rgba, 0, NULL);
@@ -413,6 +413,31 @@ static float wpaint_clamp_monotonic(float oldval, float curval, float newval)
}
}
+static float wpaint_undo_lock_relative(
+ float weight, float old_weight, float locked_weight, float free_weight, bool auto_normalize)
+{
+ /* In auto-normalize mode, or when there is no unlocked weight,
+ * compute based on locked weight. */
+ if (auto_normalize || free_weight <= 0.0f) {
+ weight *= (1.0f - locked_weight);
+ }
+ else {
+ /* When dealing with full unlocked weight, don't paint, as it is always displayed as 1. */
+ if (old_weight >= free_weight) {
+ weight = old_weight;
+ }
+ /* Try to compute a weight value that would produce the desired effect if normalized. */
+ else if (weight < 1.0f) {
+ weight = weight * (free_weight - old_weight) / (1 - weight);
+ }
+ else {
+ weight = 1.0f;
+ }
+ }
+
+ return weight;
+}
+
/* ----------------------------------------------------- */
static void do_weight_paint_normalize_all(MDeformVert *dvert,
@@ -704,10 +729,16 @@ typedef struct WeightPaintInfo {
/* same as WeightPaintData.vgroup_validmap,
* only added here for convenience */
const bool *vgroup_validmap;
+ /* same as WeightPaintData.vgroup_locked/unlocked,
+ * only added here for convenience */
+ const bool *vgroup_locked;
+ const bool *vgroup_unlocked;
bool do_flip;
bool do_multipaint;
bool do_auto_normalize;
+ bool do_lock_relative;
+ bool is_normalized;
float brush_alpha_value; /* result of BKE_brush_alpha_get() */
} WeightPaintInfo;
@@ -727,7 +758,8 @@ static void do_weight_paint_vertex_single(
bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
MDeformWeight *dw;
- float weight_prev;
+ float weight_prev, weight_cur;
+ float dw_rel_locked = 0.0f, dw_rel_free = 1.0f;
/* mirror vars */
int index_mirr;
@@ -752,10 +784,10 @@ static void do_weight_paint_vertex_single(
}
if (wp->flag & VP_FLAG_VGROUP_RESTRICT) {
- dw = defvert_find_index(dv, wpi->active.index);
+ dw = BKE_defvert_find_index(dv, wpi->active.index);
}
else {
- dw = defvert_verify_index(dv, wpi->active.index);
+ dw = BKE_defvert_ensure_index(dv, wpi->active.index);
}
if (dw == NULL) {
@@ -766,7 +798,7 @@ static void do_weight_paint_vertex_single(
if (index_mirr != -1) {
dv_mirr = &me->dvert[index_mirr];
if (wp->flag & VP_FLAG_VGROUP_RESTRICT) {
- dw_mirr = defvert_find_index(dv_mirr, vgroup_mirr);
+ dw_mirr = BKE_defvert_find_index(dv_mirr, vgroup_mirr);
if (dw_mirr == NULL) {
index_mirr = vgroup_mirr = -1;
@@ -775,13 +807,13 @@ static void do_weight_paint_vertex_single(
}
else {
if (index != index_mirr) {
- dw_mirr = defvert_verify_index(dv_mirr, vgroup_mirr);
+ dw_mirr = BKE_defvert_ensure_index(dv_mirr, vgroup_mirr);
}
else {
/* dv and dv_mirr are the same */
int totweight_prev = dv_mirr->totweight;
int dw_offset = (int)(dw - dv_mirr->dw);
- dw_mirr = defvert_verify_index(dv_mirr, vgroup_mirr);
+ dw_mirr = BKE_defvert_ensure_index(dv_mirr, vgroup_mirr);
/* if we added another, get our old one back */
if (totweight_prev != dv_mirr->totweight) {
@@ -795,6 +827,17 @@ static void do_weight_paint_vertex_single(
dw_mirr = NULL;
}
+ weight_cur = dw->weight;
+
+ /* Handle weight caught up in locked defgroups for Lock Relative. */
+ if (wpi->do_lock_relative) {
+ dw_rel_free = BKE_defvert_total_selected_weight(dv, wpi->defbase_tot, wpi->vgroup_unlocked);
+ dw_rel_locked = BKE_defvert_total_selected_weight(dv, wpi->defbase_tot, wpi->vgroup_locked);
+ CLAMP(dw_rel_locked, 0.0f, 1.0f);
+
+ weight_cur = BKE_defvert_calc_lock_relative_weight(weight_cur, dw_rel_locked, dw_rel_free);
+ }
+
if (!brush_use_accumulate(wp)) {
MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev;
MDeformVert *dv_prev = defweight_prev_init(dvert_prev, me->dvert, index);
@@ -802,10 +845,15 @@ static void do_weight_paint_vertex_single(
defweight_prev_init(dvert_prev, me->dvert, index_mirr);
}
- weight_prev = defvert_find_weight(dv_prev, wpi->active.index);
+ weight_prev = BKE_defvert_find_weight(dv_prev, wpi->active.index);
+
+ if (wpi->do_lock_relative) {
+ weight_prev = BKE_defvert_lock_relative_weight(
+ weight_prev, dv_prev, wpi->defbase_tot, wpi->vgroup_locked, wpi->vgroup_unlocked);
+ }
}
else {
- weight_prev = dw->weight;
+ weight_prev = weight_cur;
}
/* If there are no normalize-locks or multipaint,
@@ -815,7 +863,28 @@ static void do_weight_paint_vertex_single(
float new_weight = wpaint_blend(
wp, weight_prev, alpha, paintweight, wpi->brush_alpha_value, wpi->do_flip);
- dw->weight = wpaint_clamp_monotonic(weight_prev, dw->weight, new_weight);
+ float weight = wpaint_clamp_monotonic(weight_prev, weight_cur, new_weight);
+
+ /* Undo the lock relative weight correction. */
+ if (wpi->do_lock_relative) {
+ if (index_mirr == index) {
+ /* When painting a center vertex with X Mirror and L/R pair,
+ * handle both groups together. This avoids weird fighting
+ * in the non-normalized weight mode. */
+ float orig_weight = dw->weight + dw_mirr->weight;
+ weight = 0.5f *
+ wpaint_undo_lock_relative(
+ weight * 2, orig_weight, dw_rel_locked, dw_rel_free, wpi->do_auto_normalize);
+ }
+ else {
+ weight = wpaint_undo_lock_relative(
+ weight, dw->weight, dw_rel_locked, dw_rel_free, wpi->do_auto_normalize);
+ }
+
+ CLAMP(weight, 0.0f, 1.0f);
+ }
+
+ dw->weight = weight;
/* WATCH IT: take care of the ordering of applying mirror -> normalize,
* can give wrong results [#26193], least confusing if normalize is done last */
@@ -892,7 +961,8 @@ static void do_weight_paint_vertex_multi(
MDeformVert *dv_mirr = NULL;
/* weights */
- float curw, oldw, neww, change, curw_mirr, change_mirr;
+ float curw, curw_real, oldw, neww, change, curw_mirr, change_mirr;
+ float dw_rel_free, dw_rel_locked;
/* from now on we can check if mirrors enabled if this var is -1 and not bother with the flag */
if (me->editflag & ME_EDIT_MIRROR_X) {
@@ -907,14 +977,23 @@ static void do_weight_paint_vertex_multi(
}
/* compute weight change by applying the brush to average or sum of group weights */
- curw = BKE_defvert_multipaint_collective_weight(
- dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
+ curw = curw_real = BKE_defvert_multipaint_collective_weight(
+ dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized);
if (curw == 0.0f) {
/* note: no weight to assign to this vertex, could add all groups? */
return;
}
+ /* Handle weight caught up in locked defgroups for Lock Relative. */
+ if (wpi->do_lock_relative) {
+ dw_rel_free = BKE_defvert_total_selected_weight(dv, wpi->defbase_tot, wpi->vgroup_unlocked);
+ dw_rel_locked = BKE_defvert_total_selected_weight(dv, wpi->defbase_tot, wpi->vgroup_locked);
+ CLAMP(dw_rel_locked, 0.0f, 1.0f);
+
+ curw = BKE_defvert_calc_lock_relative_weight(curw, dw_rel_locked, dw_rel_free);
+ }
+
if (!brush_use_accumulate(wp)) {
MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev;
MDeformVert *dv_prev = defweight_prev_init(dvert_prev, me->dvert, index);
@@ -923,7 +1002,12 @@ static void do_weight_paint_vertex_multi(
}
oldw = BKE_defvert_multipaint_collective_weight(
- dv_prev, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
+ dv_prev, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized);
+
+ if (wpi->do_lock_relative) {
+ oldw = BKE_defvert_lock_relative_weight(
+ oldw, dv_prev, wpi->defbase_tot, wpi->vgroup_locked, wpi->vgroup_unlocked);
+ }
}
else {
oldw = curw;
@@ -932,14 +1016,19 @@ static void do_weight_paint_vertex_multi(
neww = wpaint_blend(wp, oldw, alpha, paintweight, wpi->brush_alpha_value, wpi->do_flip);
neww = wpaint_clamp_monotonic(oldw, curw, neww);
- change = neww / curw;
+ if (wpi->do_lock_relative) {
+ neww = wpaint_undo_lock_relative(
+ neww, curw_real, dw_rel_locked, dw_rel_free, wpi->do_auto_normalize);
+ }
+
+ change = neww / curw_real;
/* verify for all groups that 0 < result <= 1 */
multipaint_clamp_change(dv, wpi->defbase_tot, wpi->defbase_sel, &change);
if (dv_mirr != NULL) {
curw_mirr = BKE_defvert_multipaint_collective_weight(
- dv_mirr, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
+ dv_mirr, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized);
if (curw_mirr == 0.0f) {
/* can't mirror into a zero weight vertex */
@@ -947,7 +1036,7 @@ static void do_weight_paint_vertex_multi(
}
else {
/* mirror is changed to achieve the same collective weight value */
- float orig = change_mirr = curw * change / curw_mirr;
+ float orig = change_mirr = curw_real * change / curw_mirr;
multipaint_clamp_change(dv_mirr, wpi->defbase_tot, wpi->defbase_sel, &change_mirr);
@@ -1137,7 +1226,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain,
BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT);
/* weight paint specific */
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
+ ED_mesh_mirror_spatial_table_end(ob);
ED_vgroup_sync_from_pose(ob);
}
else {
@@ -1147,7 +1236,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain,
/* Create vertex/weight paint mode session data */
if (ob->sculpt) {
if (ob->sculpt->cache) {
- sculpt_cache_free(ob->sculpt->cache);
+ SCULPT_cache_free(ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
BKE_sculptsession_free(ob);
@@ -1220,7 +1309,7 @@ static void ed_vwpaintmode_exit_generic(Object *ob, const eObjectMode mode_flag)
/* If the cache is not released by a cancel or a done, free it now. */
if (ob->sculpt && ob->sculpt->cache) {
- sculpt_cache_free(ob->sculpt->cache);
+ SCULPT_cache_free(ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
@@ -1229,8 +1318,8 @@ static void ed_vwpaintmode_exit_generic(Object *ob, const eObjectMode mode_flag)
paint_cursor_delete_textures();
if (mode_flag == OB_MODE_WEIGHT_PAINT) {
- ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
- ED_mesh_mirror_topo_table(NULL, NULL, 'e');
+ ED_mesh_mirror_spatial_table_end(ob);
+ ED_mesh_mirror_topo_table_end(ob);
}
/* Never leave derived meshes behind. */
@@ -1309,7 +1398,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
*/
{
VirtualModifierData virtualModifierData;
- ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
if (md != NULL) {
/* Can be NULL. */
View3D *v3d = CTX_wm_view3d(C);
@@ -1361,8 +1450,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* for switching to/from mode */
-static bool paint_poll_test(bContext *C)
+static bool paint_mode_toggle_poll_test(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if (ob == NULL || ob->type != OB_MESH) {
@@ -1371,9 +1459,6 @@ static bool paint_poll_test(bContext *C)
if (!ob->data || ID_IS_LINKED(ob->data)) {
return 0;
}
- if (CTX_data_edit_object(C)) {
- return 0;
- }
return 1;
}
@@ -1387,7 +1472,7 @@ void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
/* api callbacks */
ot->exec = wpaint_mode_toggle_exec;
- ot->poll = paint_poll_test;
+ ot->poll = paint_mode_toggle_poll_test;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1408,11 +1493,14 @@ struct WPaintData {
/* variables for auto normalize */
const bool *vgroup_validmap; /* stores if vgroups tie to deforming bones or not */
const bool *lock_flags;
+ const bool *vgroup_locked; /* mask of locked defbones */
+ const bool *vgroup_unlocked; /* mask of unlocked defbones */
/* variables for multipaint */
const bool *defbase_sel; /* set of selected groups */
int defbase_tot_sel; /* number of selected groups */
bool do_multipaint; /* true if multipaint enabled and multiple groups selected */
+ bool do_lock_relative;
int defbase_tot;
@@ -1615,10 +1703,29 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
/* set up auto-normalize, and generate map for detecting which
* vgroups affect deform bones */
wpd->lock_flags = BKE_object_defgroup_lock_flags_get(ob, wpd->defbase_tot);
- if (ts->auto_normalize || ts->multipaint || wpd->lock_flags) {
+ if (ts->auto_normalize || ts->multipaint || wpd->lock_flags || ts->wpaint_lock_relative) {
wpd->vgroup_validmap = BKE_object_defgroup_validmap_get(ob, wpd->defbase_tot);
}
+ /* Compute the set of all locked deform groups when Lock Relative is active. */
+ if (ts->wpaint_lock_relative &&
+ BKE_object_defgroup_check_lock_relative(
+ wpd->lock_flags, wpd->vgroup_validmap, wpd->active.index) &&
+ (!wpd->do_multipaint || BKE_object_defgroup_check_lock_relative_multi(
+ defbase_tot, wpd->lock_flags, defbase_sel, defbase_tot_sel))) {
+ bool *unlocked = MEM_dupallocN(wpd->vgroup_validmap);
+
+ if (wpd->lock_flags) {
+ bool *locked = MEM_mallocN(sizeof(bool) * wpd->defbase_tot, __func__);
+ BKE_object_defgroup_split_locked_validmap(
+ wpd->defbase_tot, wpd->lock_flags, wpd->vgroup_validmap, locked, unlocked);
+ wpd->vgroup_locked = locked;
+ }
+
+ wpd->vgroup_unlocked = unlocked;
+ wpd->do_lock_relative = true;
+ }
+
if (wpd->do_multipaint && ts->auto_normalize) {
bool *tmpflags;
tmpflags = MEM_mallocN(sizeof(bool) * defbase_tot, __func__);
@@ -1686,16 +1793,23 @@ static void get_brush_alpha_data(const Scene *scene,
static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintInfo *wpi)
{
- if (wpi->do_multipaint) {
- float weight = BKE_defvert_multipaint_collective_weight(
- dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
+ float weight;
- CLAMP(weight, 0.0f, 1.0f);
- return weight;
+ if (wpi->do_multipaint) {
+ weight = BKE_defvert_multipaint_collective_weight(
+ dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized);
}
else {
- return defvert_find_weight(dv, wpi->active.index);
+ weight = BKE_defvert_find_weight(dv, wpi->active.index);
}
+
+ if (wpi->do_lock_relative) {
+ weight = BKE_defvert_lock_relative_weight(
+ weight, dv, wpi->defbase_tot, wpi->vgroup_locked, wpi->vgroup_unlocked);
+ }
+
+ CLAMP(weight, 0.0f, 1.0f);
+ return weight;
}
static void do_wpaint_precompute_weight_cb_ex(void *__restrict userdata,
@@ -1753,9 +1867,9 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
/* For each vertex */
@@ -1850,9 +1964,9 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) {
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
/* For each vertex */
@@ -1957,9 +2071,9 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
/* For each vertex */
@@ -2026,9 +2140,9 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(
accum->value = 0.0;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
/* For each vertex */
@@ -2065,9 +2179,9 @@ static void calculate_average_weight(SculptThreadedTaskData *data,
struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
data->custom_data = accum;
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (data->sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings);
uint accum_len = 0;
double accum_weight = 0.0;
@@ -2113,22 +2227,22 @@ static void wpaint_paint_leaves(bContext *C,
data.strength = BKE_brush_weight_get(scene, brush);
/* NOTE: current mirroring code cannot be run in parallel */
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, !(me->editflag & ME_EDIT_MIRROR_X), totnode);
switch ((eBrushWeightPaintTool)brush->weightpaint_tool) {
case WPAINT_TOOL_AVERAGE:
calculate_average_weight(&data, nodes, totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
break;
case WPAINT_TOOL_SMEAR:
- BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings);
break;
case WPAINT_TOOL_BLUR:
- BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings);
break;
case WPAINT_TOOL_DRAW:
- BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
break;
}
}
@@ -2148,9 +2262,9 @@ static PBVHNode **vwpaint_pbvh_gather_generic(
.radius_squared = ss->cache->radius_squared,
.original = true,
};
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode);
+ BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
if (use_normal) {
- sculpt_pbvh_calc_area_normal(
+ SCULPT_pbvh_calc_area_normal(
brush, ob, nodes, *r_totnode, true, ss->cache->sculpt_normal_symm);
}
else {
@@ -2168,7 +2282,7 @@ static PBVHNode **vwpaint_pbvh_gather_generic(
.original = true,
.dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc,
};
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_circle_cb, &data, &nodes, r_totnode);
+ BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_circle_cb, &data, &nodes, r_totnode);
if (use_normal) {
copy_v3_v3(ss->cache->sculpt_normal_symm, ss->cache->view_normal);
}
@@ -2194,7 +2308,7 @@ static void wpaint_do_paint(bContext *C,
{
SculptSession *ss = ob->sculpt;
ss->cache->radial_symmetry_pass = i;
- sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
+ SCULPT_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
int totnode;
PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, wp, sd, brush, &totnode);
@@ -2249,7 +2363,7 @@ static void wpaint_do_symmetrical_brush_actions(
if ((symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) {
cache->mirror_symmetry_pass = i;
cache->radial_symmetry_pass = 0;
- sculpt_cache_calc_brushdata_symm(cache, i, 0, 0);
+ SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
if (i & (1 << 0)) {
wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X', 0, 0);
@@ -2318,9 +2432,13 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
wpi.mirror = wpd->mirror;
wpi.lock_flags = wpd->lock_flags;
wpi.vgroup_validmap = wpd->vgroup_validmap;
+ wpi.vgroup_locked = wpd->vgroup_locked;
+ wpi.vgroup_unlocked = wpd->vgroup_unlocked;
wpi.do_flip = RNA_boolean_get(itemptr, "pen_flip");
wpi.do_multipaint = wpd->do_multipaint;
wpi.do_auto_normalize = ((ts->auto_normalize != 0) && (wpi.vgroup_validmap != NULL));
+ wpi.do_lock_relative = wpd->do_lock_relative;
+ wpi.is_normalized = wpi.do_auto_normalize || wpi.do_lock_relative;
wpi.brush_alpha_value = brush_alpha_value;
/* *** done setting up WeightPaintInfo *** */
@@ -2332,8 +2450,8 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
swap_m4m4(vc->rv3d->persmat, mat);
- /* calculate pivot for rotation around seletion if needed */
- /* also needed for "View Selected" on last stroke */
+ /* Calculate pivot for rotation around selection if needed.
+ * also needed for "Frame Selected" on last stroke. */
float loc_world[3];
mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location);
paint_last_stroke_update(scene, loc_world);
@@ -2345,7 +2463,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
swap_m4m4(wpd->vc.rv3d->persmat, mat);
rcti r;
- if (sculpt_get_redraw_rect(vc->ar, CTX_wm_region_view3d(C), ob, &r)) {
+ if (SCULPT_get_redraw_rect(vc->region, CTX_wm_region_view3d(C), ob, &r)) {
if (ss->cache) {
ss->cache->current_r = r;
}
@@ -2358,12 +2476,12 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
}
}
- r.xmin += vc->ar->winrct.xmin - 2;
- r.xmax += vc->ar->winrct.xmin + 2;
- r.ymin += vc->ar->winrct.ymin - 2;
- r.ymax += vc->ar->winrct.ymin + 2;
+ r.xmin += vc->region->winrct.xmin - 2;
+ r.xmax += vc->region->winrct.xmin + 2;
+ r.ymin += vc->region->winrct.ymin - 2;
+ r.ymax += vc->region->winrct.ymin + 2;
}
- ED_region_tag_redraw_partial(vc->ar, &r, true);
+ ED_region_tag_redraw_partial(vc->region, &r, true);
}
static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
@@ -2378,6 +2496,12 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
if (wpd->vgroup_validmap) {
MEM_freeN((void *)wpd->vgroup_validmap);
}
+ if (wpd->vgroup_locked) {
+ MEM_freeN((void *)wpd->vgroup_locked);
+ }
+ if (wpd->vgroup_unlocked) {
+ MEM_freeN((void *)wpd->vgroup_unlocked);
+ }
if (wpd->lock_flags) {
MEM_freeN((void *)wpd->lock_flags);
}
@@ -2413,7 +2537,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- sculpt_cache_free(ob->sculpt->cache);
+ SCULPT_cache_free(ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
@@ -2423,7 +2547,7 @@ static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
op->customdata = paint_stroke_new(C,
op,
- sculpt_stroke_get_location,
+ SCULPT_stroke_get_location,
wpaint_stroke_test_start,
wpaint_stroke_update_step,
NULL,
@@ -2447,7 +2571,7 @@ static int wpaint_exec(bContext *C, wmOperator *op)
{
op->customdata = paint_stroke_new(C,
op,
- sculpt_stroke_get_location,
+ SCULPT_stroke_get_location,
wpaint_stroke_test_start,
wpaint_stroke_update_step,
NULL,
@@ -2464,7 +2588,7 @@ static void wpaint_cancel(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
if (ob->sculpt->cache) {
- sculpt_cache_free(ob->sculpt->cache);
+ SCULPT_cache_free(ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
@@ -2524,6 +2648,9 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
}
else {
Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
+ if (depsgraph) {
+ depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ }
wmWindowManager *wm = CTX_wm_manager(C);
ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
BKE_paint_toolslots_brush_validate(bmain, &ts->vpaint->paint);
@@ -2552,7 +2679,7 @@ void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
/* api callbacks */
ot->exec = vpaint_mode_toggle_exec;
- ot->poll = paint_poll_test;
+ ot->poll = paint_mode_toggle_poll_test;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2707,7 +2834,7 @@ static void do_vpaint_brush_calc_average_color_cb_ex(void *__restrict userdata,
memset(accum->value, 0, sizeof(accum->value));
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
/* For each vertex */
@@ -2775,9 +2902,9 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata,
const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
/* For each vertex */
@@ -2874,9 +3001,9 @@ static void do_vpaint_brush_blur_task_cb_ex(void *__restrict userdata,
const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
/* For each vertex */
@@ -2998,9 +3125,9 @@ static void do_vpaint_brush_smear_task_cb_ex(void *__restrict userdata,
if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) {
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
- const float *sculpt_normal_frontface = sculpt_brush_frontface_normal_from_falloff_shape(
+ const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
/* For each vertex */
@@ -3121,9 +3248,9 @@ static void calculate_average_color(SculptThreadedTaskData *data,
struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
data->custom_data = accum;
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
- BKE_pbvh_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings);
uint accum_len = 0;
uint accum_value[3] = {0};
@@ -3167,21 +3294,21 @@ static void vpaint_paint_leaves(bContext *C,
.lcol = (uint *)me->mloopcol,
.me = me,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) {
case VPAINT_TOOL_AVERAGE:
calculate_average_color(&data, nodes, totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
break;
case VPAINT_TOOL_BLUR:
- BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings);
break;
case VPAINT_TOOL_SMEAR:
- BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings);
break;
case VPAINT_TOOL_DRAW:
- BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
break;
}
}
@@ -3200,7 +3327,7 @@ static void vpaint_do_paint(bContext *C,
{
SculptSession *ss = ob->sculpt;
ss->cache->radial_symmetry_pass = i;
- sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
+ SCULPT_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
int totnode;
PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, vp, sd, brush, &totnode);
@@ -3255,7 +3382,7 @@ static void vpaint_do_symmetrical_brush_actions(
if (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5))) {
cache->mirror_symmetry_pass = i;
cache->radial_symmetry_pass = 0;
- sculpt_cache_calc_brushdata_symm(cache, i, 0, 0);
+ SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
if (i & (1 << 0)) {
vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'X', 0, 0);
@@ -3309,13 +3436,13 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
vpd->smear.color_prev, vpd->smear.color_curr, sizeof(uint) * ((Mesh *)ob->data)->totloop);
}
- /* calculate pivot for rotation around seletion if needed */
- /* also needed for "View Selected" on last stroke */
+ /* Calculate pivot for rotation around selection if needed.
+ * also needed for "Frame Selected" on last stroke. */
float loc_world[3];
mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location);
paint_last_stroke_update(scene, loc_world);
- ED_region_tag_redraw(vc->ar);
+ ED_region_tag_redraw(vc->region);
if (vpd->use_fast_update == false) {
/* recalculate modifier stack to get new colors, slow,
@@ -3352,7 +3479,7 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
MEM_freeN(vpd);
- sculpt_cache_free(ob->sculpt->cache);
+ SCULPT_cache_free(ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
@@ -3362,7 +3489,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
op->customdata = paint_stroke_new(C,
op,
- sculpt_stroke_get_location,
+ SCULPT_stroke_get_location,
vpaint_stroke_test_start,
vpaint_stroke_update_step,
NULL,
@@ -3387,7 +3514,7 @@ static int vpaint_exec(bContext *C, wmOperator *op)
{
op->customdata = paint_stroke_new(C,
op,
- sculpt_stroke_get_location,
+ SCULPT_stroke_get_location,
vpaint_stroke_test_start,
vpaint_stroke_update_step,
NULL,
@@ -3404,7 +3531,7 @@ static void vpaint_cancel(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
if (ob->sculpt->cache) {
- sculpt_cache_free(ob->sculpt->cache);
+ SCULPT_cache_free(ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
index 266c130d12a..addf7e9f868 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
@@ -29,8 +29,8 @@
#include "BLI_math_color.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
#include "BKE_deform.h"
+#include "BKE_mesh.h"
#include "DEG_depsgraph.h"
@@ -109,7 +109,7 @@ static int vertex_color_set_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
- unsigned int paintcol = vpaint_get_current_col(scene, scene->toolsettings->vpaint, false);
+ uint paintcol = vpaint_get_current_col(scene, scene->toolsettings->vpaint, false);
if (vertex_color_set(obact, paintcol)) {
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
@@ -160,7 +160,7 @@ static bool vertex_paint_from_weight(Object *ob)
uint j = 0;
do {
uint vidx = me->mloop[mp->loopstart + j].v;
- const float weight = defvert_find_weight(&me->dvert[vidx], vgroup_active);
+ const float weight = BKE_defvert_find_weight(&me->dvert[vidx], vgroup_active);
const uchar grayscale = weight * 255;
lcol->r = grayscale;
lcol->b = grayscale;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
index 71865d0de73..c26db3e265b 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
@@ -230,7 +230,7 @@ BLI_INLINE uint mcol_lighten(uint col_src, uint col_dst, int fac)
cp_dst = (uchar *)&col_dst;
cp_mix = (uchar *)&col_mix;
- /* See if are lighter, if so mix, else don't do anything.
+ /* See if we're lighter, if so mix, else don't do anything.
* if the paint color is darker then the original, then ignore */
if (IMB_colormanagement_get_luminance_byte(cp_src) >
IMB_colormanagement_get_luminance_byte(cp_dst)) {
@@ -264,7 +264,7 @@ BLI_INLINE uint mcol_darken(uint col_src, uint col_dst, int fac)
cp_dst = (uchar *)&col_dst;
cp_mix = (uchar *)&col_mix;
- /* See if were darker, if so mix, else don't do anything.
+ /* See if we're darker, if so mix, else don't do anything.
* if the paint color is brighter then the original, then ignore */
if (IMB_colormanagement_get_luminance_byte(cp_src) <
IMB_colormanagement_get_luminance_byte(cp_dst)) {
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
index 7bca7745ca0..85cd211367a 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
@@ -26,8 +26,8 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
@@ -65,7 +65,7 @@ struct VertProjUpdate {
struct VertProjHandle *vp_handle;
/* runtime */
- ARegion *ar;
+ ARegion *region;
const float *mval_fl;
};
@@ -130,7 +130,7 @@ static void vpaint_proj_dm_map_cosnos_update__map_cb(
float co_ss[2]; /* screenspace */
if (ED_view3d_project_float_object(
- vp_update->ar, co, co_ss, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) ==
+ vp_update->region, co, co_ss, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) ==
V3D_PROJ_RET_OK) {
const float dist_sq = len_squared_v2v2(vp_update->mval_fl, co_ss);
if (dist_sq > vp_handle->dists_sq[index]) {
@@ -158,10 +158,10 @@ static void vpaint_proj_dm_map_cosnos_update__map_cb(
static void vpaint_proj_dm_map_cosnos_update(struct Depsgraph *depsgraph,
struct VertProjHandle *vp_handle,
- ARegion *ar,
+ ARegion *region,
const float mval_fl[2])
{
- struct VertProjUpdate vp_update = {vp_handle, ar, mval_fl};
+ struct VertProjUpdate vp_update = {vp_handle, region, mval_fl};
Object *ob = vp_handle->ob;
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
@@ -216,11 +216,11 @@ struct VertProjHandle *ED_vpaint_proj_handle_create(struct Depsgraph *depsgraph,
void ED_vpaint_proj_handle_update(struct Depsgraph *depsgraph,
struct VertProjHandle *vp_handle,
- ARegion *ar,
+ ARegion *region,
const float mval_fl[2])
{
if (vp_handle->use_update) {
- vpaint_proj_dm_map_cosnos_update(depsgraph, vp_handle, ar, mval_fl);
+ vpaint_proj_dm_map_cosnos_update(depsgraph, vp_handle, region, mval_fl);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index ae4ef59597b..08ffd8e620e 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -20,13 +20,13 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_bitmap.h"
+#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_brush_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -35,6 +35,7 @@
#include "RNA_enum_types.h"
#include "BKE_brush.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_mesh.h"
@@ -44,7 +45,6 @@
#include "BKE_object_deform.h"
#include "BKE_paint.h"
#include "BKE_report.h"
-#include "BKE_colortools.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -108,7 +108,7 @@ static bool weight_from_bones_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && modifiers_isDeformedByArmature(ob));
+ return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && BKE_modifiers_is_deformed_by_armature(ob));
}
static int weight_from_bones_exec(bContext *C, wmOperator *op)
@@ -116,7 +116,7 @@ static int weight_from_bones_exec(bContext *C, wmOperator *op)
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- Object *armob = modifiers_isDeformedByArmature(ob);
+ Object *armob = BKE_modifiers_is_deformed_by_armature(ob);
Mesh *me = ob->data;
int type = RNA_enum_get(op->ptr, "type");
@@ -211,13 +211,23 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
ToolSettings *ts = vc.scene->toolsettings;
Brush *brush = BKE_paint_brush(&ts->wpaint->paint);
const int vgroup_active = vc.obact->actdef - 1;
- float vgroup_weight = defvert_find_weight(&me->dvert[v_idx_best], vgroup_active);
+ float vgroup_weight = BKE_defvert_find_weight(&me->dvert[v_idx_best], vgroup_active);
+ const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
+ bool use_lock_relative = ts->wpaint_lock_relative;
+ bool *defbase_locked = NULL, *defbase_unlocked = NULL;
+
+ if (use_lock_relative) {
+ defbase_locked = BKE_object_defgroup_lock_flags_get(vc.obact, defbase_tot);
+ defbase_unlocked = BKE_object_defgroup_validmap_get(vc.obact, defbase_tot);
+
+ use_lock_relative = BKE_object_defgroup_check_lock_relative(
+ defbase_locked, defbase_unlocked, vgroup_active);
+ }
/* use combined weight in multipaint mode,
* since that's what is displayed to the user in the colors */
if (ts->multipaint) {
int defbase_tot_sel;
- const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
bool *defbase_sel = BKE_object_defgroup_selected_get(
vc.obact, defbase_tot, &defbase_tot_sel);
@@ -227,20 +237,30 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
vc.obact, defbase_tot, defbase_sel, defbase_sel, &defbase_tot_sel);
}
- vgroup_weight = BKE_defvert_multipaint_collective_weight(&me->dvert[v_idx_best],
- defbase_tot,
- defbase_sel,
- defbase_tot_sel,
- ts->auto_normalize);
+ use_lock_relative = use_lock_relative &&
+ BKE_object_defgroup_check_lock_relative_multi(
+ defbase_tot, defbase_locked, defbase_sel, defbase_tot_sel);
- /* If auto-normalize is enabled, but weights are not normalized,
- * the value can exceed 1. */
- CLAMP(vgroup_weight, 0.0f, 1.0f);
+ bool is_normalized = ts->auto_normalize || use_lock_relative;
+ vgroup_weight = BKE_defvert_multipaint_collective_weight(
+ &me->dvert[v_idx_best], defbase_tot, defbase_sel, defbase_tot_sel, is_normalized);
}
MEM_freeN(defbase_sel);
}
+ if (use_lock_relative) {
+ BKE_object_defgroup_split_locked_validmap(
+ defbase_tot, defbase_locked, defbase_unlocked, defbase_locked, defbase_unlocked);
+
+ vgroup_weight = BKE_defvert_lock_relative_weight(
+ vgroup_weight, &me->dvert[v_idx_best], defbase_tot, defbase_locked, defbase_unlocked);
+ }
+
+ MEM_SAFE_FREE(defbase_locked);
+ MEM_SAFE_FREE(defbase_unlocked);
+
+ CLAMP(vgroup_weight, 0.0f, 1.0f);
BKE_brush_weight_set(vc.scene, brush, vgroup_weight);
changed = true;
}
@@ -318,8 +338,8 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C,
uint index;
const int mval[2] = {
- win->eventstate->x - vc.ar->winrct.xmin,
- win->eventstate->y - vc.ar->winrct.ymin,
+ win->eventstate->x - vc.region->winrct.xmin,
+ win->eventstate->y - vc.region->winrct.ymin,
};
view3d_operator_needs_opengl(C);
@@ -462,9 +482,9 @@ static bool weight_paint_set(Object *ob, float paintweight)
continue;
}
- dw = defvert_verify_index(&me->dvert[vidx], vgroup_active);
+ dw = BKE_defvert_ensure_index(&me->dvert[vidx], vgroup_active);
if (dw) {
- dw_prev = defvert_verify_index(wpp.wpaint_prev + vidx, vgroup_active);
+ dw_prev = BKE_defvert_ensure_index(wpp.wpaint_prev + vidx, vgroup_active);
dw_prev->weight = dw->weight; /* set the undo weight */
dw->weight = paintweight;
@@ -473,12 +493,12 @@ static bool weight_paint_set(Object *ob, float paintweight)
if (j >= 0) {
/* copy, not paint again */
if (vgroup_mirror != -1) {
- dw = defvert_verify_index(me->dvert + j, vgroup_mirror);
- dw_prev = defvert_verify_index(wpp.wpaint_prev + j, vgroup_mirror);
+ dw = BKE_defvert_ensure_index(me->dvert + j, vgroup_mirror);
+ dw_prev = BKE_defvert_ensure_index(wpp.wpaint_prev + j, vgroup_mirror);
}
else {
- dw = defvert_verify_index(me->dvert + j, vgroup_active);
- dw_prev = defvert_verify_index(wpp.wpaint_prev + j, vgroup_active);
+ dw = BKE_defvert_ensure_index(me->dvert + j, vgroup_active);
+ dw_prev = BKE_defvert_ensure_index(wpp.wpaint_prev + j, vgroup_active);
}
dw_prev->weight = dw->weight; /* set the undo weight */
dw->weight = paintweight;
@@ -563,7 +583,7 @@ typedef struct WPGradient_vertStoreBase {
} WPGradient_vertStoreBase;
typedef struct WPGradient_userData {
- struct ARegion *ar;
+ struct ARegion *region;
Scene *scene;
Mesh *me;
Brush *brush;
@@ -602,7 +622,7 @@ static void gradientVert_update(WPGradient_userData *grad_data, int index)
if (alpha != 0.0f) {
MDeformVert *dv = &me->dvert[index];
- MDeformWeight *dw = defvert_verify_index(dv, grad_data->def_nr);
+ MDeformWeight *dw = BKE_defvert_ensure_index(dv, grad_data->def_nr);
// dw->weight = alpha; // testing
int tool = grad_data->brush->blend;
float testw;
@@ -617,14 +637,14 @@ static void gradientVert_update(WPGradient_userData *grad_data, int index)
MDeformVert *dv = &me->dvert[index];
if (vs->flag & VGRAD_STORE_DW_EXIST) {
/* normally we NULL check, but in this case we know it exists */
- MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
+ MDeformWeight *dw = BKE_defvert_find_index(dv, grad_data->def_nr);
dw->weight = vs->weight_orig;
}
else {
/* wasn't originally existing, remove */
- MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
+ MDeformWeight *dw = BKE_defvert_find_index(dv, grad_data->def_nr);
if (dw) {
- defvert_remove_group(dv, dw);
+ BKE_defvert_remove_group(dv, dw);
}
}
}
@@ -671,14 +691,14 @@ static void gradientVertInit__mapFunc(void *userData,
}
if (ED_view3d_project_float_object(
- grad_data->ar, co, vs->sco, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) !=
+ grad_data->region, co, vs->sco, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) !=
V3D_PROJ_RET_OK) {
copy_v2_fl(vs->sco, FLT_MAX);
return;
}
MDeformVert *dv = &me->dvert[index];
- const MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
+ const MDeformWeight *dw = BKE_defvert_find_index(dv, grad_data->def_nr);
if (dw) {
vs->weight_orig = dw->weight;
vs->flag = VGRAD_STORE_DW_EXIST;
@@ -733,7 +753,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
{
wmGesture *gesture = op->customdata;
WPGradient_vertStoreBase *vert_cache;
- struct ARegion *ar = CTX_wm_region(C);
+ struct ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
Mesh *me = ob->data;
@@ -778,7 +798,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
sizeof(WPGradient_vertStoreBase) + (sizeof(WPGradient_vertStore) * me->totvert), __func__);
}
- data.ar = ar;
+ data.region = region;
data.scene = scene;
data.me = ob->data;
data.sco_start = sco_start;
@@ -801,7 +821,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
data.weightpaint = BKE_brush_weight_get(scene, brush);
}
- ED_view3d_init_mats_rv3d(ob, ar->regiondata);
+ ED_view3d_init_mats_rv3d(ob, region->regiondata);
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
@@ -843,8 +863,8 @@ static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, const wmEve
ret = WM_gesture_straightline_invoke(C, op, event);
if (ret & OPERATOR_RUNNING_MODAL) {
- struct ARegion *ar = CTX_wm_region(C);
- if (ar->regiontype == RGN_TYPE_WINDOW) {
+ struct ARegion *region = CTX_wm_region(C);
+ if (region->regiontype == RGN_TYPE_WINDOW) {
/* TODO, hardcoded, extend WM_gesture_straightline_ */
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
wmGesture *gesture = op->customdata;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
index 28699b45add..a483f63bc06 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
@@ -33,9 +33,9 @@
#include "BKE_deform.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_report.h"
-#include "BKE_object.h"
#include "DEG_depsgraph_build.h"
@@ -82,13 +82,13 @@ bool ED_wpaint_ensure_data(bContext *C,
/* this happens on a Bone select, when no vgroup existed yet */
if (ob->actdef <= 0) {
Object *modob;
- if ((modob = modifiers_isDeformedByArmature(ob))) {
+ if ((modob = BKE_modifiers_is_deformed_by_armature(ob))) {
Bone *actbone = ((bArmature *)modob->data)->act_bone;
if (actbone) {
bPoseChannel *pchan = BKE_pose_channel_find_name(modob->pose, actbone->name);
if (pchan) {
- bDeformGroup *dg = defgroup_find_name(ob, pchan->name);
+ bDeformGroup *dg = BKE_object_defgroup_find_name(ob, pchan->name);
if (dg == NULL) {
dg = BKE_object_defgroup_add_name(ob, pchan->name); /* sets actdef */
DEG_relations_tag_update(CTX_data_main(C));
@@ -140,9 +140,9 @@ int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
char name_flip[MAXBONENAME];
BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
- mirrdef = defgroup_name_index(ob, name_flip);
+ mirrdef = BKE_object_defgroup_name_index(ob, name_flip);
if (mirrdef == -1) {
- if (BKE_defgroup_new(ob, name_flip)) {
+ if (BKE_object_defgroup_new(ob, name_flip)) {
mirrdef = BLI_listbase_count(&ob->defbase) - 1;
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 5663b109dc4..045fd54b46a 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2006 by Nicholas Bishop
@@ -24,24 +24,26 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_dial_2d.h"
-#include "BLI_gsqueue.h"
#include "BLI_ghash.h"
+#include "BLI_gsqueue.h"
#include "BLI_hash.h"
+#include "BLI_math.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
+#include "PIL_time.h"
+
+#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_brush_types.h"
#include "BKE_brush.h"
#include "BKE_ccg.h"
@@ -50,7 +52,7 @@
#include "BKE_image.h"
#include "BKE_kelvinlet.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
@@ -72,13 +74,13 @@
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
-#include "ED_sculpt.h"
#include "ED_object.h"
#include "ED_screen.h"
+#include "ED_sculpt.h"
#include "ED_view3d.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
@@ -104,7 +106,7 @@
* For multires, the same vertex in multiple grids is counted multiple times, with
* different index for each grid. */
-static void sculpt_vertex_random_access_init(SculptSession *ss)
+void SCULPT_vertex_random_access_init(SculptSession *ss)
{
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
@@ -112,7 +114,7 @@ static void sculpt_vertex_random_access_init(SculptSession *ss)
}
}
-static int sculpt_vertex_count_get(SculptSession *ss)
+int SCULPT_vertex_count_get(SculptSession *ss)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
@@ -126,11 +128,18 @@ static int sculpt_vertex_count_get(SculptSession *ss)
return 0;
}
-const float *sculpt_vertex_co_get(SculptSession *ss, int index)
+const float *SCULPT_vertex_co_get(SculptSession *ss, int index)
{
switch (BKE_pbvh_type(ss->pbvh)) {
- case PBVH_FACES:
- return ss->mvert[index].co;
+ case PBVH_FACES: {
+ if (ss->shapekey_active || ss->deform_modifiers_active) {
+ const MVert *mverts = BKE_pbvh_get_verts(ss->pbvh);
+ return mverts[index].co;
+ }
+ else {
+ return ss->mvert[index].co;
+ }
+ }
case PBVH_BMESH:
return BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co;
case PBVH_GRIDS: {
@@ -144,7 +153,7 @@ const float *sculpt_vertex_co_get(SculptSession *ss, int index)
return NULL;
}
-static void sculpt_vertex_normal_get(SculptSession *ss, int index, float no[3])
+void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
@@ -164,7 +173,7 @@ static void sculpt_vertex_normal_get(SculptSession *ss, int index, float no[3])
}
}
-static float sculpt_vertex_mask_get(SculptSession *ss, int index)
+float SCULPT_vertex_mask_get(SculptSession *ss, int index)
{
BMVert *v;
float *mask;
@@ -187,47 +196,359 @@ static float sculpt_vertex_mask_get(SculptSession *ss, int index)
return 0.0f;
}
-static int sculpt_active_vertex_get(SculptSession *ss)
+int SCULPT_active_vertex_get(SculptSession *ss)
+{
+ if (ELEM(BKE_pbvh_type(ss->pbvh), PBVH_FACES, PBVH_BMESH, PBVH_GRIDS)) {
+ return ss->active_vertex_index;
+ }
+ return 0;
+}
+
+const float *SCULPT_active_vertex_co_get(SculptSession *ss)
+{
+ return SCULPT_vertex_co_get(ss, SCULPT_active_vertex_get(ss));
+}
+
+void SCULPT_active_vertex_normal_get(SculptSession *ss, float normal[3])
+{
+ SCULPT_vertex_normal_get(ss, SCULPT_active_vertex_get(ss), normal);
+}
+
+/* Sculpt Face Sets and Visibility. */
+
+int SCULPT_active_face_set_get(SculptSession *ss)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
- return ss->active_vertex_index;
+ return ss->face_sets[ss->active_face_index];
+ case PBVH_GRIDS: {
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg,
+ ss->active_grid_index);
+ return ss->face_sets[face_index];
+ }
+ case PBVH_BMESH:
+ return SCULPT_FACE_SET_NONE;
+ }
+ return SCULPT_FACE_SET_NONE;
+}
+
+void SCULPT_vertex_visible_set(SculptSession *ss, int index, bool visible)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ SET_FLAG_FROM_TEST(ss->mvert[index].flag, !visible, ME_HIDE);
+ ss->mvert[index].flag |= ME_VERT_PBVH_UPDATE;
+ break;
case PBVH_BMESH:
- return ss->active_vertex_index;
+ BM_elem_flag_set(BM_vert_at_index(ss->bm, index), BM_ELEM_HIDDEN, !visible);
+ break;
case PBVH_GRIDS:
- return ss->active_vertex_index;
+ break;
}
+}
+bool SCULPT_vertex_visible_get(SculptSession *ss, int index)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ return !(ss->mvert[index].flag & ME_HIDE);
+ case PBVH_BMESH:
+ return !BM_elem_flag_test(BM_vert_at_index(ss->bm, index), BM_ELEM_HIDDEN);
+ case PBVH_GRIDS:
+ return true;
+ }
+ return true;
+}
+
+void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ case PBVH_GRIDS:
+ for (int i = 0; i < ss->totfaces; i++) {
+ if (abs(ss->face_sets[i]) == face_set) {
+ if (visible) {
+ ss->face_sets[i] = abs(ss->face_sets[i]);
+ }
+ else {
+ ss->face_sets[i] = -abs(ss->face_sets[i]);
+ }
+ }
+ }
+ break;
+ case PBVH_BMESH:
+ break;
+ }
+}
+
+void SCULPT_face_sets_visibility_invert(SculptSession *ss)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ case PBVH_GRIDS:
+ for (int i = 0; i < ss->totfaces; i++) {
+ ss->face_sets[i] *= -1;
+ }
+ break;
+ case PBVH_BMESH:
+ break;
+ }
+}
+
+void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ case PBVH_GRIDS:
+ for (int i = 0; i < ss->totfaces; i++) {
+
+ /* This can run on geometry without a face set assigned, so its ID sign can't be changed to
+ * modify the visibility. Force that geometry to the ID 1 to enable changing the visibility
+ * here. */
+ if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) {
+ ss->face_sets[i] = 1;
+ }
+
+ if (visible) {
+ ss->face_sets[i] = abs(ss->face_sets[i]);
+ }
+ else {
+ ss->face_sets[i] = -abs(ss->face_sets[i]);
+ }
+ }
+ break;
+ case PBVH_BMESH:
+ break;
+ }
+}
+
+bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, int index)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES: {
+ MeshElemMap *vert_map = &ss->pmap[index];
+ for (int j = 0; j < ss->pmap[index].count; j++) {
+ if (ss->face_sets[vert_map->indices[j]] > 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+ case PBVH_BMESH:
+ return true;
+ case PBVH_GRIDS:
+ return true;
+ }
+ return true;
+}
+
+bool SCULPT_vertex_all_face_sets_visible_get(SculptSession *ss, int index)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES: {
+ MeshElemMap *vert_map = &ss->pmap[index];
+ for (int j = 0; j < ss->pmap[index].count; j++) {
+ if (ss->face_sets[vert_map->indices[j]] < 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+ case PBVH_BMESH:
+ return true;
+ case PBVH_GRIDS: {
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
+ return ss->face_sets[face_index] > 0;
+ }
+ }
+ return true;
+}
+
+void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_set)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES: {
+ MeshElemMap *vert_map = &ss->pmap[index];
+ for (int j = 0; j < ss->pmap[index].count; j++) {
+ if (ss->face_sets[vert_map->indices[j]] > 0) {
+ ss->face_sets[vert_map->indices[j]] = abs(face_set);
+ }
+ }
+ } break;
+ case PBVH_BMESH:
+ break;
+ case PBVH_GRIDS: {
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
+ if (ss->face_sets[face_index] > 0) {
+ ss->face_sets[face_index] = abs(face_set);
+ }
+
+ } break;
+ }
+}
+
+int SCULPT_vertex_face_set_get(SculptSession *ss, int index)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES: {
+ MeshElemMap *vert_map = &ss->pmap[index];
+ int face_set = 0;
+ for (int i = 0; i < ss->pmap[index].count; i++) {
+ if (ss->face_sets[vert_map->indices[i]] > face_set) {
+ face_set = abs(ss->face_sets[vert_map->indices[i]]);
+ }
+ }
+ return face_set;
+ }
+ case PBVH_BMESH:
+ return 0;
+ case PBVH_GRIDS: {
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
+ return ss->face_sets[face_index];
+ }
+ }
return 0;
}
-static const float *sculpt_active_vertex_co_get(SculptSession *ss)
+bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES: {
+ MeshElemMap *vert_map = &ss->pmap[index];
+ for (int i = 0; i < ss->pmap[index].count; i++) {
+ if (ss->face_sets[vert_map->indices[i]] == face_set) {
+ return true;
+ }
+ }
+ return false;
+ }
+ case PBVH_BMESH:
+ return true;
+ case PBVH_GRIDS: {
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
+ return ss->face_sets[face_index] == face_set;
+ }
+ }
+ return true;
+}
+
+static void sculpt_visibility_sync_face_sets_to_vertex(SculptSession *ss, int index)
{
- return sculpt_vertex_co_get(ss, sculpt_active_vertex_get(ss));
+ SCULPT_vertex_visible_set(ss, index, SCULPT_vertex_any_face_set_visible_get(ss, index));
}
-static void sculpt_active_vertex_normal_get(SculptSession *ss, float normal[3])
+void SCULPT_visibility_sync_all_face_sets_to_vertices(SculptSession *ss)
{
- sculpt_vertex_normal_get(ss, sculpt_active_vertex_get(ss), normal);
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES: {
+ for (int i = 0; i < ss->totvert; i++) {
+ sculpt_visibility_sync_face_sets_to_vertex(ss, i);
+ }
+ break;
+ }
+ case PBVH_GRIDS: {
+ BKE_pbvh_sync_face_sets_to_grids(ss->pbvh);
+ }
+ case PBVH_BMESH:
+ break;
+ }
}
-#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
+static void UNUSED_FUNCTION(sculpt_visibility_sync_vertex_to_face_sets)(SculptSession *ss,
+ int index)
+{
+ MeshElemMap *vert_map = &ss->pmap[index];
+ const bool visible = SCULPT_vertex_visible_get(ss, index);
+ for (int i = 0; i < ss->pmap[index].count; i++) {
+ if (visible) {
+ ss->face_sets[vert_map->indices[i]] = abs(ss->face_sets[vert_map->indices[i]]);
+ }
+ else {
+ ss->face_sets[vert_map->indices[i]] = -abs(ss->face_sets[vert_map->indices[i]]);
+ }
+ }
+ ss->mvert[index].flag |= ME_VERT_PBVH_UPDATE;
+}
-typedef struct SculptVertexNeighborIter {
- /* Storage */
- int *neighbors;
- int size;
- int capacity;
- int neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
+void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss)
+{
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
+ for (int i = 0; i < ss->totfaces; i++) {
+ MPoly *poly = &ss->mpoly[i];
+ bool poly_visible = true;
+ for (int l = 0; l < poly->totloop; l++) {
+ MLoop *loop = &ss->mloop[poly->loopstart + l];
+ if (!SCULPT_vertex_visible_get(ss, (int)loop->v)) {
+ poly_visible = false;
+ }
+ }
+ if (poly_visible) {
+ ss->face_sets[i] = abs(ss->face_sets[i]);
+ }
+ else {
+ ss->face_sets[i] = -abs(ss->face_sets[i]);
+ }
+ }
+ }
+}
- /* Internal iterator. */
- int num_duplicates;
- int i;
+bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES: {
+ MeshElemMap *vert_map = &ss->pmap[index];
+ int face_set = -1;
+ for (int i = 0; i < ss->pmap[index].count; i++) {
+ if (face_set == -1) {
+ face_set = abs(ss->face_sets[vert_map->indices[i]]);
+ }
+ else {
+ if (abs(ss->face_sets[vert_map->indices[i]]) != face_set) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ case PBVH_BMESH:
+ return false;
+ case PBVH_GRIDS:
+ return true;
+ }
+ return false;
+}
- /* Public */
- int index;
- bool is_duplicate;
-} SculptVertexNeighborIter;
+int SCULPT_face_set_next_available_get(SculptSession *ss)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ case PBVH_GRIDS: {
+ int next_face_set = 0;
+ for (int i = 0; i < ss->totfaces; i++) {
+ if (abs(ss->face_sets[i]) > next_face_set) {
+ next_face_set = abs(ss->face_sets[i]);
+ }
+ }
+ next_face_set++;
+ return next_face_set;
+ }
+ case PBVH_BMESH:
+ return 0;
+ }
+ return 0;
+}
+
+/* Sculpt Neighbor Iterators */
+
+#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter, int neighbor_index)
{
@@ -266,10 +587,9 @@ static void sculpt_vertex_neighbors_get_bmesh(SculptSession *ss,
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
- int i = 0;
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
const BMVert *adj_v[2] = {l->prev->v, l->next->v};
- for (i = 0; i < ARRAY_SIZE(adj_v); i++) {
+ for (int i = 0; i < ARRAY_SIZE(adj_v); i++) {
const BMVert *v_other = adj_v[i];
if (BM_elem_index_get(v_other) != (int)index) {
sculpt_vertex_neighbor_add(iter, BM_elem_index_get(v_other));
@@ -282,20 +602,18 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
int index,
SculptVertexNeighborIter *iter)
{
- int i;
- MeshElemMap *vert_map = &ss->pmap[(int)index];
+ MeshElemMap *vert_map = &ss->pmap[index];
iter->size = 0;
iter->num_duplicates = 0;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
- for (i = 0; i < ss->pmap[(int)index].count; i++) {
+ for (int i = 0; i < ss->pmap[index].count; i++) {
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
- unsigned f_adj_v[2];
- if (poly_get_adj_loops_from_vert(p, ss->mloop, (int)index, f_adj_v) != -1) {
- int j;
- for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
- if (f_adj_v[j] != (int)index) {
+ uint f_adj_v[2];
+ if (poly_get_adj_loops_from_vert(p, ss->mloop, index, f_adj_v) != -1) {
+ for (int j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
+ if (f_adj_v[j] != index) {
sculpt_vertex_neighbor_add(iter, f_adj_v[j]);
}
}
@@ -338,10 +656,10 @@ static void sculpt_vertex_neighbors_get_grids(SculptSession *ss,
}
}
-static void sculpt_vertex_neighbors_get(SculptSession *ss,
- const int index,
- const bool include_duplicates,
- SculptVertexNeighborIter *iter)
+void SCULPT_vertex_neighbors_get(SculptSession *ss,
+ const int index,
+ const bool include_duplicates,
+ SculptVertexNeighborIter *iter)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
@@ -356,32 +674,48 @@ static void sculpt_vertex_neighbors_get(SculptSession *ss,
}
}
-/* Iterator over neighboring vertices. */
-#define sculpt_vertex_neighbors_iter_begin(ss, v_index, neighbor_iterator) \
- sculpt_vertex_neighbors_get(ss, v_index, false, &neighbor_iterator); \
- for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \
- neighbor_iterator.i++) { \
- neighbor_iterator.index = ni.neighbors[ni.i];
+bool SCULPT_vertex_is_boundary(SculptSession *ss, const int index)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES: {
+ const MeshElemMap *vert_map = &ss->pmap[index];
-/* Iterate over neighboring and duplicate vertices (for PBVH_GRIDS). Duplicates come
- * first since they are nearest for floodfill. */
-#define sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, v_index, neighbor_iterator) \
- sculpt_vertex_neighbors_get(ss, v_index, true, &neighbor_iterator); \
- for (neighbor_iterator.i = neighbor_iterator.size - 1; neighbor_iterator.i >= 0; \
- neighbor_iterator.i--) { \
- neighbor_iterator.index = ni.neighbors[ni.i]; \
- neighbor_iterator.is_duplicate = (ni.i >= \
- neighbor_iterator.size - neighbor_iterator.num_duplicates);
+ if (vert_map->count <= 1) {
+ return false;
+ }
-#define sculpt_vertex_neighbors_iter_end(neighbor_iterator) \
- } \
- if (neighbor_iterator.neighbors != neighbor_iterator.neighbors_fixed) { \
- MEM_freeN(neighbor_iterator.neighbors); \
- } \
- ((void)0)
+ if (!SCULPT_vertex_all_face_sets_visible_get(ss, index)) {
+ return false;
+ }
+
+ for (int i = 0; i < vert_map->count; i++) {
+ const MPoly *p = &ss->mpoly[vert_map->indices[i]];
+ unsigned f_adj_v[2];
+ if (poly_get_adj_loops_from_vert(p, ss->mloop, index, f_adj_v) != -1) {
+ int j;
+ for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
+ if (!(vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ case PBVH_BMESH: {
+ BMVert *v = BM_vert_at_index(ss->bm, index);
+ return BM_vert_is_boundary(v);
+ }
+
+ case PBVH_GRIDS:
+ return true;
+ }
+
+ return true;
+}
/* Utils */
-static bool check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
+bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
{
bool is_in_symmetry_area = true;
for (int i = 0; i < 3; i++) {
@@ -442,7 +776,7 @@ static void nearest_vertex_get_reduce(const void *__restrict UNUSED(userdata),
}
}
-static int sculpt_nearest_vertex_get(
+int SCULPT_nearest_vertex_get(
Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original)
{
SculptSession *ss = ob->sculpt;
@@ -455,7 +789,7 @@ static int sculpt_nearest_vertex_get(
.original = use_original,
.center = co,
};
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
if (totnode == 0) {
return -1;
}
@@ -472,31 +806,31 @@ static int sculpt_nearest_vertex_get(
nvtd.nearest_vertex_index = -1;
nvtd.nearest_vertex_distance_squared = FLT_MAX;
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
settings.func_reduce = nearest_vertex_get_reduce;
settings.userdata_chunk = &nvtd;
settings.userdata_chunk_size = sizeof(NearestVertexTLSData);
- BKE_pbvh_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings);
MEM_SAFE_FREE(nodes);
return nvtd.nearest_vertex_index;
}
-static bool is_symmetry_iteration_valid(char i, char symm)
+bool SCULPT_is_symmetry_iteration_valid(char i, char symm)
{
return i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)));
}
-/* Checks if a vertex is inside the brush radius from any of its mirrored axis */
-static bool sculpt_is_vertex_inside_brush_radius_symm(const float vertex[3],
- const float br_co[3],
- float radius,
- char symm)
+/* Checks if a vertex is inside the brush radius from any of its mirrored axis. */
+bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3],
+ const float br_co[3],
+ float radius,
+ char symm)
{
for (char i = 0; i <= symm; ++i) {
- if (is_symmetry_iteration_valid(i, symm)) {
+ if (SCULPT_is_symmetry_iteration_valid(i, symm)) {
float location[3];
flip_v3_v3(location, br_co, (char)i);
if (len_squared_v3v3(location, vertex) < radius * radius) {
@@ -511,50 +845,69 @@ static bool sculpt_is_vertex_inside_brush_radius_symm(const float vertex[3],
*
* Iterate over connected vertices, starting from one or more initial vertices. */
-typedef struct SculptFloodFill {
- GSQueue *queue;
- char *visited_vertices;
-} SculptFloodFill;
-
-static void sculpt_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
+void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
{
- int vertex_count = sculpt_vertex_count_get(ss);
- sculpt_vertex_random_access_init(ss);
+ int vertex_count = SCULPT_vertex_count_get(ss);
+ SCULPT_vertex_random_access_init(ss);
flood->queue = BLI_gsqueue_new(sizeof(int));
flood->visited_vertices = MEM_callocN(vertex_count * sizeof(char), "visited vertices");
}
-static void sculpt_floodfill_add_initial(SculptFloodFill *flood, int index)
+void SCULPT_floodfill_add_initial(SculptFloodFill *flood, int index)
{
BLI_gsqueue_push(flood->queue, &index);
}
-static void sculpt_floodfill_add_active(
+void SCULPT_floodfill_add_initial_with_symmetry(
+ Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, int index, float radius)
+{
+ /* Add active vertex and symmetric vertices to the queue. */
+ const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ for (char i = 0; i <= symm; ++i) {
+ if (SCULPT_is_symmetry_iteration_valid(i, symm)) {
+ int v = -1;
+ if (i == 0) {
+ v = index;
+ }
+ else if (radius > 0.0f) {
+ float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius;
+ float location[3];
+ flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i);
+ v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false);
+ }
+ if (v != -1) {
+ SCULPT_floodfill_add_initial(flood, v);
+ }
+ }
+ }
+}
+
+void SCULPT_floodfill_add_active(
Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, float radius)
{
/* Add active vertex and symmetric vertices to the queue. */
const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
for (char i = 0; i <= symm; ++i) {
- if (is_symmetry_iteration_valid(i, symm)) {
+ if (SCULPT_is_symmetry_iteration_valid(i, symm)) {
int v = -1;
if (i == 0) {
- v = sculpt_active_vertex_get(ss);
+ v = SCULPT_active_vertex_get(ss);
}
else if (radius > 0.0f) {
float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius;
float location[3];
- flip_v3_v3(location, sculpt_active_vertex_co_get(ss), i);
- v = sculpt_nearest_vertex_get(sd, ob, location, radius_squared, false);
+ flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), i);
+ v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false);
}
if (v != -1) {
- sculpt_floodfill_add_initial(flood, v);
+ SCULPT_floodfill_add_initial(flood, v);
}
}
}
}
-static void sculpt_floodfill_execute(
+void SCULPT_floodfill_execute(
SculptSession *ss,
SculptFloodFill *flood,
bool (*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata),
@@ -564,10 +917,9 @@ static void sculpt_floodfill_execute(
int from_v;
BLI_gsqueue_pop(flood->queue, &from_v);
SculptVertexNeighborIter ni;
- sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, from_v, ni)
- {
+ SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) {
const int to_v = ni.index;
- if (flood->visited_vertices[to_v] == 0) {
+ if (flood->visited_vertices[to_v] == 0 && SCULPT_vertex_visible_get(ss, to_v)) {
flood->visited_vertices[to_v] = 1;
if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) {
@@ -575,11 +927,11 @@ static void sculpt_floodfill_execute(
}
}
}
- sculpt_vertex_neighbors_iter_end(ni);
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
}
}
-static void sculpt_floodfill_free(SculptFloodFill *flood)
+void SCULPT_floodfill_free(SculptFloodFill *flood)
{
MEM_SAFE_FREE(flood->visited_vertices);
BLI_gsqueue_free(flood->queue);
@@ -593,23 +945,23 @@ static void sculpt_floodfill_free(SculptFloodFill *flood)
*
* \{ */
-/* Check if there are any active modifiers in stack
- * (used for flushing updates at enter/exit sculpt mode) */
+/* Check if there are any active modifiers in stack.
+ * Used for flushing updates at enter/exit sculpt mode. */
static bool sculpt_has_active_modifiers(Scene *scene, Object *ob)
{
ModifierData *md;
VirtualModifierData virtualModifierData;
- md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
- /* exception for shape keys because we can edit those */
+ /* Exception for shape keys because we can edit those. */
for (; md; md = md->next) {
- if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
- return 1;
+ if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) {
+ return true;
}
}
- return 0;
+ return false;
}
static bool sculpt_tool_needs_original(const char sculpt_tool)
@@ -621,12 +973,18 @@ static bool sculpt_tool_needs_original(const char sculpt_tool)
SCULPT_TOOL_LAYER,
SCULPT_TOOL_DRAW_SHARP,
SCULPT_TOOL_ELASTIC_DEFORM,
+ SCULPT_TOOL_SMOOTH,
SCULPT_TOOL_POSE);
}
static bool sculpt_tool_is_proxy_used(const char sculpt_tool)
{
- return ELEM(sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER, SCULPT_TOOL_POSE);
+ return ELEM(sculpt_tool,
+ SCULPT_TOOL_SMOOTH,
+ SCULPT_TOOL_LAYER,
+ SCULPT_TOOL_POSE,
+ SCULPT_TOOL_CLOTH,
+ SCULPT_TOOL_DRAW_FACE_SETS);
}
static bool sculpt_brush_use_topology_rake(const SculptSession *ss, const Brush *brush)
@@ -648,6 +1006,7 @@ static int sculpt_brush_needs_normal(const SculptSession *ss, const Brush *brush
SCULPT_TOOL_CREASE,
SCULPT_TOOL_DRAW,
SCULPT_TOOL_DRAW_SHARP,
+ SCULPT_TOOL_CLOTH,
SCULPT_TOOL_LAYER,
SCULPT_TOOL_NUDGE,
SCULPT_TOOL_ROTATE,
@@ -670,24 +1029,8 @@ typedef enum StrokeFlags {
CLIP_Z = 4,
} StrokeFlags;
-/************** Access to original unmodified vertex data *************/
-
-typedef struct {
- BMLog *bm_log;
-
- SculptUndoNode *unode;
- float (*coords)[3];
- short (*normals)[3];
- const float *vmasks;
-
- /* Original coordinate, normal, and mask */
- const float *co;
- const short *no;
- float mask;
-} SculptOrigVertData;
-
/* Initialize a SculptOrigVertData for accessing original vertex data;
- * handles BMesh, mesh, and multires */
+ * handles BMesh, mesh, and multires. */
static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data,
Object *ob,
SculptUndoNode *unode)
@@ -709,17 +1052,17 @@ static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data,
}
/* Initialize a SculptOrigVertData for accessing original vertex data;
- * handles BMesh, mesh, and multires */
-static void sculpt_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node)
+ * handles BMesh, mesh, and multires. */
+void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node)
{
SculptUndoNode *unode;
- unode = sculpt_undo_push_node(ob, node, SCULPT_UNDO_COORDS);
+ unode = SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COORDS);
sculpt_orig_vert_data_unode_init(data, ob, unode);
}
/* Update a SculptOrigVertData for a particular vertex from the PBVH
- * iterator */
-static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
+ * iterator. */
+void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
{
if (orig_data->unode->type == SCULPT_UNDO_COORDS) {
if (orig_data->bm_log) {
@@ -786,10 +1129,10 @@ static void sculpt_project_v3_normal_align(SculptSession *ss,
const float normal_weight,
float grab_delta[3])
{
- /* signed to support grabbing in (to make a hole) as well as out. */
+ /* Signed to support grabbing in (to make a hole) as well as out. */
const float len_signed = dot_v3v3(ss->cache->sculpt_normal_symm, grab_delta);
- /* this scale effectively projects the offset so dragging follows the cursor,
+ /* This scale effectively projects the offset so dragging follows the cursor,
* as the normal points towards the view, the scale increases. */
float len_view_scale;
{
@@ -853,14 +1196,14 @@ static void sculpt_project_v3(const SculptProjectVector *spvc, const float vec[3
* Factors: some brushes like grab cannot do dynamic topology.
* Others, like smooth, are better without. Same goes for alt-
* key smoothing. */
-static bool sculpt_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush)
+bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush)
{
return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
(!ss->cache || (!ss->cache->alt_smooth)) &&
/* Requires mesh restore, which doesn't work with
- * dynamic-topology */
+ * dynamic-topology. */
!(brush->flag & BRUSH_ANCHORED) && !(brush->flag & BRUSH_DRAG_DOT) &&
SCULPT_TOOL_HAS_DYNTOPO(brush->sculpt_tool));
@@ -880,10 +1223,10 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
SCULPT_UNDO_COORDS);
if (ss->bm) {
- unode = sculpt_undo_push_node(data->ob, data->nodes[n], type);
+ unode = SCULPT_undo_push_node(data->ob, data->nodes[n], type);
}
else {
- unode = sculpt_undo_get_node(data->nodes[n]);
+ unode = SCULPT_undo_get_node(data->nodes[n]);
}
if (unode) {
@@ -894,7 +1237,7 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
if (orig_data.unode->type == SCULPT_UNDO_COORDS) {
copy_v3_v3(vd.co, orig_data.co);
@@ -940,9 +1283,9 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
.nodes = nodes,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP) && !ss->bm, totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings);
MEM_SAFE_FREE(nodes);
}
@@ -951,12 +1294,12 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect)
{
- /* expand redraw rect with redraw rect from previous step to
+ /* Expand redraw rect with redraw rect from previous step to
* prevent partial-redraw issues caused by fast strokes. This is
* needed here (not in sculpt_flush_update) as it was before
* because redraw rectangle should be the same in both of
* optimized PBVH draw function and 3d view redraw (if not -- some
- * mesh parts could disappear from screen (sergey) */
+ * mesh parts could disappear from screen (sergey). */
SculptSession *ss = ob->sculpt;
if (ss->cache) {
@@ -966,43 +1309,43 @@ static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect)
}
}
-/* Get a screen-space rectangle of the modified area */
-bool sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d, Object *ob, rcti *rect)
+/* Get a screen-space rectangle of the modified area. */
+bool SCULPT_get_redraw_rect(ARegion *region, RegionView3D *rv3d, Object *ob, rcti *rect)
{
PBVH *pbvh = ob->sculpt->pbvh;
float bb_min[3], bb_max[3];
if (!pbvh) {
- return 0;
+ return false;
}
BKE_pbvh_redraw_BB(pbvh, bb_min, bb_max);
- /* convert 3D bounding box to screen space */
- if (!paint_convert_bb_to_rect(rect, bb_min, bb_max, ar, rv3d, ob)) {
- return 0;
+ /* Convert 3D bounding box to screen space. */
+ if (!paint_convert_bb_to_rect(rect, bb_min, bb_max, region, rv3d, ob)) {
+ return false;
}
- return 1;
+ return true;
}
-void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob)
+void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *region, Object *ob)
{
PBVH *pbvh = ob->sculpt->pbvh;
- /* copy here, original will be used below */
+ /* Copy here, original will be used below. */
rcti rect = ob->sculpt->cache->current_r;
sculpt_extend_redraw_rect_previous(ob, &rect);
- paint_calc_redraw_planes(planes, ar, ob, &rect);
+ paint_calc_redraw_planes(planes, region, ob, &rect);
- /* we will draw this rect, so now we can set it as the previous partial rect.
+ /* We will draw this rect, so now we can set it as the previous partial rect.
* Note that we don't update with the union of previous/current (rect), only with
* the current. Thus we avoid the rectangle needlessly growing to include
- * all the stroke area */
+ * all the stroke area. */
ob->sculpt->cache->previous_r = ob->sculpt->cache->current_r;
- /* clear redraw flag from nodes */
+ /* Clear redraw flag from nodes. */
if (pbvh) {
BKE_pbvh_update_bounds(pbvh, PBVH_UpdateRedraw);
}
@@ -1010,13 +1353,15 @@ void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob)
/************************ Brush Testing *******************/
-void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
+void SCULPT_brush_test_init(SculptSession *ss, SculptBrushTest *test)
{
RegionView3D *rv3d = ss->cache ? ss->cache->vc->rv3d : ss->rv3d;
View3D *v3d = ss->cache ? ss->cache->vc->v3d : ss->v3d;
test->radius_squared = ss->cache ? ss->cache->radius_squared :
ss->cursor_radius * ss->cursor_radius;
+ test->radius = sqrtf(test->radius_squared);
+
if (ss->cache) {
copy_v3_v3(test->location, ss->cache->location);
test->mirror_symmetry_pass = ss->cache->mirror_symmetry_pass;
@@ -1026,7 +1371,8 @@ void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
test->mirror_symmetry_pass = 0;
}
- test->dist = 0.0f; /* just for initialize */
+ /* Just for initialize. */
+ test->dist = 0.0f;
/* Only for 2D projection. */
zero_v4(test->plane_view);
@@ -1053,47 +1399,47 @@ BLI_INLINE bool sculpt_brush_test_clipping(const SculptBrushTest *test, const fl
return ED_view3d_clipping_test(rv3d, symm_co, true);
}
-bool sculpt_brush_test_sphere(SculptBrushTest *test, const float co[3])
+bool SCULPT_brush_test_sphere(SculptBrushTest *test, const float co[3])
{
float distsq = len_squared_v3v3(co, test->location);
if (distsq <= test->radius_squared) {
if (sculpt_brush_test_clipping(test, co)) {
- return 0;
+ return false;
}
test->dist = sqrtf(distsq);
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
-bool sculpt_brush_test_sphere_sq(SculptBrushTest *test, const float co[3])
+bool SCULPT_brush_test_sphere_sq(SculptBrushTest *test, const float co[3])
{
float distsq = len_squared_v3v3(co, test->location);
if (distsq <= test->radius_squared) {
if (sculpt_brush_test_clipping(test, co)) {
- return 0;
+ return false;
}
test->dist = distsq;
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
-bool sculpt_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3])
+bool SCULPT_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3])
{
if (sculpt_brush_test_clipping(test, co)) {
- return 0;
+ return false;
}
return len_squared_v3v3(co, test->location) <= test->radius_squared;
}
-bool sculpt_brush_test_circle_sq(SculptBrushTest *test, const float co[3])
+bool SCULPT_brush_test_circle_sq(SculptBrushTest *test, const float co[3])
{
float co_proj[3];
closest_to_plane_normalized_v3(co_proj, test->plane_view, co);
@@ -1101,23 +1447,26 @@ bool sculpt_brush_test_circle_sq(SculptBrushTest *test, const float co[3])
if (distsq <= test->radius_squared) {
if (sculpt_brush_test_clipping(test, co)) {
- return 0;
+ return false;
}
test->dist = distsq;
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
-bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float local[4][4])
+bool SCULPT_brush_test_cube(SculptBrushTest *test,
+ const float co[3],
+ const float local[4][4],
+ const float roundness)
{
float side = M_SQRT1_2;
float local_co[3];
if (sculpt_brush_test_clipping(test, co)) {
- return 0;
+ return false;
}
mul_v3_m4v3(local_co, local, co);
@@ -1126,36 +1475,54 @@ bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float loca
local_co[1] = fabsf(local_co[1]);
local_co[2] = fabsf(local_co[2]);
- const float p = 8.0f;
- if (local_co[0] <= side && local_co[1] <= side && local_co[2] <= side) {
- test->dist = ((powf(local_co[0], p) + powf(local_co[1], p) + powf(local_co[2], p)) /
- powf(side, p));
+ /* Keep the square and circular brush tips the same size. */
+ side += (1.0f - side) * roundness;
- return 1;
+ const float hardness = 1.0f - roundness;
+ const float constant_side = hardness * side;
+ const float falloff_side = roundness * side;
+
+ if (local_co[0] <= side && local_co[1] <= side && local_co[2] <= side) {
+ /* Corner, distance to the center of the corner circle. */
+ if (min_ff(local_co[0], local_co[1]) > constant_side) {
+ float r_point[3];
+ copy_v3_fl(r_point, constant_side);
+ test->dist = len_v2v2(r_point, local_co) / falloff_side;
+ return true;
+ }
+ /* Side, distance to the square XY axis. */
+ if (max_ff(local_co[0], local_co[1]) > constant_side) {
+ test->dist = (max_ff(local_co[0], local_co[1]) - constant_side) / falloff_side;
+ return true;
+ }
+ /* Inside the square, constant distance. */
+ test->dist = 0.0f;
+ return true;
}
else {
- return 0;
+ /* Outside the square. */
+ return false;
}
}
-SculptBrushTestFn sculpt_brush_test_init_with_falloff_shape(SculptSession *ss,
+SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss,
SculptBrushTest *test,
char falloff_shape)
{
- sculpt_brush_test_init(ss, test);
+ SCULPT_brush_test_init(ss, test);
SculptBrushTestFn sculpt_brush_test_sq_fn;
if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
- sculpt_brush_test_sq_fn = sculpt_brush_test_sphere_sq;
+ sculpt_brush_test_sq_fn = SCULPT_brush_test_sphere_sq;
}
else {
/* PAINT_FALLOFF_SHAPE_TUBE */
plane_from_point_normal_v3(test->plane_view, test->location, ss->cache->view_normal);
- sculpt_brush_test_sq_fn = sculpt_brush_test_circle_sq;
+ sculpt_brush_test_sq_fn = SCULPT_brush_test_circle_sq;
}
return sculpt_brush_test_sq_fn;
}
-const float *sculpt_brush_frontface_normal_from_falloff_shape(SculptSession *ss,
+const float *SCULPT_brush_frontface_normal_from_falloff_shape(SculptSession *ss,
char falloff_shape)
{
if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
@@ -1184,10 +1551,10 @@ static float frontface(const Brush *br,
else {
dot = dot_v3v3(fno, sculpt_normal);
}
- return dot > 0 ? dot : 0;
+ return dot > 0.0f ? dot : 0.0f;
}
else {
- return 1;
+ return 1.0f;
}
}
@@ -1218,116 +1585,6 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test,
#endif
-/* Automasking */
-
-static bool sculpt_automasking_enabled(SculptSession *ss, const Brush *br)
-{
- if (sculpt_stroke_is_dynamic_topology(ss, br)) {
- return false;
- }
- if (br->automasking_flags & BRUSH_AUTOMASKING_TOPOLOGY) {
- return true;
- }
- return false;
-}
-
-static float sculpt_automasking_factor_get(SculptSession *ss, int vert)
-{
- if (ss->cache->automask) {
- return ss->cache->automask[vert];
- }
- else {
- return 1.0f;
- }
-}
-
-static void sculpt_automasking_end(Object *ob)
-{
- SculptSession *ss = ob->sculpt;
- if (ss->cache && ss->cache->automask) {
- MEM_freeN(ss->cache->automask);
- }
-}
-
-static bool sculpt_automasking_is_constrained_by_radius(Brush *br)
-{
- /* 2D falloff is not constrained by radius */
- if (br->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
- return false;
- }
-
- if (ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE)) {
- return true;
- }
- return false;
-}
-
-typedef struct AutomaskFloodFillData {
- float *automask_factor;
- float radius;
- bool use_radius;
- float location[3];
- char symm;
-} AutomaskFloodFillData;
-
-static bool automask_floodfill_cb(
- SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata)
-{
- AutomaskFloodFillData *data = userdata;
-
- data->automask_factor[to_v] = 1.0f;
- return (!data->use_radius ||
- sculpt_is_vertex_inside_brush_radius_symm(
- sculpt_vertex_co_get(ss, to_v), data->location, data->radius, data->symm));
-}
-
-static float *sculpt_topology_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
-{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- if (!sculpt_automasking_enabled(ss, brush)) {
- return NULL;
- }
-
- if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
- BLI_assert(!"Topology masking: pmap missing");
- return NULL;
- }
-
- /* Flood fill automask to connected vertices. Limited to vertices inside
- * the brush radius if the tool requires it */
- SculptFloodFill flood;
- sculpt_floodfill_init(ss, &flood);
- sculpt_floodfill_add_active(sd, ob, ss, &flood, ss->cache->radius);
-
- AutomaskFloodFillData fdata = {
- .automask_factor = automask_factor,
- .radius = ss->cache->radius,
- .use_radius = sculpt_automasking_is_constrained_by_radius(brush),
- .symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL,
- };
- copy_v3_v3(fdata.location, sculpt_active_vertex_co_get(ss));
- sculpt_floodfill_execute(ss, &flood, automask_floodfill_cb, &fdata);
- sculpt_floodfill_free(&flood);
-
- return automask_factor;
-}
-
-static void sculpt_automasking_init(Sculpt *sd, Object *ob)
-{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- ss->cache->automask = MEM_callocN(sizeof(float) * sculpt_vertex_count_get(ss),
- "automask_factor");
-
- if (brush->automasking_flags & BRUSH_AUTOMASKING_TOPOLOGY) {
- sculpt_vertex_random_access_init(ss);
- sculpt_topology_automasking_init(sd, ob, ss->cache->automask);
- }
-}
-
/* ===== Sculpting =====
*/
static void flip_v3(float v[3], const ePaintSymmetryFlags symm)
@@ -1345,7 +1602,6 @@ static float calc_overlap(StrokeCache *cache, const char symm, const char axis,
float mirror[3];
float distsq;
- /* flip_v3_v3(mirror, cache->traced_location, symm); */
flip_v3_v3(mirror, cache->true_location, symm);
if (axis != 0) {
@@ -1354,14 +1610,13 @@ static float calc_overlap(StrokeCache *cache, const char symm, const char axis,
mul_m3_v3(mat, mirror);
}
- /* distsq = len_squared_v3v3(mirror, cache->traced_location); */
distsq = len_squared_v3v3(mirror, cache->true_location);
if (distsq <= 4.0f * (cache->radius_squared)) {
return (2.0f * (cache->radius) - sqrtf(distsq)) / (2.0f * (cache->radius));
}
else {
- return 0;
+ return 0.0f;
}
}
@@ -1370,12 +1625,10 @@ static float calc_radial_symmetry_feather(Sculpt *sd,
const char symm,
const char axis)
{
- int i;
- float overlap;
+ float overlap = 0.0f;
- overlap = 0;
- for (i = 1; i < sd->radial_symm[axis - 'X']; i++) {
- const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X'];
+ for (int i = 1; i < sd->radial_symm[axis - 'X']; i++) {
+ const float angle = 2.0f * M_PI * i / sd->radial_symm[axis - 'X'];
overlap += calc_overlap(cache, symm, axis, angle);
}
@@ -1386,11 +1639,10 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
{
if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) {
float overlap;
- int symm = cache->symmetry;
- int i;
+ const int symm = cache->symmetry;
- overlap = 0;
- for (i = 0; i <= symm; i++) {
+ overlap = 0.0f;
+ for (int i = 0; i <= symm; i++) {
if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) {
overlap += calc_overlap(cache, i, 0, 0);
@@ -1401,10 +1653,10 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
}
}
- return 1 / overlap;
+ return 1.0f / overlap;
}
else {
- return 1;
+ return 1.0f;
}
}
@@ -1422,10 +1674,11 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
* \{ */
typedef struct AreaNormalCenterTLSData {
- /* 0=towards view, 1=flipped */
+ /* 0 = towards view, 1 = flipped */
float area_cos[2][3];
float area_nos[2][3];
- int area_count[2];
+ int count_no[2];
+ int count_co[2];
} AreaNormalCenterTLSData;
static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
@@ -1442,37 +1695,54 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
SculptUndoNode *unode = NULL;
bool use_original = false;
+ bool normal_test_r, area_test_r;
if (ss->cache && ss->cache->original) {
- unode = sculpt_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
+ unode = SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
use_original = (unode->co || unode->bm_entry);
}
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
- ss, &test, data->brush->falloff_shape);
+ SculptBrushTest normal_test;
+ SculptBrushTestFn sculpt_brush_normal_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &normal_test, data->brush->falloff_shape);
- /* Update the test radius to sample the normal using the normal radius of the brush */
+ /* Update the test radius to sample the normal using the normal radius of the brush. */
if (data->brush->ob_mode == OB_MODE_SCULPT) {
- float test_radius = sqrtf(test.radius_squared);
- /* Layer brush produces artifacts with normal radius */
- if (!(ss->cache && data->brush->sculpt_tool == SCULPT_TOOL_LAYER)) {
+ float test_radius = sqrtf(normal_test.radius_squared);
+ test_radius *= data->brush->normal_radius_factor;
+ normal_test.radius = test_radius;
+ normal_test.radius_squared = test_radius * test_radius;
+ }
+
+ SculptBrushTest area_test;
+ SculptBrushTestFn sculpt_brush_area_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &area_test, data->brush->falloff_shape);
+
+ if (data->brush->ob_mode == OB_MODE_SCULPT) {
+ float test_radius = sqrtf(area_test.radius_squared);
+ /* Layer brush produces artifacts with normal and area radius */
+ /* Enable area radius control only on Scrape for now */
+ if (ELEM(data->brush->sculpt_tool, SCULPT_TOOL_SCRAPE, SCULPT_TOOL_FILL) &&
+ data->brush->area_radius_factor > 0.0f) {
+ test_radius *= data->brush->area_radius_factor;
+ }
+ else {
test_radius *= data->brush->normal_radius_factor;
}
- test.radius_squared = test_radius * test_radius;
+ area_test.radius = test_radius;
+ area_test.radius_squared = test_radius * test_radius;
}
- /* when the mesh is edited we can't rely on original coords
- * (original mesh may not even have verts in brush radius) */
+ /* When the mesh is edited we can't rely on original coords
+ * (original mesh may not even have verts in brush radius). */
if (use_original && data->has_bm_orco) {
float(*orco_coords)[3];
int(*orco_tris)[3];
int orco_tris_num;
- int i;
BKE_pbvh_node_get_bm_orco_data(data->nodes[n], &orco_tris, &orco_tris_num, &orco_coords);
- for (i = 0; i < orco_tris_num; i++) {
+ for (int i = 0; i < orco_tris_num; i++) {
const float *co_tri[3] = {
orco_coords[orco_tris[i][0]],
orco_coords[orco_tris[i][1]],
@@ -1480,74 +1750,118 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
};
float co[3];
- closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri));
+ closest_on_tri_to_point_v3(co, normal_test.location, UNPACK3(co_tri));
+
+ normal_test_r = sculpt_brush_normal_test_sq_fn(&normal_test, co);
+ area_test_r = sculpt_brush_area_test_sq_fn(&area_test, co);
- if (sculpt_brush_test_sq_fn(&test, co)) {
+ if (normal_test_r || area_test_r) {
float no[3];
int flip_index;
normal_tri_v3(no, UNPACK3(co_tri));
flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
- if (use_area_cos) {
+ if (use_area_cos && area_test_r) {
+ /* Weight the coordinates towards the center. */
+ float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius);
+ float afactor = 3.0f * p * p - 2.0f * p * p * p;
+ CLAMP(afactor, 0.0f, 1.0f);
+
+ float disp[3];
+ sub_v3_v3v3(disp, co, area_test.location);
+ mul_v3_fl(disp, 1.0f - afactor);
+ add_v3_v3v3(co, area_test.location, disp);
add_v3_v3(anctd->area_cos[flip_index], co);
+
+ anctd->count_co[flip_index] += 1;
}
- if (use_area_nos) {
+ if (use_area_nos && normal_test_r) {
+ /* Weight the normals towards the center. */
+ float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius);
+ float nfactor = 3.0f * p * p - 2.0f * p * p * p;
+ CLAMP(nfactor, 0.0f, 1.0f);
+ mul_v3_fl(no, nfactor);
+
add_v3_v3(anctd->area_nos[flip_index], no);
+ anctd->count_no[flip_index] += 1;
}
- anctd->area_count[flip_index] += 1;
}
}
}
else {
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- const float *co;
- const short *no_s; /* bm_vert only */
+ float co[3];
+
+ /* For bm_vert only. */
+ short no_s[3];
if (use_original) {
if (unode->bm_entry) {
- BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s);
+ const float *temp_co;
+ const short *temp_no_s;
+ BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &temp_co, &temp_no_s);
+ copy_v3_v3(co, temp_co);
+ copy_v3_v3_short(no_s, temp_no_s);
}
else {
- co = unode->co[vd.i];
- no_s = unode->no[vd.i];
+ copy_v3_v3(co, unode->co[vd.i]);
+ copy_v3_v3_short(no_s, unode->no[vd.i]);
}
}
else {
- co = vd.co;
+ copy_v3_v3(co, vd.co);
}
- if (sculpt_brush_test_sq_fn(&test, co)) {
- float no_buf[3];
- const float *no;
+ normal_test_r = sculpt_brush_normal_test_sq_fn(&normal_test, co);
+ area_test_r = sculpt_brush_area_test_sq_fn(&area_test, co);
+
+ if (normal_test_r || area_test_r) {
+ float no[3];
int flip_index;
data->any_vertex_sampled = true;
if (use_original) {
- normal_short_to_float_v3(no_buf, no_s);
- no = no_buf;
+ normal_short_to_float_v3(no, no_s);
}
else {
if (vd.no) {
- normal_short_to_float_v3(no_buf, vd.no);
- no = no_buf;
+ normal_short_to_float_v3(no, vd.no);
}
else {
- no = vd.fno;
+ copy_v3_v3(no, vd.fno);
}
}
flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <=
0.0f);
- if (use_area_cos) {
+
+ if (use_area_cos && area_test_r) {
+ /* Weight the coordinates towards the center. */
+ float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius);
+ float afactor = 3.0f * p * p - 2.0f * p * p * p;
+ CLAMP(afactor, 0.0f, 1.0f);
+
+ float disp[3];
+ sub_v3_v3v3(disp, co, area_test.location);
+ mul_v3_fl(disp, 1.0f - afactor);
+ add_v3_v3v3(co, area_test.location, disp);
+
add_v3_v3(anctd->area_cos[flip_index], co);
+ anctd->count_co[flip_index] += 1;
}
- if (use_area_nos) {
+ if (use_area_nos && normal_test_r) {
+ /* Weight the normals towards the center. */
+ float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius);
+ float nfactor = 3.0f * p * p - 2.0f * p * p * p;
+ CLAMP(nfactor, 0.0f, 1.0f);
+ mul_v3_fl(no, nfactor);
+
add_v3_v3(anctd->area_nos[flip_index], no);
+ anctd->count_no[flip_index] += 1;
}
- anctd->area_count[flip_index] += 1;
}
}
BKE_pbvh_vertex_iter_end;
@@ -1561,17 +1875,17 @@ static void calc_area_normal_and_center_reduce(const void *__restrict UNUSED(use
AreaNormalCenterTLSData *join = chunk_join;
AreaNormalCenterTLSData *anctd = chunk;
- /* for flatten center */
+ /* For flatten center. */
add_v3_v3(join->area_cos[0], anctd->area_cos[0]);
add_v3_v3(join->area_cos[1], anctd->area_cos[1]);
- /* for area normal */
+ /* For area normal. */
add_v3_v3(join->area_nos[0], anctd->area_nos[0]);
add_v3_v3(join->area_nos[1], anctd->area_nos[1]);
- /* weights */
- join->area_count[0] += anctd->area_count[0];
- join->area_count[1] += anctd->area_count[1];
+ /* Weights. */
+ add_v2_v2_int(join->count_no, anctd->count_no);
+ add_v2_v2_int(join->count_co, anctd->count_co);
}
static void calc_area_center(
@@ -1579,7 +1893,7 @@ static void calc_area_center(
{
const Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
- const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
+ const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush);
int n;
/* Intentionally set 'sd' to NULL since we share logic with vertex paint. */
@@ -1595,35 +1909,42 @@ static void calc_area_center(
AreaNormalCenterTLSData anctd = {{{0}}};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
- BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
- /* for flatten center */
+ /* For flatten center. */
for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) {
- if (anctd.area_count[n] != 0) {
- mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.area_count[n]);
+ if (anctd.count_co[n] != 0) {
+ mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]);
break;
}
}
+
if (n == 2) {
zero_v3(r_area_co);
}
+
+ if (anctd.count_co[0] == 0 && anctd.count_co[1] == 0) {
+ if (ss->cache) {
+ copy_v3_v3(r_area_co, ss->cache->location);
+ }
+ }
}
-static void calc_area_normal(
+void SCULPT_calc_area_normal(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3])
{
const Brush *brush = BKE_paint_brush(&sd->paint);
bool use_threading = (sd->flags & SCULPT_USE_OPENMP);
- sculpt_pbvh_calc_area_normal(brush, ob, nodes, totnode, use_threading, r_area_no);
+ SCULPT_pbvh_calc_area_normal(brush, ob, nodes, totnode, use_threading, r_area_no);
}
-/* expose 'calc_area_normal' externally. */
-bool sculpt_pbvh_calc_area_normal(const Brush *brush,
+/* Expose 'calc_area_normal' externally. */
+bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
Object *ob,
PBVHNode **nodes,
int totnode,
@@ -1631,7 +1952,7 @@ bool sculpt_pbvh_calc_area_normal(const Brush *brush,
float r_area_no[3])
{
SculptSession *ss = ob->sculpt;
- const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
+ const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush);
/* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
SculptThreadedTaskData data = {
@@ -1647,14 +1968,14 @@ bool sculpt_pbvh_calc_area_normal(const Brush *brush,
AreaNormalCenterTLSData anctd = {{{0}}};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode);
settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
- BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
- /* for area normal */
+ /* For area normal. */
for (int i = 0; i < ARRAY_SIZE(anctd.area_nos); i++) {
if (normalize_v3_v3(r_area_no, anctd.area_nos[i]) != 0.0f) {
break;
@@ -1664,14 +1985,14 @@ bool sculpt_pbvh_calc_area_normal(const Brush *brush,
return data.any_vertex_sampled;
}
-/* this calculates flatten center and area normal together,
- * amortizing the memory bandwidth and loop overhead to calculate both at the same time */
+/* This calculates flatten center and area normal together,
+ * amortizing the memory bandwidth and loop overhead to calculate both at the same time. */
static void calc_area_normal_and_center(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3])
{
const Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
- const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
+ const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush);
int n;
/* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
@@ -1688,25 +2009,32 @@ static void calc_area_normal_and_center(
AreaNormalCenterTLSData anctd = {{{0}}};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
- BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
- /* for flatten center */
+ /* For flatten center. */
for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) {
- if (anctd.area_count[n] != 0) {
- mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.area_count[n]);
+ if (anctd.count_co[n] != 0) {
+ mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]);
break;
}
}
+
if (n == 2) {
zero_v3(r_area_co);
}
- /* for area normal */
+ if (anctd.count_co[0] == 0 && anctd.count_co[1] == 0) {
+ if (ss->cache) {
+ copy_v3_v3(r_area_co, ss->cache->location);
+ }
+ }
+
+ /* For area normal. */
for (n = 0; n < ARRAY_SIZE(anctd.area_nos); n++) {
if (normalize_v3_v3(r_area_no, anctd.area_nos[n]) != 0.0f) {
break;
@@ -1727,23 +2055,23 @@ static float brush_strength(const Sculpt *sd,
const Scene *scene = cache->vc->scene;
const Brush *brush = BKE_paint_brush((Paint *)&sd->paint);
- /* Primary strength input; square it to make lower values more sensitive */
+ /* Primary strength input; square it to make lower values more sensitive. */
const float root_alpha = BKE_brush_alpha_get(scene, brush);
- float alpha = root_alpha * root_alpha;
- float dir = (brush->flag & BRUSH_DIR_IN) ? -1 : 1;
- float pressure = BKE_brush_use_alpha_pressure(brush) ? cache->pressure : 1;
- float pen_flip = cache->pen_flip ? -1 : 1;
- float invert = cache->invert ? -1 : 1;
+ const float alpha = root_alpha * root_alpha;
+ const float dir = (brush->flag & BRUSH_DIR_IN) ? -1.0f : 1.0f;
+ const float pressure = BKE_brush_use_alpha_pressure(brush) ? cache->pressure : 1.0f;
+ const float pen_flip = cache->pen_flip ? -1.0f : 1.0f;
+ const float invert = cache->invert ? -1.0f : 1.0f;
float overlap = ups->overlap_factor;
- /* spacing is integer percentage of radius, divide by 50 to get
- * normalized diameter */
+ /* Spacing is integer percentage of radius, divide by 50 to get
+ * normalized diameter. */
float flip = dir * invert * pen_flip;
if (brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
flip = 1.0f;
}
- /* Pressure final value after being tweaked depending on the brush */
+ /* Pressure final value after being tweaked depending on the brush. */
float final_pressure;
switch (brush->sculpt_tool) {
@@ -1755,15 +2083,31 @@ static float brush_strength(const Sculpt *sd,
case SCULPT_TOOL_DRAW_SHARP:
case SCULPT_TOOL_LAYER:
return alpha * flip * pressure * overlap * feather;
+ case SCULPT_TOOL_CLOTH:
+ /* Expand is more sensible to strength as it keeps expanding the cloth when sculpting over
+ * the same vertices. */
+ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_EXPAND) {
+ return 0.1f * alpha * flip * pressure * overlap * feather;
+ }
+ else {
+ /* Multiply by 10 by default to get a larger range of strength depending on the size of the
+ * brush and object. */
+ return 10.0f * alpha * flip * pressure * overlap * feather;
+ }
+ case SCULPT_TOOL_DRAW_FACE_SETS:
+ return alpha * pressure * overlap * feather;
case SCULPT_TOOL_SLIDE_RELAX:
return alpha * pressure * overlap * feather * 2.0f;
case SCULPT_TOOL_CLAY_STRIPS:
- /* Clay Strips needs less strength to compensate the curve */
- final_pressure = pressure * pressure * pressure;
+ /* Clay Strips needs less strength to compensate the curve. */
+ final_pressure = powf(pressure, 1.5f);
return alpha * flip * final_pressure * overlap * feather * 0.3f;
+ case SCULPT_TOOL_CLAY_THUMB:
+ final_pressure = pressure * pressure;
+ return alpha * flip * final_pressure * overlap * feather * 1.3f;
case SCULPT_TOOL_MASK:
- overlap = (1 + overlap) / 2;
+ overlap = (1.0f + overlap) / 2.0f;
switch ((BrushMaskTool)brush->mask_tool) {
case BRUSH_MASK_DRAW:
return alpha * flip * pressure * overlap * feather;
@@ -1778,7 +2122,7 @@ static float brush_strength(const Sculpt *sd,
return alpha * flip * pressure * overlap * feather;
case SCULPT_TOOL_INFLATE:
- if (flip > 0) {
+ if (flip > 0.0f) {
return 0.250f * alpha * flip * pressure * overlap * feather;
}
else {
@@ -1792,12 +2136,12 @@ static float brush_strength(const Sculpt *sd,
case SCULPT_TOOL_FILL:
case SCULPT_TOOL_SCRAPE:
case SCULPT_TOOL_FLATTEN:
- if (flip > 0) {
- overlap = (1 + overlap) / 2;
+ if (flip > 0.0f) {
+ overlap = (1.0f + overlap) / 2.0f;
return alpha * flip * pressure * overlap * feather;
}
else {
- /* reduce strength for DEEPEN, PEAKS, and CONTRAST */
+ /* Reduce strength for DEEPEN, PEAKS, and CONTRAST. */
return 0.5f * alpha * flip * pressure * overlap * feather;
}
@@ -1805,7 +2149,7 @@ static float brush_strength(const Sculpt *sd,
return alpha * pressure * feather;
case SCULPT_TOOL_PINCH:
- if (flip > 0) {
+ if (flip > 0.0f) {
return alpha * flip * pressure * overlap * feather;
}
else {
@@ -1813,7 +2157,7 @@ static float brush_strength(const Sculpt *sd,
}
case SCULPT_TOOL_NUDGE:
- overlap = (1 + overlap) / 2;
+ overlap = (1.0f + overlap) / 2.0f;
return alpha * pressure * overlap * feather;
case SCULPT_TOOL_THUMB:
@@ -1833,43 +2177,43 @@ static float brush_strength(const Sculpt *sd,
return root_alpha * feather;
default:
- return 0;
+ return 0.0f;
}
}
/* Return a multiplier for brush strength on a particular vertex. */
-float tex_strength(SculptSession *ss,
- const Brush *br,
- const float brush_point[3],
- const float len,
- const short vno[3],
- const float fno[3],
- const float mask,
- const int vertex_index,
- const int thread_id)
+float SCULPT_brush_strength_factor(SculptSession *ss,
+ const Brush *br,
+ const float brush_point[3],
+ const float len,
+ const short vno[3],
+ const float fno[3],
+ const float mask,
+ const int vertex_index,
+ const int thread_id)
{
StrokeCache *cache = ss->cache;
const Scene *scene = cache->vc->scene;
const MTex *mtex = &br->mtex;
- float avg = 1;
+ float avg = 1.0f;
float rgba[4];
float point[3];
sub_v3_v3v3(point, brush_point, cache->plane_offset);
if (!mtex->tex) {
- avg = 1;
+ avg = 1.0f;
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
- /* Get strength by feeding the vertex
- * location directly into a texture */
+ /* Get strength by feeding the vertex location directly into a texture. */
avg = BKE_brush_sample_tex_3d(scene, br, point, rgba, 0, ss->tex_pool);
}
else if (ss->texcache) {
float symm_point[3], point_2d[2];
- float x = 0.0f, y = 0.0f; /* Quite warnings */
+ /* Quite warnings. */
+ float x = 0.0f, y = 0.0f;
- /* if the active area is being applied for symmetry, flip it
+ /* If the active area is being applied for symmetry, flip it
* across the symmetry axis and rotate it back to the original
* position in order to project it. This insures that the
* brush texture will be oriented correctly. */
@@ -1880,13 +2224,13 @@ float tex_strength(SculptSession *ss,
mul_m4_v3(cache->symm_rot_mat_inv, symm_point);
}
- ED_view3d_project_float_v2_m4(cache->vc->ar, symm_point, point_2d, cache->projection_mat);
+ ED_view3d_project_float_v2_m4(cache->vc->region, symm_point, point_2d, cache->projection_mat);
- /* still no symmetry supported for other paint modes.
- * Sculpt does it DIY */
+ /* Still no symmetry supported for other paint modes.
+ * Sculpt does it DIY. */
if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) {
/* Similar to fixed mode, but projects from brush angle
- * rather than view direction */
+ * rather than view direction. */
mul_m4_v3(cache->brush_local_mat, symm_point);
@@ -1909,21 +2253,36 @@ float tex_strength(SculptSession *ss,
}
}
- /* Falloff curve */
- avg *= BKE_brush_curve_strength(br, len, cache->radius);
+ /* Hardness. */
+ float final_len = len;
+ const float hardness = br->hardness;
+ float p = len / cache->radius;
+ if (p < hardness) {
+ final_len = 0.0f;
+ }
+ else if (hardness == 1.0f) {
+ final_len = cache->radius;
+ }
+ else {
+ p = (p - hardness) / (1.0f - hardness);
+ final_len = p * cache->radius;
+ }
+
+ /* Falloff curve. */
+ avg *= BKE_brush_curve_strength(br, final_len, cache->radius);
avg *= frontface(br, cache->view_normal, vno, fno);
- /* Paint mask */
+ /* Paint mask. */
avg *= 1.0f - mask;
- /* Automasking */
- avg *= sculpt_automasking_factor_get(ss, vertex_index);
+ /* Automasking. */
+ avg *= SCULPT_automasking_factor_get(ss, vertex_index);
return avg;
}
-/* Test AABB against sphere */
-bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
+/* Test AABB against sphere. */
+bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
{
SculptSearchSphereData *data = data_v;
const float *center;
@@ -1935,7 +2294,6 @@ bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
center = data->ss->cache ? data->ss->cache->location : data->ss->cursor_location;
}
float t[3], bb_min[3], bb_max[3];
- int i;
if (data->ignore_fully_masked) {
if (BKE_pbvh_node_fully_masked_get(node)) {
@@ -1950,7 +2308,7 @@ bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
BKE_pbvh_node_get_BB(node, bb_min, bb_max);
}
- for (i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++) {
if (bb_min[i] > center[i]) {
nearest[i] = bb_min[i];
}
@@ -1968,7 +2326,7 @@ bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
}
/* 2D projection (distance to line). */
-bool sculpt_search_circle_cb(PBVHNode *node, void *data_v)
+bool SCULPT_search_circle_cb(PBVHNode *node, void *data_v)
{
SculptSearchCircleData *data = data_v;
float bb_min[3], bb_max[3];
@@ -1990,15 +2348,15 @@ bool sculpt_search_circle_cb(PBVHNode *node, void *data_v)
const float dist_sq = dist_squared_ray_to_aabb_v3(
data->dist_ray_to_aabb_precalc, bb_min, bb_max, dummy_co, &dummy_depth);
- return dist_sq < data->radius_squared || 1;
+ /* Seems like debug code.
+ * Maybe this function can just return true if the node is not fully masked. */
+ return dist_sq < data->radius_squared || true;
}
-/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags */
-static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3])
+/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags. */
+void SCULPT_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3])
{
- int i;
-
- for (i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++) {
if (sd->flags & (SCULPT_LOCK_X << i)) {
continue;
}
@@ -2027,7 +2385,7 @@ static PBVHNode **sculpt_pbvh_gather_cursor_update(Object *ob,
.ignore_fully_masked = false,
.center = NULL,
};
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode);
+ BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
return nodes;
}
@@ -2041,18 +2399,18 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob,
SculptSession *ss = ob->sculpt;
PBVHNode **nodes = NULL;
- /* Build a list of all nodes that are potentially within the cursor or brush's area of influence
+ /* Build a list of all nodes that are potentially within the cursor or brush's area of influence.
*/
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
SculptSearchSphereData data = {
.ss = ss,
.sd = sd,
- .radius_squared = SQUARE(ss->cache->radius * radius_scale),
+ .radius_squared = square_f(ss->cache->radius * radius_scale),
.original = use_original,
.ignore_fully_masked = brush->sculpt_tool != SCULPT_TOOL_MASK,
.center = NULL,
};
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode);
+ BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
}
else {
struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
@@ -2061,17 +2419,18 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob,
SculptSearchCircleData data = {
.ss = ss,
.sd = sd,
- .radius_squared = ss->cache ? SQUARE(ss->cache->radius * radius_scale) : ss->cursor_radius,
+ .radius_squared = ss->cache ? square_f(ss->cache->radius * radius_scale) :
+ ss->cursor_radius,
.original = use_original,
.dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc,
.ignore_fully_masked = brush->sculpt_tool != SCULPT_TOOL_MASK,
};
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_circle_cb, &data, &nodes, r_totnode);
+ BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_circle_cb, &data, &nodes, r_totnode);
}
return nodes;
}
-/* Calculate primary direction of movement for many brushes */
+/* Calculate primary direction of movement for many brushes. */
static void calc_sculpt_normal(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3])
{
@@ -2084,19 +2443,19 @@ static void calc_sculpt_normal(
break;
case SCULPT_DISP_DIR_X:
- ARRAY_SET_ITEMS(r_area_no, 1, 0, 0);
+ ARRAY_SET_ITEMS(r_area_no, 1.0f, 0.0f, 0.0f);
break;
case SCULPT_DISP_DIR_Y:
- ARRAY_SET_ITEMS(r_area_no, 0, 1, 0);
+ ARRAY_SET_ITEMS(r_area_no, 0.0f, 1.0f, 0.0f);
break;
case SCULPT_DISP_DIR_Z:
- ARRAY_SET_ITEMS(r_area_no, 0, 0, 1);
+ ARRAY_SET_ITEMS(r_area_no, 0.0f, 0.0f, 1.0f);
break;
case SCULPT_DISP_DIR_AREA:
- calc_area_normal(sd, ob, nodes, totnode, r_area_no);
+ SCULPT_calc_area_normal(sd, ob, nodes, totnode, r_area_no);
break;
default:
@@ -2108,7 +2467,7 @@ static void update_sculpt_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
{
const Brush *brush = BKE_paint_brush(&sd->paint);
StrokeCache *cache = ob->sculpt->cache;
- /* Grab brush does not update the sculpt normal during a stroke */
+ /* Grab brush does not update the sculpt normal during a stroke. */
const bool update_normal = !(brush->flag & BRUSH_ORIGINAL_NORMAL) &&
!(brush->sculpt_tool == SCULPT_TOOL_GRAB) &&
!(brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM) &&
@@ -2140,7 +2499,7 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3])
mul_v3_m4v3(loc, ob->imat, center);
zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL);
- ED_view3d_win_to_delta(vc->ar, mval_f, y, zfac);
+ ED_view3d_win_to_delta(vc->region, mval_f, y, zfac);
normalize_v3(y);
add_v3_v3(y, ob->loc);
@@ -2156,38 +2515,38 @@ static void calc_brush_local_mat(const Brush *brush, Object *ob, float local_mat
float angle, v[3];
float up[3];
- /* Ensure ob->imat is up to date */
+ /* Ensure ob->imat is up to date. */
invert_m4_m4(ob->imat, ob->obmat);
- /* Initialize last column of matrix */
- mat[0][3] = 0;
- mat[1][3] = 0;
- mat[2][3] = 0;
- mat[3][3] = 1;
+ /* Initialize last column of matrix. */
+ mat[0][3] = 0.0f;
+ mat[1][3] = 0.0f;
+ mat[2][3] = 0.0f;
+ mat[3][3] = 1.0f;
- /* Get view's up vector in object-space */
+ /* Get view's up vector in object-space. */
calc_local_y(cache->vc, cache->location, up);
- /* Calculate the X axis of the local matrix */
+ /* Calculate the X axis of the local matrix. */
cross_v3_v3v3(v, up, cache->sculpt_normal);
- /* Apply rotation (user angle, rake, etc.) to X axis */
+ /* Apply rotation (user angle, rake, etc.) to X axis. */
angle = brush->mtex.rot - cache->special_rotation;
rotate_v3_v3v3fl(mat[0], v, cache->sculpt_normal, angle);
- /* Get other axes */
+ /* Get other axes. */
cross_v3_v3v3(mat[1], cache->sculpt_normal, mat[0]);
copy_v3_v3(mat[2], cache->sculpt_normal);
- /* Set location */
+ /* Set location. */
copy_v3_v3(mat[3], cache->location);
- /* Scale by brush radius */
+ /* Scale by brush radius. */
normalize_m4(mat);
scale_m4_fl(scale, cache->radius);
mul_m4_m4m4(tmat, mat, scale);
/* Return inverse (for converting from modelspace coords to local
- * area coords) */
+ * area coords). */
invert_m4_m4(local_mat, tmat);
}
@@ -2200,229 +2559,6 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob)
}
}
-/* For the smooth brush, uses the neighboring vertices around vert to calculate
- * a smoothed location for vert. Skips corner vertices (used by only one
- * polygon.) */
-static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert)
-{
- const MeshElemMap *vert_map = &ss->pmap[vert];
- const MVert *mvert = ss->mvert;
- float(*deform_co)[3] = ss->deform_cos;
-
- /* Don't modify corner vertices */
- if (vert_map->count > 1) {
- int i, total = 0;
-
- zero_v3(avg);
-
- for (i = 0; i < vert_map->count; i++) {
- const MPoly *p = &ss->mpoly[vert_map->indices[i]];
- unsigned f_adj_v[2];
-
- if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) {
- int j;
- for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
- if (vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2) {
- add_v3_v3(avg, deform_co ? deform_co[f_adj_v[j]] : mvert[f_adj_v[j]].co);
-
- total++;
- }
- }
- }
- }
-
- if (total > 0) {
- mul_v3_fl(avg, 1.0f / total);
- return;
- }
- }
-
- copy_v3_v3(avg, deform_co ? deform_co[vert] : mvert[vert].co);
-}
-
-/* Similar to neighbor_average(), but returns an averaged mask value
- * instead of coordinate. Also does not restrict based on border or
- * corner vertices. */
-static float neighbor_average_mask(SculptSession *ss, unsigned vert)
-{
- const float *vmask = ss->vmask;
- float avg = 0;
- int i, total = 0;
-
- for (i = 0; i < ss->pmap[vert].count; i++) {
- const MPoly *p = &ss->mpoly[ss->pmap[vert].indices[i]];
- unsigned f_adj_v[2];
-
- if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) {
- int j;
- for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
- avg += vmask[f_adj_v[j]];
- total++;
- }
- }
- }
-
- if (total > 0) {
- return avg / (float)total;
- }
- else {
- return vmask[vert];
- }
-}
-
-/* Same logic as neighbor_average(), but for bmesh rather than mesh */
-static void bmesh_neighbor_average(float avg[3], BMVert *v)
-{
- /* logic for 3 or more is identical */
- const int vfcount = BM_vert_face_count_at_most(v, 3);
-
- /* Don't modify corner vertices */
- if (vfcount > 1) {
- BMIter liter;
- BMLoop *l;
- int i, total = 0;
-
- zero_v3(avg);
-
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- const BMVert *adj_v[2] = {l->prev->v, l->next->v};
-
- for (i = 0; i < ARRAY_SIZE(adj_v); i++) {
- const BMVert *v_other = adj_v[i];
- if (vfcount != 2 || BM_vert_face_count_at_most(v_other, 2) <= 2) {
- add_v3_v3(avg, v_other->co);
- total++;
- }
- }
- }
-
- if (total > 0) {
- mul_v3_fl(avg, 1.0f / total);
- return;
- }
- }
-
- copy_v3_v3(avg, v->co);
-}
-
-/* For bmesh: Average surrounding verts based on an orthogonality measure.
- * Naturally converges to a quad-like structure. */
-static void bmesh_four_neighbor_average(float avg[3], float direction[3], BMVert *v)
-{
-
- float avg_co[3] = {0, 0, 0};
- float tot_co = 0;
-
- BMIter eiter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_boundary(e)) {
- copy_v3_v3(avg, v->co);
- return;
- }
- BMVert *v_other = (e->v1 == v) ? e->v2 : e->v1;
- float vec[3];
- sub_v3_v3v3(vec, v_other->co, v->co);
- madd_v3_v3fl(vec, v->no, -dot_v3v3(vec, v->no));
- normalize_v3(vec);
-
- /* fac is a measure of how orthogonal or parallel the edge is
- * relative to the direction */
- float fac = dot_v3v3(vec, direction);
- fac = fac * fac - 0.5f;
- fac *= fac;
- madd_v3_v3fl(avg_co, v_other->co, fac);
- tot_co += fac;
- }
-
- /* In case vert has no Edge s */
- if (tot_co > 0) {
- mul_v3_v3fl(avg, avg_co, 1.0f / tot_co);
-
- /* Preserve volume. */
- float vec[3];
- sub_v3_v3(avg, v->co);
- mul_v3_v3fl(vec, v->no, dot_v3v3(avg, v->no));
- sub_v3_v3(avg, vec);
- add_v3_v3(avg, v->co);
- }
- else {
- zero_v3(avg);
- }
-}
-
-/* Same logic as neighbor_average_mask(), but for bmesh rather than mesh */
-static float bmesh_neighbor_average_mask(BMVert *v, const int cd_vert_mask_offset)
-{
- BMIter liter;
- BMLoop *l;
- float avg = 0;
- int i, total = 0;
-
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- /* skip this vertex */
- const BMVert *adj_v[2] = {l->prev->v, l->next->v};
-
- for (i = 0; i < ARRAY_SIZE(adj_v); i++) {
- const BMVert *v_other = adj_v[i];
- const float *vmask = BM_ELEM_CD_GET_VOID_P(v_other, cd_vert_mask_offset);
- avg += (*vmask);
- total++;
- }
- }
-
- if (total > 0) {
- return avg / (float)total;
- }
- else {
- const float *vmask = BM_ELEM_CD_GET_VOID_P(v, cd_vert_mask_offset);
- return (*vmask);
- }
-}
-
-static void grids_neighbor_average(SculptSession *ss, float result[3], int index)
-{
- float avg[3] = {0.0f, 0.0f, 0.0f};
- int total = 0;
-
- SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, index, ni)
- {
- add_v3_v3(avg, sculpt_vertex_co_get(ss, ni.index));
- total++;
- }
- sculpt_vertex_neighbors_iter_end(ni);
-
- if (total > 0) {
- mul_v3_v3fl(result, avg, 1.0f / (float)total);
- }
- else {
- copy_v3_v3(result, sculpt_vertex_co_get(ss, index));
- }
-}
-
-static float grids_neighbor_average_mask(SculptSession *ss, int index)
-{
- float avg = 0.0f;
- int total = 0;
-
- SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, index, ni)
- {
- avg += sculpt_vertex_mask_get(ss, ni.index);
- total++;
- }
- sculpt_vertex_neighbors_iter_end(ni);
-
- if (total > 0) {
- return avg / (float)total;
- }
- else {
- return sculpt_vertex_mask_get(ss, index);
- }
-}
-
/* Note: uses after-struct allocated mem to store actual cache... */
typedef struct SculptDoBrushSmoothGridDataChunk {
size_t tmpgrid_size;
@@ -2439,17 +2575,10 @@ typedef struct {
int active_vertex_index;
float *face_normal;
- struct IsectRayPrecalc isect_precalc;
-} SculptRaycastData;
-
-typedef struct {
- const float *ray_start;
- bool hit;
- float depth;
- float edge_length;
+ int active_face_grid_index;
struct IsectRayPrecalc isect_precalc;
-} SculptDetailRaycastData;
+} SculptRaycastData;
typedef struct {
SculptSession *ss;
@@ -2460,118 +2589,6 @@ typedef struct {
bool original;
} SculptFindNearestToRayData;
-static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- Sculpt *sd = data->sd;
- const Brush *brush = data->brush;
- const bool smooth_mask = data->smooth_mask;
- float bstrength = data->strength;
-
- PBVHVertexIter vd;
-
- CLAMP(bstrength, 0.0f, 1.0f);
-
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
- ss, &test, data->brush->falloff_shape);
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
- vd.index,
- tls->thread_id);
- if (smooth_mask) {
- float val = neighbor_average_mask(ss, vd.vert_indices[vd.i]) - *vd.mask;
- val *= fade * bstrength;
- *vd.mask += val;
- CLAMP(*vd.mask, 0.0f, 1.0f);
- }
- else {
- float avg[3], val[3];
-
- neighbor_average(ss, avg, vd.vert_indices[vd.i]);
- sub_v3_v3v3(val, avg, vd.co);
-
- madd_v3_v3v3fl(val, vd.co, val, fade);
-
- sculpt_clip(sd, ss, vd.co, val);
- }
-
- if (vd.mvert) {
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static void do_smooth_brush_bmesh_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- Sculpt *sd = data->sd;
- const Brush *brush = data->brush;
- const bool smooth_mask = data->smooth_mask;
- float bstrength = data->strength;
-
- PBVHVertexIter vd;
-
- CLAMP(bstrength, 0.0f, 1.0f);
-
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
- ss, &test, data->brush->falloff_shape);
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- smooth_mask ? 0.0f : *vd.mask,
- vd.index,
- tls->thread_id);
- if (smooth_mask) {
- float val = bmesh_neighbor_average_mask(vd.bm_vert, vd.cd_vert_mask_offset) - *vd.mask;
- val *= fade * bstrength;
- *vd.mask += val;
- CLAMP(*vd.mask, 0.0f, 1.0f);
- }
- else {
- float avg[3], val[3];
-
- bmesh_neighbor_average(avg, vd.bm_vert);
- sub_v3_v3v3(val, avg, vd.co);
-
- madd_v3_v3v3fl(val, vd.co, val, fade);
-
- sculpt_clip(sd, ss, vd.co, val);
- }
-
- if (vd.mvert) {
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
@@ -2599,34 +2616,29 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
CLAMP(bstrength, 0.0f, 1.0f);
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = bstrength *
- tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- *vd.mask,
- vd.index,
- tls->thread_id) *
- ss->cache->pressure;
+ const float fade =
+ bstrength *
+ SCULPT_brush_strength_factor(
+ ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) *
+ ss->cache->pressure;
float avg[3], val[3];
- bmesh_four_neighbor_average(avg, direction, vd.bm_vert);
+ SCULPT_bmesh_four_neighbor_average(avg, direction, vd.bm_vert);
sub_v3_v3v3(val, avg, vd.co);
madd_v3_v3v3fl(val, vd.co, val, fade);
- sculpt_clip(sd, ss, vd.co, val);
+ SCULPT_clip(sd, ss, vd.co, val);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@@ -2636,110 +2648,6 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- Sculpt *sd = data->sd;
- const Brush *brush = data->brush;
- const bool smooth_mask = data->smooth_mask;
- float bstrength = data->strength;
-
- PBVHVertexIter vd;
-
- CLAMP(bstrength, 0.0f, 1.0f);
-
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
- ss, &test, data->brush->falloff_shape);
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
- vd.index,
- tls->thread_id);
- if (smooth_mask) {
- float val = grids_neighbor_average_mask(ss, vd.index) - *vd.mask;
- val *= fade * bstrength;
- *vd.mask += val;
- CLAMP(*vd.mask, 0.0f, 1.0f);
- }
- else {
- float avg[3], val[3];
- grids_neighbor_average(ss, avg, vd.index);
- sub_v3_v3v3(val, avg, vd.co);
- madd_v3_v3v3fl(val, vd.co, val, fade);
- sculpt_clip(sd, ss, vd.co, val);
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static void smooth(Sculpt *sd,
- Object *ob,
- PBVHNode **nodes,
- const int totnode,
- float bstrength,
- const bool smooth_mask)
-{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- const int max_iterations = 4;
- const float fract = 1.0f / max_iterations;
- PBVHType type = BKE_pbvh_type(ss->pbvh);
- int iteration, count;
- float last;
-
- CLAMP(bstrength, 0.0f, 1.0f);
-
- count = (int)(bstrength * max_iterations);
- last = max_iterations * (bstrength - count * fract);
-
- if (type == PBVH_FACES && !ss->pmap) {
- BLI_assert(!"sculpt smooth: pmap missing");
- return;
- }
-
- for (iteration = 0; iteration <= count; iteration++) {
- const float strength = (iteration != count) ? 1.0f : last;
-
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .smooth_mask = smooth_mask,
- .strength = strength,
- };
-
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
-
- switch (type) {
- case PBVH_GRIDS:
- BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings);
- break;
- case PBVH_FACES:
- BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings);
- break;
- case PBVH_BMESH:
- BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings);
- break;
- }
- }
-}
-
static void bmesh_topology_rake(
Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength)
{
@@ -2762,19 +2670,13 @@ static void bmesh_topology_rake(
.nodes = nodes,
.strength = factor,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings);
}
}
-static void do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
-{
- SculptSession *ss = ob->sculpt;
- smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false);
-}
-
static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
@@ -2787,14 +2689,15 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = tex_strength(
- ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, tls->thread_id);
+ const float fade = SCULPT_brush_strength_factor(
+ ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id);
if (bstrength > 0.0f) {
(*vd.mask) += fade * bstrength * (1.0f - *vd.mask);
@@ -2816,7 +2719,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
{
Brush *brush = BKE_paint_brush(&sd->paint);
- /* threaded loop over nodes */
+ /* Threaded loop over nodes. */
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
@@ -2824,9 +2727,9 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
.nodes = nodes,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings);
}
static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
@@ -2839,7 +2742,7 @@ static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
do_mask_brush_draw(sd, ob, nodes, totnode);
break;
case BRUSH_MASK_SMOOTH:
- smooth(sd, ob, nodes, totnode, ss->cache->bstrength, true);
+ SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, true);
break;
}
}
@@ -2859,22 +2762,23 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* offset vertex */
- const float fade = tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ /* Offset vertex. */
+ const float fade = SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -2893,16 +2797,16 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
float offset[3];
const float bstrength = ss->cache->bstrength;
- /* offset with as much as possible factored in already */
+ /* Offset with as much as possible factored in already. */
mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius);
mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
/* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
- * initialize before threads so they can do curve mapping */
+ * initialize before threads so they can do curve mapping. */
BKE_curvemapping_initialize(brush->curve);
- /* threaded loop over nodes */
+ /* Threaded loop over nodes. */
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
@@ -2911,9 +2815,9 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.offset = offset,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings);
}
static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
@@ -2929,28 +2833,29 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
SculptOrigVertData orig_data;
float(*proxy)[3];
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
- /* offset vertex */
- const float fade = tex_strength(ss,
- brush,
- orig_data.co,
- sqrtf(test.dist),
- orig_data.no,
- NULL,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ /* Offset vertex. */
+ const float fade = SCULPT_brush_strength_factor(ss,
+ brush,
+ orig_data.co,
+ sqrtf(test.dist),
+ orig_data.no,
+ NULL,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -2969,16 +2874,16 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
float offset[3];
const float bstrength = ss->cache->bstrength;
- /* offset with as much as possible factored in already */
+ /* Offset with as much as possible factored in already. */
mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius);
mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
/* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
- * initialize before threads so they can do curve mapping */
+ * initialize before threads so they can do curve mapping. */
BKE_curvemapping_initialize(brush->curve);
- /* threaded loop over nodes */
+ /* Threaded loop over nodes. */
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
@@ -2987,9 +2892,9 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
.offset = offset,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings);
}
/* -------------------------------------------------------------------- */
@@ -3009,27 +2914,28 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
SculptOrigVertData orig_data;
float(*proxy)[3];
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
- const float fade = tex_strength(ss,
- brush,
- orig_data.co,
- sqrtf(test.dist),
- orig_data.no,
- NULL,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ const float fade = SCULPT_brush_strength_factor(ss,
+ brush,
+ orig_data.co,
+ sqrtf(test.dist),
+ orig_data.no,
+ NULL,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
float current_disp[3];
float current_disp_norm[3];
float final_disp[3];
@@ -3038,17 +2944,16 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
normalize_v3_v3(current_disp_norm, current_disp);
mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength);
SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni)
- {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
float vertex_disp[3];
float vertex_disp_norm[3];
- sub_v3_v3v3(vertex_disp, sculpt_vertex_co_get(ss, ni.index), vd.co);
+ sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co);
normalize_v3_v3(vertex_disp_norm, vertex_disp);
if (dot_v3v3(current_disp_norm, vertex_disp_norm) > 0.0f) {
madd_v3_v3fl(final_disp, vertex_disp_norm, dot_v3v3(current_disp, vertex_disp));
}
}
- sculpt_vertex_neighbors_iter_end(ni);
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
mul_v3_v3fl(proxy[vd.i], final_disp, fade);
@@ -3060,10 +2965,11 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void sculpt_relax_vertex(SculptSession *ss,
- PBVHVertexIter *vd,
- float factor,
- float *r_final_pos)
+void SCULPT_relax_vertex(SculptSession *ss,
+ PBVHVertexIter *vd,
+ float factor,
+ bool filter_boundary_face_sets,
+ float *r_final_pos)
{
float smooth_pos[3];
float final_disp[3];
@@ -3071,16 +2977,22 @@ static void sculpt_relax_vertex(SculptSession *ss,
zero_v3(smooth_pos);
SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, vd->index, ni)
- {
- add_v3_v3(smooth_pos, sculpt_vertex_co_get(ss, ni.index));
- count++;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->index, ni) {
+ if (!filter_boundary_face_sets ||
+ (filter_boundary_face_sets && !SCULPT_vertex_has_unique_face_set(ss, ni.index))) {
+ add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index));
+ count++;
+ }
}
- sculpt_vertex_neighbors_iter_end(ni);
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
if (count > 0) {
mul_v3_fl(smooth_pos, 1.0f / (float)count);
}
+ else {
+ copy_v3_v3(r_final_pos, vd->co);
+ return;
+ }
float plane[4];
float smooth_closest_plane[3];
@@ -3091,6 +3003,12 @@ static void sculpt_relax_vertex(SculptSession *ss,
else {
copy_v3_v3(vno, vd->fno);
}
+
+ if (is_zero_v3(vno)) {
+ copy_v3_v3(r_final_pos, vd->co);
+ return;
+ }
+
plane_from_point_normal_v3(plane, vd->co, vno);
closest_to_plane_v3(smooth_closest_plane, plane, smooth_pos);
sub_v3_v3v3(final_disp, smooth_closest_plane, vd->co);
@@ -3111,29 +3029,30 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptOrigVertData orig_data;
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n]);
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
- const float fade = tex_strength(ss,
- brush,
- orig_data.co,
- sqrtf(test.dist),
- orig_data.no,
- NULL,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
-
- sculpt_relax_vertex(ss, &vd, fade * bstrength, vd.co);
+ const float fade = SCULPT_brush_strength_factor(ss,
+ brush,
+ orig_data.co,
+ sqrtf(test.dist),
+ orig_data.no,
+ NULL,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
@@ -3160,15 +3079,100 @@ static void do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
.nodes = nodes,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
if (ss->cache->alt_smooth) {
for (int i = 0; i < 4; i++) {
- BKE_pbvh_parallel_range(0, totnode, &data, do_topology_relax_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_topology_relax_task_cb_ex, &settings);
}
}
else {
- BKE_pbvh_parallel_range(0, totnode, &data, do_topology_slide_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_topology_slide_task_cb_ex, &settings);
+ }
+}
+
+static void calc_sculpt_plane(
+ Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3])
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0 &&
+ ss->cache->tile_pass == 0 &&
+ (ss->cache->first_time || !(brush->flag & BRUSH_ORIGINAL_PLANE) ||
+ !(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
+ switch (brush->sculpt_plane) {
+ case SCULPT_DISP_DIR_VIEW:
+ copy_v3_v3(r_area_no, ss->cache->true_view_normal);
+ break;
+
+ case SCULPT_DISP_DIR_X:
+ ARRAY_SET_ITEMS(r_area_no, 1.0f, 0.0f, 0.0f);
+ break;
+
+ case SCULPT_DISP_DIR_Y:
+ ARRAY_SET_ITEMS(r_area_no, 0.0f, 1.0f, 0.0f);
+ break;
+
+ case SCULPT_DISP_DIR_Z:
+ ARRAY_SET_ITEMS(r_area_no, 0.0f, 0.0f, 1.0f);
+ break;
+
+ case SCULPT_DISP_DIR_AREA:
+ calc_area_normal_and_center(sd, ob, nodes, totnode, r_area_no, r_area_co);
+ if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
+ project_plane_v3_v3v3(r_area_no, r_area_no, ss->cache->view_normal);
+ normalize_v3(r_area_no);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* For flatten center. */
+ /* Flatten center has not been calculated yet if we are not using the area normal. */
+ if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA) {
+ calc_area_center(sd, ob, nodes, totnode, r_area_co);
+ }
+
+ /* For area normal. */
+ if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
+ copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
+ }
+ else {
+ copy_v3_v3(ss->cache->sculpt_normal, r_area_no);
+ }
+
+ /* For flatten center. */
+ if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_PLANE)) {
+ copy_v3_v3(r_area_co, ss->cache->last_center);
+ }
+ else {
+ copy_v3_v3(ss->cache->last_center, r_area_co);
+ }
+ }
+ else {
+ /* For area normal. */
+ copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
+
+ /* For flatten center. */
+ copy_v3_v3(r_area_co, ss->cache->last_center);
+
+ /* For area normal. */
+ flip_v3(r_area_no, ss->cache->mirror_symmetry_pass);
+
+ /* For flatten center. */
+ flip_v3(r_area_co, ss->cache->mirror_symmetry_pass);
+
+ /* For area normal. */
+ mul_m4_v3(ss->cache->symm_rot_mat, r_area_no);
+
+ /* For flatten center. */
+ mul_m4_v3(ss->cache->symm_rot_mat, r_area_co);
+
+ /* Shift the plane for the current tile. */
+ add_v3_v3(r_area_co, ss->cache->plane_offset);
}
}
@@ -3194,26 +3198,27 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* offset vertex */
- const float fade = tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ /* Offset vertex. */
+ const float fade = SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
float val1[3];
float val2[3];
- /* first we pinch */
+ /* First we pinch. */
sub_v3_v3v3(val1, test.location, vd.co);
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
project_plane_v3_v3v3(val1, val1, ss->cache->view_normal);
@@ -3223,7 +3228,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata,
sculpt_project_v3(spvc, val1, val1);
- /* then we draw */
+ /* Then we draw. */
mul_v3_v3fl(val2, offset, fade);
add_v3_v3v3(proxy[vd.i], val1, val2);
@@ -3248,7 +3253,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
SculptProjectVector spvc;
- /* offset with as much as possible factored in already */
+ /* Offset with as much as possible factored in already. */
mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius);
mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
@@ -3261,20 +3266,19 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
crease_correction /= brush_alpha * brush_alpha;
}
- /* we always want crease to pinch or blob to relax even when draw is negative */
- flippedbstrength = (bstrength < 0) ? -crease_correction * bstrength :
- crease_correction * bstrength;
+ /* We always want crease to pinch or blob to relax even when draw is negative. */
+ flippedbstrength = (bstrength < 0.0f) ? -crease_correction * bstrength :
+ crease_correction * bstrength;
if (brush->sculpt_tool == SCULPT_TOOL_BLOB) {
flippedbstrength *= -1.0f;
}
- /* Use surface normal for 'spvc',
- * so the vertices are pinched towards a line instead of a single point.
- * Without this we get a 'flat' surface surrounding the pinch */
+ /* Use surface normal for 'spvc', so the vertices are pinched towards a line instead of a single
+ * point. Without this we get a 'flat' surface surrounding the pinch. */
sculpt_project_v3_cache_init(&spvc, ss->cache->sculpt_normal_symm);
- /* threaded loop over nodes */
+ /* Threaded loop over nodes. */
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
@@ -3285,9 +3289,9 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
.flippedbstrength = flippedbstrength,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings);
}
static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
@@ -3297,6 +3301,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
const Brush *brush = data->brush;
+ float(*stroke_xz)[3] = data->stroke_xz;
PBVHVertexIter vd;
float(*proxy)[3];
@@ -3305,28 +3310,47 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ float x_object_space[3];
+ float z_object_space[3];
+ copy_v3_v3(x_object_space, stroke_xz[0]);
+ copy_v3_v3(z_object_space, stroke_xz[1]);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
- float val[3];
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+ float disp_center[3];
+ float x_disp[3];
+ float z_disp[3];
+ /* Calcualte displacement from the vertex to the brush center. */
+ sub_v3_v3v3(disp_center, test.location, vd.co);
+
+ /* Project the displacement into the X vector (aligned to the stroke). */
+ mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space));
+
+ /* Project the displacement into the Z vector (aligned to the surface normal). */
+ mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space));
+
+ /* Add the two projected vectors to calculate the final displacement. The Y component is
+ * removed */
+ add_v3_v3v3(disp_center, x_disp, z_disp);
- sub_v3_v3v3(val, test.location, vd.co);
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
- project_plane_v3_v3v3(val, val, ss->cache->view_normal);
+ project_plane_v3_v3v3(disp_center, disp_center, ss->cache->view_normal);
}
- mul_v3_v3fl(proxy[vd.i], val, fade);
+ mul_v3_v3fl(proxy[vd.i], disp_center, fade);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@@ -3338,18 +3362,50 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
+ SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
+ float area_no[3];
+ float area_co[3];
+
+ float mat[4][4];
+ calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
+
+ /* delay the first daub because grab delta is not setup */
+ if (ss->cache->first_time) {
+ return;
+ }
+
+ if (is_zero_v3(ss->cache->grab_delta_symmetry)) {
+ return;
+ }
+
+ /* Init mat */
+ cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
+ mat[0][3] = 0.0f;
+ cross_v3_v3v3(mat[1], area_no, mat[0]);
+ mat[1][3] = 0.0f;
+ copy_v3_v3(mat[2], area_no);
+ mat[2][3] = 0.0f;
+ copy_v3_v3(mat[3], ss->cache->location);
+ mat[3][3] = 1.0f;
+ normalize_m4(mat);
+
+ float stroke_xz[2][3];
+ normalize_v3_v3(stroke_xz[0], mat[0]);
+ normalize_v3_v3(stroke_xz[1], mat[2]);
+
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
+ .stroke_xz = stroke_xz,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings);
}
static void do_grab_brush_task_cb_ex(void *__restrict userdata,
@@ -3366,28 +3422,29 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
float(*proxy)[3];
const float bstrength = ss->cache->bstrength;
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- orig_data.co,
- sqrtf(test.dist),
- orig_data.no,
- NULL,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ orig_data.co,
+ sqrtf(test.dist),
+ orig_data.no,
+ NULL,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
@@ -3419,9 +3476,9 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.grab_delta = grab_delta,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
}
static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
@@ -3440,7 +3497,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
const float bstrength = ss->cache->bstrength;
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
@@ -3466,7 +3523,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
float final_disp[3];
switch (brush->elastic_deform_type) {
case BRUSH_ELASTIC_DEFORM_GRAB:
@@ -3497,7 +3554,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
mul_v3_fl(final_disp, 1.0f - *vd.mask);
}
- mul_v3_fl(final_disp, sculpt_automasking_factor_get(ss, vd.index));
+ mul_v3_fl(final_disp, SCULPT_automasking_factor_get(ss, vd.index));
copy_v3_v3(proxy[vd.i], final_disp);
@@ -3528,12 +3585,12 @@ static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
.grab_delta = grab_delta,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings);
}
-static ePaintSymmetryAreas sculpt_get_vertex_symm_area(const float co[3])
+ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3])
{
ePaintSymmetryAreas symm_area = PAINT_SYMM_AREA_DEFAULT;
if (co[0] < 0.0f) {
@@ -3548,10 +3605,10 @@ static ePaintSymmetryAreas sculpt_get_vertex_symm_area(const float co[3])
return symm_area;
}
-static void sculpt_flip_v3_by_symm_area(float v[3],
- const ePaintSymmetryFlags symm,
- const ePaintSymmetryAreas symmarea,
- const float pivot[3])
+void SCULPT_flip_v3_by_symm_area(float v[3],
+ const ePaintSymmetryFlags symm,
+ const ePaintSymmetryAreas symmarea,
+ const float pivot[3])
{
for (char i = 0; i < 3; i++) {
ePaintSymmetryFlags symm_it = 1 << i;
@@ -3566,10 +3623,10 @@ static void sculpt_flip_v3_by_symm_area(float v[3],
}
}
-static void sculpt_flip_quat_by_symm_area(float quat[3],
- const ePaintSymmetryFlags symm,
- const ePaintSymmetryAreas symmarea,
- const float pivot[3])
+void SCULPT_flip_quat_by_symm_area(float quat[3],
+ const ePaintSymmetryFlags symm,
+ const ePaintSymmetryAreas symmarea,
+ const float pivot[3])
{
for (char i = 0; i < 3; i++) {
ePaintSymmetryFlags symm_it = 1 << i;
@@ -3584,634 +3641,92 @@ static void sculpt_flip_quat_by_symm_area(float quat[3],
}
}
-static void pose_solve_ik_chain(SculptPoseIKChain *ik_chain, const float initial_target[3])
-{
- SculptPoseIKChainSegment *segments = ik_chain->segments;
- int tot_segments = ik_chain->tot_segments;
-
- float target[3];
-
- /* Set the initial target. */
- copy_v3_v3(target, initial_target);
-
- /* Solve the positions and rotations of all segments in the chain. */
- for (int i = 0; i < tot_segments; i++) {
- float initial_orientation[3];
- float current_orientation[3];
- float current_head_position[3];
- float current_origin_position[3];
-
- /* Calculate the rotation to orientate the segment to the target from its initial state. */
- sub_v3_v3v3(current_orientation, target, segments[i].orig);
- normalize_v3(current_orientation);
- sub_v3_v3v3(initial_orientation, segments[i].initial_head, segments[i].initial_orig);
- normalize_v3(initial_orientation);
- rotation_between_vecs_to_quat(segments[i].rot, initial_orientation, current_orientation);
-
- /* Rotate the segment by calculating a new head position. */
- madd_v3_v3v3fl(current_head_position, segments[i].orig, current_orientation, segments[i].len);
-
- /* Move the origin of the segment towards the target. */
- sub_v3_v3v3(current_origin_position, target, current_head_position);
-
- /* Store the new head and origin positions to the segment. */
- copy_v3_v3(segments[i].head, current_head_position);
- add_v3_v3(segments[i].orig, current_origin_position);
-
- /* Use the origin of this segment as target for the next segment in the chain. */
- copy_v3_v3(target, segments[i].orig);
- }
-
- /* Move back the whole chain to preserve the anchor point. */
- float anchor_diff[3];
- sub_v3_v3v3(
- anchor_diff, segments[tot_segments - 1].initial_orig, segments[tot_segments - 1].orig);
-
- for (int i = 0; i < tot_segments; i++) {
- add_v3_v3(segments[i].orig, anchor_diff);
- add_v3_v3(segments[i].head, anchor_diff);
- }
-}
-
-static void pose_solve_roll_chain(SculptPoseIKChain *ik_chain,
- const Brush *brush,
- const float roll)
-{
- SculptPoseIKChainSegment *segments = ik_chain->segments;
- int tot_segments = ik_chain->tot_segments;
-
- for (int i = 0; i < tot_segments; i++) {
- float initial_orientation[3];
- float initial_rotation[4];
- float current_rotation[4];
-
- sub_v3_v3v3(initial_orientation, segments[i].initial_head, segments[i].initial_orig);
- normalize_v3(initial_orientation);
-
- /* Calculate the current roll angle using the brush curve. */
- float current_roll = roll * BKE_brush_curve_strength(brush, i, tot_segments);
-
- axis_angle_normalized_to_quat(initial_rotation, initial_orientation, 0.0f);
- axis_angle_normalized_to_quat(current_rotation, initial_orientation, current_roll);
-
- /* Store the difference of the rotations in the segment rotation. */
- rotation_between_quats_to_quat(segments[i].rot, current_rotation, initial_rotation);
- }
-}
-
-static void do_pose_brush_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
- SculptPoseIKChainSegment *segments = ik_chain->segments;
-
- PBVHVertexIter vd;
- float disp[3], new_co[3];
- float final_pos[3];
-
- SculptOrigVertData orig_data;
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- sculpt_orig_vert_data_update(&orig_data, &vd);
-
- float total_disp[3];
- zero_v3(total_disp);
-
- ePaintSymmetryAreas symm_area = sculpt_get_vertex_symm_area(orig_data.co);
-
- /* Calculate the displacement of each vertex for all the segments in the chain. */
- for (int ik = 0; ik < ik_chain->tot_segments; ik++) {
- copy_v3_v3(new_co, orig_data.co);
-
- /* Get the transform matrix for the vertex symmetry area to calculate a displacement in the
- * vertex. */
- mul_m4_v3(segments[ik].pivot_mat_inv[(int)symm_area], new_co);
- mul_m4_v3(segments[ik].trans_mat[(int)symm_area], new_co);
- mul_m4_v3(segments[ik].pivot_mat[(int)symm_area], new_co);
-
- /* Apply the segment weight of the vertex to the displacement. */
- sub_v3_v3v3(disp, new_co, orig_data.co);
- mul_v3_fl(disp, segments[ik].weights[vd.index]);
-
- /* Apply the vertex mask to the displacement. */
- float mask = vd.mask ? *vd.mask : 0.0f;
- mul_v3_fl(disp, 1.0f - mask);
-
- /* Accumulate the displacement. */
- add_v3_v3(total_disp, disp);
- }
-
- /* Apply the accumulated displacement to the vertex. */
- add_v3_v3v3(final_pos, orig_data.co, total_disp);
- copy_v3_v3(vd.co, final_pos);
-
- if (vd.mvert) {
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static void do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+void SCULPT_calc_brush_plane(
+ Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3])
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- float grab_delta[3];
- float ik_target[3];
- const ePaintSymmetryFlags symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
-
- /* The pose brush applies all enabled symmetry axis in a single iteration, so the rest can be
- * ignored. */
- if (ss->cache->mirror_symmetry_pass != 0) {
- return;
- }
-
- SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
-
- /* Solve the positions and rotations of the IK chain. */
- if (ss->cache->invert) {
- /* Roll Mode */
- /* Calculate the maximum roll. 0.02 radians per pixel works fine. */
- float roll = (ss->cache->initial_mouse[0] - ss->cache->mouse[0]) * ss->cache->bstrength *
- 0.02f;
- BKE_curvemapping_initialize(brush->curve);
- pose_solve_roll_chain(ik_chain, brush, roll);
- }
- else {
- /* IK follow target mode */
- /* Calculate the IK target. */
-
- copy_v3_v3(grab_delta, ss->cache->grab_delta);
- copy_v3_v3(ik_target, ss->cache->true_location);
- add_v3_v3(ik_target, ss->cache->grab_delta);
-
- /* Solve the IK positions */
- pose_solve_ik_chain(ik_chain, ik_target);
- }
-
- /* Flip the segment chain in all symmetry axis and calculate the transform matrices for each
- * possible combination. */
- /* This can be optimized by skipping the calculation of matrices where the symmetry is not
- * enabled. */
- for (int symm_it = 0; symm_it < PAINT_SYMM_AREAS; symm_it++) {
- for (int i = 0; i < brush->pose_ik_segments; i++) {
- float symm_rot[4];
- float symm_orig[3];
- float symm_initial_orig[3];
- ePaintSymmetryAreas symm_area = symm_it;
+ zero_v3(r_area_co);
+ zero_v3(r_area_no);
- copy_qt_qt(symm_rot, ik_chain->segments[i].rot);
- copy_v3_v3(symm_orig, ik_chain->segments[i].orig);
- copy_v3_v3(symm_initial_orig, ik_chain->segments[i].initial_orig);
-
- /* Flip the origins and rotation quats of each segment. */
- sculpt_flip_quat_by_symm_area(symm_rot, symm, symm_area, ss->cache->orig_grab_location);
- sculpt_flip_v3_by_symm_area(symm_orig, symm, symm_area, ss->cache->orig_grab_location);
- sculpt_flip_v3_by_symm_area(
- symm_initial_orig, symm, symm_area, ss->cache->orig_grab_location);
-
- /* Create the transform matrix and store it in the segment. */
- unit_m4(ik_chain->segments[i].pivot_mat[symm_it]);
- quat_to_mat4(ik_chain->segments[i].trans_mat[symm_it], symm_rot);
-
- translate_m4(ik_chain->segments[i].trans_mat[symm_it],
- symm_orig[0] - symm_initial_orig[0],
- symm_orig[1] - symm_initial_orig[1],
- symm_orig[2] - symm_initial_orig[2]);
- translate_m4(
- ik_chain->segments[i].pivot_mat[symm_it], symm_orig[0], symm_orig[1], symm_orig[2]);
- invert_m4_m4(ik_chain->segments[i].pivot_mat_inv[symm_it],
- ik_chain->segments[i].pivot_mat[symm_it]);
- }
- }
-
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .grab_delta = grab_delta,
- };
-
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings);
-}
-
-typedef struct PoseGrowFactorTLSData {
- float pos_avg[3];
- int pos_count;
-} PoseGrowFactorTLSData;
-
-static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- PoseGrowFactorTLSData *gftd = tls->userdata_chunk;
- SculptSession *ss = data->ob->sculpt;
- const char symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- SculptVertexNeighborIter ni;
- float max = 0.0f;
-
- /* Grow the factor. */
- sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni)
- {
- float vmask_f = data->prev_mask[ni.index];
- max = MAX2(vmask_f, max);
- }
- sculpt_vertex_neighbors_iter_end(ni);
-
- /* Keep the count of the vertices that where added to the factors in this grow iteration. */
- if (max > data->prev_mask[vd.index]) {
- data->pose_factor[vd.index] = max;
- if (check_vertex_pivot_symmetry(vd.co, data->pose_initial_co, symm)) {
- add_v3_v3(gftd->pos_avg, vd.co);
- gftd->pos_count++;
- }
- }
- }
-
- BKE_pbvh_vertex_iter_end;
-}
+ if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0 &&
+ ss->cache->tile_pass == 0 &&
+ (ss->cache->first_time || !(brush->flag & BRUSH_ORIGINAL_PLANE) ||
+ !(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
+ switch (brush->sculpt_plane) {
+ case SCULPT_DISP_DIR_VIEW:
+ copy_v3_v3(r_area_no, ss->cache->true_view_normal);
+ break;
-static void pose_brush_grow_factor_reduce(const void *__restrict UNUSED(userdata),
- void *__restrict chunk_join,
- void *__restrict chunk)
-{
- PoseGrowFactorTLSData *join = chunk_join;
- PoseGrowFactorTLSData *gftd = chunk;
- add_v3_v3(join->pos_avg, gftd->pos_avg);
- join->pos_count += gftd->pos_count;
-}
+ case SCULPT_DISP_DIR_X:
+ ARRAY_SET_ITEMS(r_area_no, 1.0f, 0.0f, 0.0f);
+ break;
-/* Grow the factor until its boundary is near to the offset pose origin or outside the target
- * distance. */
-static void sculpt_pose_grow_pose_factor(Sculpt *sd,
- Object *ob,
- SculptSession *ss,
- float pose_origin[3],
- float pose_target[3],
- float max_len,
- float *r_pose_origin,
- float *pose_factor)
-{
- PBVHNode **nodes;
- PBVH *pbvh = ob->sculpt->pbvh;
- int totnode;
+ case SCULPT_DISP_DIR_Y:
+ ARRAY_SET_ITEMS(r_area_no, 0.0f, 1.0f, 0.0f);
+ break;
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = nodes,
- .totnode = totnode,
- .pose_factor = pose_factor,
- };
+ case SCULPT_DISP_DIR_Z:
+ ARRAY_SET_ITEMS(r_area_no, 0.0f, 0.0f, 1.0f);
+ break;
- data.pose_initial_co = pose_target;
- PBVHParallelSettings settings;
- PoseGrowFactorTLSData gftd;
- gftd.pos_count = 0;
- zero_v3(gftd.pos_avg);
- BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_reduce = pose_brush_grow_factor_reduce;
- settings.userdata_chunk = &gftd;
- settings.userdata_chunk_size = sizeof(PoseGrowFactorTLSData);
-
- bool grow_next_iteration = true;
- float prev_len = FLT_MAX;
- data.prev_mask = MEM_mallocN(sculpt_vertex_count_get(ss) * sizeof(float), "prev mask");
- while (grow_next_iteration) {
- zero_v3(gftd.pos_avg);
- gftd.pos_count = 0;
- memcpy(data.prev_mask, pose_factor, sculpt_vertex_count_get(ss) * sizeof(float));
- BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings);
-
- if (gftd.pos_count != 0) {
- mul_v3_fl(gftd.pos_avg, 1.0f / (float)gftd.pos_count);
- if (pose_origin) {
- /* Test with pose origin. Used when growing the factors to compensate the Origin Offset. */
- /* Stop when the factor's avg_pos starts moving away from the origin instead of getting
- * closer to it. */
- float len = len_v3v3(gftd.pos_avg, pose_origin);
- if (len < prev_len) {
- prev_len = len;
- grow_next_iteration = true;
- }
- else {
- grow_next_iteration = false;
- memcpy(pose_factor, data.prev_mask, sculpt_vertex_count_get(ss) * sizeof(float));
- }
- }
- else {
- /* Test with length. Used to calculate the origin positions of the IK chain. */
- /* Stops when the factors have grown enough to generate a new segment origin. */
- float len = len_v3v3(gftd.pos_avg, pose_target);
- if (len < max_len) {
- prev_len = len;
- grow_next_iteration = true;
- }
- else {
- grow_next_iteration = false;
- if (r_pose_origin) {
- copy_v3_v3(r_pose_origin, gftd.pos_avg);
- }
- memcpy(pose_factor, data.prev_mask, sculpt_vertex_count_get(ss) * sizeof(float));
+ case SCULPT_DISP_DIR_AREA:
+ calc_area_normal_and_center(sd, ob, nodes, totnode, r_area_no, r_area_co);
+ if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
+ project_plane_v3_v3v3(r_area_no, r_area_no, ss->cache->view_normal);
+ normalize_v3(r_area_no);
}
- }
- }
- else {
- if (r_pose_origin) {
- copy_v3_v3(r_pose_origin, pose_target);
- }
- grow_next_iteration = false;
- }
- }
- MEM_freeN(data.prev_mask);
-
- MEM_SAFE_FREE(nodes);
-}
+ break;
-static bool sculpt_pose_brush_is_vertex_inside_brush_radius(const float vertex[3],
- const float br_co[3],
- float radius,
- char symm)
-{
- for (char i = 0; i <= symm; ++i) {
- if (is_symmetry_iteration_valid(i, symm)) {
- float location[3];
- flip_v3_v3(location, br_co, (char)i);
- if (len_v3v3(location, vertex) < radius) {
- return true;
- }
+ default:
+ break;
}
- }
- return false;
-}
-
-typedef struct PoseFloodFillData {
- float pose_initial_co[3];
- float radius;
- int symm;
- float *pose_factor;
- float pose_origin[3];
- int tot_co;
-} PoseFloodFillData;
-
-static bool pose_floodfill_cb(
- SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
-{
- PoseFloodFillData *data = userdata;
-
- if (data->pose_factor) {
- data->pose_factor[to_v] = 1.0f;
- }
-
- const float *co = sculpt_vertex_co_get(ss, to_v);
- if (sculpt_pose_brush_is_vertex_inside_brush_radius(
- co, data->pose_initial_co, data->radius, data->symm)) {
- return true;
- }
- else if (check_vertex_pivot_symmetry(co, data->pose_initial_co, data->symm)) {
- if (!is_duplicate) {
- add_v3_v3(data->pose_origin, co);
- data->tot_co++;
+ /* For flatten center. */
+ /* fFlatten center has not been calculated yet if we are not using the area normal. */
+ if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA) {
+ calc_area_center(sd, ob, nodes, totnode, r_area_co);
}
- }
- return false;
-}
-
-/* Calculate the pose origin and (Optionaly the pose factor) that is used when using the pose brush
- *
- * r_pose_origin must be a valid pointer. the r_pose_factor is optional. When set to NULL it won't
- * be calculated. */
-void sculpt_pose_calc_pose_data(Sculpt *sd,
- Object *ob,
- SculptSession *ss,
- float initial_location[3],
- float radius,
- float pose_offset,
- float *r_pose_origin,
- float *r_pose_factor)
-{
- sculpt_vertex_random_access_init(ss);
-
- /* Calculate the pose rotation point based on the boundaries of the brush factor. */
- SculptFloodFill flood;
- sculpt_floodfill_init(ss, &flood);
- sculpt_floodfill_add_active(sd, ob, ss, &flood, (r_pose_factor) ? radius : 0.0f);
-
- PoseFloodFillData fdata = {
- .radius = radius,
- .symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL,
- .pose_factor = r_pose_factor,
- .tot_co = 0,
- };
- zero_v3(fdata.pose_origin);
- copy_v3_v3(fdata.pose_initial_co, initial_location);
- sculpt_floodfill_execute(ss, &flood, pose_floodfill_cb, &fdata);
- sculpt_floodfill_free(&flood);
-
- if (fdata.tot_co > 0) {
- mul_v3_fl(fdata.pose_origin, 1.0f / (float)fdata.tot_co);
- }
-
- /* Offset the pose origin */
- float pose_d[3];
- sub_v3_v3v3(pose_d, fdata.pose_origin, fdata.pose_initial_co);
- normalize_v3(pose_d);
- madd_v3_v3fl(fdata.pose_origin, pose_d, radius * pose_offset);
- copy_v3_v3(r_pose_origin, fdata.pose_origin);
-
- /* Do the initial grow of the factors to get the first segment of the chain with Origin Offset.
- */
- if (pose_offset != 0.0f && r_pose_factor) {
- sculpt_pose_grow_pose_factor(
- sd, ob, ss, fdata.pose_origin, fdata.pose_origin, 0, NULL, r_pose_factor);
- }
-}
-
-static void pose_brush_init_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- SculptVertexNeighborIter ni;
- float avg = 0.0f;
- int total = 0.0f;
- sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni)
- {
- avg += data->pose_factor[ni.index];
- total++;
+ /* For area normal. */
+ if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
+ copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
}
- sculpt_vertex_neighbors_iter_end(ni);
-
- if (total > 0) {
- data->pose_factor[vd.index] = avg / total;
+ else {
+ copy_v3_v3(ss->cache->sculpt_normal, r_area_no);
}
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-void sculpt_pose_ik_chain_free(SculptPoseIKChain *ik_chain)
-{
- for (int i = 0; i < ik_chain->tot_segments; i++) {
- MEM_SAFE_FREE(ik_chain->segments[i].weights);
- }
- MEM_SAFE_FREE(ik_chain->segments);
- MEM_SAFE_FREE(ik_chain);
-}
-SculptPoseIKChain *sculpt_pose_ik_chain_init(Sculpt *sd,
- Object *ob,
- SculptSession *ss,
- Brush *br,
- const float initial_location[3],
- const float radius)
-{
-
- float chain_end[3];
- float chain_segment_len = len_v3v3(initial_location, chain_end) / br->pose_ik_segments;
- chain_segment_len = radius * (1.0f + br->pose_offset);
- float next_chain_segment_target[3];
-
- int totvert = sculpt_vertex_count_get(ss);
- int nearest_vertex_index = sculpt_nearest_vertex_get(sd, ob, initial_location, FLT_MAX, true);
-
- /* Init the buffers used to keep track of the changes in the pose factors as more segments are
- * added to the IK chain. */
-
- /* This stores the whole pose factors values as they grow through the mesh. */
- float *pose_factor_grow = MEM_callocN(totvert * sizeof(float), "Pose Factor Grow");
-
- /* This stores the previous status of the factors when growing a new iteration. */
- float *pose_factor_grow_prev = MEM_callocN(totvert * sizeof(float),
- "Pose Factor Grow Prev Iteration");
-
- pose_factor_grow[nearest_vertex_index] = 1.0f;
-
- /* Init the IK chain with empty weights. */
- SculptPoseIKChain *ik_chain = MEM_callocN(sizeof(SculptPoseIKChain), "Pose IK Chain");
- ik_chain->tot_segments = br->pose_ik_segments;
- ik_chain->segments = MEM_callocN(ik_chain->tot_segments * sizeof(SculptPoseIKChainSegment),
- "Pose IK Chain Segments");
- for (int i = 0; i < br->pose_ik_segments; i++) {
- ik_chain->segments[i].weights = MEM_callocN(totvert * sizeof(float), "Pose IK weights");
- }
-
- /* Calculate the first segment in the chain using the brush radius and the pose origin offset. */
- copy_v3_v3(next_chain_segment_target, initial_location);
- sculpt_pose_calc_pose_data(sd,
- ob,
- ss,
- next_chain_segment_target,
- radius,
- br->pose_offset,
- ik_chain->segments[0].orig,
- pose_factor_grow);
-
- copy_v3_v3(next_chain_segment_target, ik_chain->segments[0].orig);
-
- /* Init the weights of this segment and store the status of the pose factors to start calculating
- * new segment origins. */
- for (int j = 0; j < totvert; j++) {
- ik_chain->segments[0].weights[j] = pose_factor_grow[j];
- pose_factor_grow_prev[j] = pose_factor_grow[j];
- }
-
- /* Calculate the next segments in the chain growing the pose factors. */
- for (int i = 1; i < ik_chain->tot_segments; i++) {
-
- /* Grow the factors to get the new segment origin. */
- sculpt_pose_grow_pose_factor(sd,
- ob,
- ss,
- NULL,
- next_chain_segment_target,
- chain_segment_len,
- ik_chain->segments[i].orig,
- pose_factor_grow);
- copy_v3_v3(next_chain_segment_target, ik_chain->segments[i].orig);
-
- /* Create the weights for this segment from the difference between the previous grow factor
- * iteration an the current iteration. */
- for (int j = 0; j < totvert; j++) {
- ik_chain->segments[i].weights[j] = pose_factor_grow[j] - pose_factor_grow_prev[j];
- /* Store the current grow factor status for the next interation. */
- pose_factor_grow_prev[j] = pose_factor_grow[j];
- }
- }
-
- /* Init the origin/head pairs of all the segments from the calculated origins. */
- float origin[3];
- float head[3];
- for (int i = 0; i < ik_chain->tot_segments; i++) {
- if (i == 0) {
- copy_v3_v3(head, initial_location);
- copy_v3_v3(origin, ik_chain->segments[i].orig);
+ /* For flatten center. */
+ if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_PLANE)) {
+ copy_v3_v3(r_area_co, ss->cache->last_center);
}
else {
- copy_v3_v3(head, ik_chain->segments[i - 1].orig);
- copy_v3_v3(origin, ik_chain->segments[i].orig);
+ copy_v3_v3(ss->cache->last_center, r_area_co);
}
- copy_v3_v3(ik_chain->segments[i].orig, origin);
- copy_v3_v3(ik_chain->segments[i].initial_orig, origin);
- copy_v3_v3(ik_chain->segments[i].initial_head, head);
- ik_chain->segments[i].len = len_v3v3(head, origin);
}
+ else {
+ /* For area normal. */
+ copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
- MEM_freeN(pose_factor_grow);
- MEM_freeN(pose_factor_grow_prev);
-
- return ik_chain;
-}
+ /* For flatten center. */
+ copy_v3_v3(r_area_co, ss->cache->last_center);
-static void sculpt_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br)
-{
- PBVHNode **nodes;
- PBVH *pbvh = ob->sculpt->pbvh;
- int totnode;
+ /* For area normal. */
+ flip_v3(r_area_no, ss->cache->mirror_symmetry_pass);
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ /* For flatten center. */
+ flip_v3(r_area_co, ss->cache->mirror_symmetry_pass);
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .brush = br,
- .nodes = nodes,
- };
+ /* For area normal. */
+ mul_m4_v3(ss->cache->symm_rot_mat, r_area_no);
- /* Init the IK chain that is going to be used to deform the vertices. */
- ss->cache->pose_ik_chain = sculpt_pose_ik_chain_init(
- sd, ob, ss, br, ss->cache->true_location, ss->cache->radius);
+ /* For flatten center. */
+ mul_m4_v3(ss->cache->symm_rot_mat, r_area_co);
- /* Smooth the weights of each segment for cleaner deformation. */
- for (int ik = 0; ik < ss->cache->pose_ik_chain->tot_segments; ik++) {
- data.pose_factor = ss->cache->pose_ik_chain->segments[ik].weights;
- for (int i = 0; i < br->pose_smooth_iterations; i++) {
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings);
- }
+ /* Shift the plane for the current tile. */
+ add_v3_v3(r_area_co, ss->cache->plane_offset);
}
-
- MEM_SAFE_FREE(nodes);
}
static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
@@ -4230,21 +3745,22 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -4276,9 +3792,9 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
.cono = cono,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings);
}
static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
@@ -4303,25 +3819,26 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
- /* negative pinch will inflate, helps maintain volume */
+ /* Negative pinch will inflate, helps maintain volume. */
if (do_pinch) {
float delta_pinch_init[3], delta_pinch[3];
@@ -4330,7 +3847,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
project_plane_v3_v3v3(delta_pinch, delta_pinch, ss->cache->true_view_normal);
}
- /* important to calculate based on the grabbed location
+ /* Important to calculate based on the grabbed location
* (intentionally ignore fade here). */
add_v3_v3(delta_pinch, grab_delta);
@@ -4339,10 +3856,10 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
copy_v3_v3(delta_pinch_init, delta_pinch);
float pinch_fade = pinch * fade;
- /* when reducing, scale reduction back by how close to the center we are,
- * so we don't pinch into nothingness */
+ /* When reducing, scale reduction back by how close to the center we are,
+ * so we don't pinch into nothingness. */
if (pinch > 0.0f) {
- /* square to have even less impact for close vertices */
+ /* Square to have even less impact for close vertices. */
pinch_fade *= pow2f(min_ff(1.0f, len_v3(delta_pinch) / ss->cache->radius));
}
mul_v3_fl(delta_pinch, 1.0f + pinch_fade);
@@ -4375,7 +3892,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
- if (bstrength < 0) {
+ if (bstrength < 0.0f) {
negate_v3(grab_delta);
}
@@ -4383,7 +3900,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
sculpt_project_v3_normal_align(ss, ss->cache->normal_weight, grab_delta);
}
- /* optionally pinch while painting */
+ /* Optionally pinch while painting. */
if (brush->crease_pinch_factor != 0.5f) {
sculpt_project_v3_cache_init(&spvc, grab_delta);
}
@@ -4397,9 +3914,9 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
.grab_delta = grab_delta,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings);
}
static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
@@ -4416,28 +3933,29 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
float(*proxy)[3];
const float bstrength = ss->cache->bstrength;
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- orig_data.co,
- sqrtf(test.dist),
- orig_data.no,
- NULL,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ orig_data.co,
+ sqrtf(test.dist),
+ orig_data.no,
+ NULL,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -4469,9 +3987,9 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
.cono = cono,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings);
}
static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
@@ -4488,29 +4006,30 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
float(*proxy)[3];
const float bstrength = ss->cache->bstrength;
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
float vec[3], rot[3][3];
- const float fade = bstrength * tex_strength(ss,
- brush,
- orig_data.co,
- sqrtf(test.dist),
- orig_data.no,
- NULL,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ orig_data.co,
+ sqrtf(test.dist),
+ orig_data.no,
+ NULL,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
sub_v3_v3v3(vec, orig_data.co, ss->cache->location);
axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade);
@@ -4542,9 +4061,9 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
.angle = angle,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings);
}
static void do_layer_brush_task_cb_ex(void *__restrict userdata,
@@ -4555,64 +4074,83 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
SculptSession *ss = data->ob->sculpt;
Sculpt *sd = data->sd;
const Brush *brush = data->brush;
- const float *offset = data->offset;
+
+ const bool use_persistent_base = ss->layer_base && brush->flag & BRUSH_PERSISTENT;
PBVHVertexIter vd;
SculptOrigVertData orig_data;
- float *layer_disp;
const float bstrength = ss->cache->bstrength;
- const float lim = (bstrength < 0) ? -data->brush->height : data->brush->height;
- /* XXX: layer brush needs conversion to proxy but its more complicated */
- /* proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */
-
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
-
- /* Why does this have to be thread-protected? */
- BLI_mutex_lock(&data->mutex);
- layer_disp = BKE_pbvh_node_layer_disp_get(ss->pbvh, data->nodes[n]);
- BLI_mutex_unlock(&data->mutex);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- sculpt_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
- float *disp = &layer_disp[vd.i];
- float val[3];
-
- *disp += fade;
+ const float fade = SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
- /* Don't let the displacement go past the limit */
- if ((lim < 0.0f && *disp < lim) || (lim >= 0.0f && *disp > lim)) {
- *disp = lim;
+ const int vi = vd.index;
+ float *disp_factor;
+ if (use_persistent_base) {
+ disp_factor = &ss->layer_base[vi].disp;
+ }
+ else {
+ disp_factor = &ss->cache->layer_displacement_factor[vi];
}
- mul_v3_v3fl(val, offset, *disp);
+ /* When using persistent base, the layer brush Ctrl invert mode resets the height of the
+ * layer to 0. This makes possible to clean edges of previously added layers on top of the
+ * base. */
+ /* The main direction of the layers is inverted using the regular brush strength with the
+ * brush direction property. */
+ if (use_persistent_base && ss->cache->invert) {
+ (*disp_factor) += fabsf(fade * bstrength * (*disp_factor)) *
+ ((*disp_factor) > 0.0f ? -1.0f : 1.0f);
+ }
+ else {
+ (*disp_factor) += fade * bstrength * (1.05f - fabsf(*disp_factor));
+ }
+ if (vd.mask) {
+ const float clamp_mask = 1.0f - *vd.mask;
+ CLAMP(*disp_factor, -clamp_mask, clamp_mask);
+ }
+ else {
+ CLAMP(*disp_factor, -1.0f, 1.0f);
+ }
- if (!ss->multires && !ss->bm && ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) {
- int index = vd.vert_indices[vd.i];
+ float final_co[3];
+ float normal[3];
- /* persistent base */
- add_v3_v3(val, ss->layer_co[index]);
+ if (use_persistent_base) {
+ copy_v3_v3(normal, ss->layer_base[vi].no);
+ mul_v3_fl(normal, brush->height);
+ madd_v3_v3v3fl(final_co, ss->layer_base[vi].co, normal, *disp_factor);
}
else {
- add_v3_v3(val, orig_data.co);
+ normal_short_to_float_v3(normal, orig_data.no);
+ mul_v3_fl(normal, brush->height);
+ madd_v3_v3v3fl(final_co, orig_data.co, normal, *disp_factor);
}
- sculpt_clip(sd, ss, vd.co, val);
+ float vdisp[3];
+ sub_v3_v3v3(vdisp, final_co, vd.co);
+ mul_v3_fl(vdisp, fabsf(fade));
+ add_v3_v3v3(final_co, vd.co, vdisp);
+
+ SCULPT_clip(sd, ss, vd.co, final_co);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@@ -4626,24 +4164,22 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- float offset[3];
- mul_v3_v3v3(offset, ss->cache->scale, ss->cache->sculpt_normal_symm);
+ if (ss->cache->layer_displacement_factor == NULL) {
+ ss->cache->layer_displacement_factor = MEM_callocN(sizeof(float) * SCULPT_vertex_count_get(ss),
+ "layer displacement factor");
+ }
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
- .offset = offset,
};
- BLI_mutex_init(&data.mutex);
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings);
-
- BLI_mutex_end(&data.mutex);
+ BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings);
}
static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
@@ -4661,21 +4197,22 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
float val[3];
if (vd.fno) {
@@ -4707,97 +4244,12 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
.nodes = nodes,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings);
-}
-
-static void calc_sculpt_plane(
- Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3])
-{
- SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0 &&
- ss->cache->tile_pass == 0 &&
- (ss->cache->first_time || !(brush->flag & BRUSH_ORIGINAL_PLANE) ||
- !(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
- switch (brush->sculpt_plane) {
- case SCULPT_DISP_DIR_VIEW:
- copy_v3_v3(r_area_no, ss->cache->true_view_normal);
- break;
-
- case SCULPT_DISP_DIR_X:
- ARRAY_SET_ITEMS(r_area_no, 1, 0, 0);
- break;
-
- case SCULPT_DISP_DIR_Y:
- ARRAY_SET_ITEMS(r_area_no, 0, 1, 0);
- break;
-
- case SCULPT_DISP_DIR_Z:
- ARRAY_SET_ITEMS(r_area_no, 0, 0, 1);
- break;
-
- case SCULPT_DISP_DIR_AREA:
- calc_area_normal_and_center(sd, ob, nodes, totnode, r_area_no, r_area_co);
- if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
- project_plane_v3_v3v3(r_area_no, r_area_no, ss->cache->view_normal);
- normalize_v3(r_area_no);
- }
- break;
-
- default:
- break;
- }
-
- /* for flatten center */
- /* flatten center has not been calculated yet if we are not using the area normal */
- if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA) {
- calc_area_center(sd, ob, nodes, totnode, r_area_co);
- }
-
- /* for area normal */
- if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
- copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
- }
- else {
- copy_v3_v3(ss->cache->sculpt_normal, r_area_no);
- }
-
- /* for flatten center */
- if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_PLANE)) {
- copy_v3_v3(r_area_co, ss->cache->last_center);
- }
- else {
- copy_v3_v3(ss->cache->last_center, r_area_co);
- }
- }
- else {
- /* for area normal */
- copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
-
- /* for flatten center */
- copy_v3_v3(r_area_co, ss->cache->last_center);
-
- /* for area normal */
- flip_v3(r_area_no, ss->cache->mirror_symmetry_pass);
-
- /* for flatten center */
- flip_v3(r_area_co, ss->cache->mirror_symmetry_pass);
-
- /* for area normal */
- mul_m4_v3(ss->cache->symm_rot_mat, r_area_no);
-
- /* for flatten center */
- mul_m4_v3(ss->cache->symm_rot_mat, r_area_co);
-
- /* shift the plane for the current tile */
- add_v3_v3(r_area_co, ss->cache->plane_offset);
- }
+ BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings);
}
-static int plane_trim(const StrokeCache *cache, const Brush *brush, const float val[3])
+int SCULPT_plane_trim(const StrokeCache *cache, const Brush *brush, const float val[3])
{
return (!(brush->flag & BRUSH_PLANE_TRIM) ||
((dot_v3v3(val, val) <= cache->radius_squared * cache->plane_trim_squared)));
@@ -4812,13 +4264,13 @@ static bool plane_point_side_flip(const float co[3], const float plane[4], const
return d <= 0.0f;
}
-static int plane_point_side(const float co[3], const float plane[4])
+int SCULPT_plane_point_side(const float co[3], const float plane[4])
{
float d = plane_point_side_v3(plane, co);
return d <= 0.0f;
}
-static float get_offset(Sculpt *sd, SculptSession *ss)
+float SCULPT_brush_plane_offset_get(Sculpt *sd, SculptSession *ss)
{
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -4848,8 +4300,9 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
@@ -4863,16 +4316,16 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
sub_v3_v3v3(val, intr, vd.co);
- if (plane_trim(ss->cache, brush, val)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ if (SCULPT_plane_trim(ss->cache, brush, val)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -4895,11 +4348,11 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
float area_no[3];
float area_co[3];
- float offset = get_offset(sd, ss);
+ float offset = SCULPT_brush_plane_offset_get(sd, ss);
float displace;
float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
+ SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
displace = radius * offset;
@@ -4916,9 +4369,9 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
.area_co = area_co,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings);
}
/* -------------------------------------------------------------------- */
@@ -4945,10 +4398,10 @@ static void calc_clay_surface_task_cb(void *__restrict userdata,
PBVHVertexIter vd;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, brush->falloff_shape);
- /* Apply the brush normal radius to the test before sampling */
+ /* Apply the brush normal radius to the test before sampling. */
float test_radius = sqrtf(test.radius_squared);
test_radius *= brush->normal_radius_factor;
test.radius_squared = test_radius * test_radius;
@@ -4994,7 +4447,6 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
const Brush *brush = data->brush;
const float *area_no = data->area_no;
const float *area_co = data->area_co;
- const float hardness = 0.65f;
PBVHVertexIter vd;
float(*proxy)[3];
@@ -5003,8 +4455,9 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
@@ -5017,20 +4470,15 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
sub_v3_v3v3(val, intr, vd.co);
- float dist = sqrtf(test.dist);
- float p = dist / ss->cache->radius;
- p = (p - hardness) / (1.0f - hardness);
- CLAMP(p, 0.0f, 1.0f);
- dist *= p;
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- dist,
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5051,14 +4499,14 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
const float initial_radius = fabsf(ss->cache->initial_radius);
bool flip = ss->cache->bstrength < 0.0f;
- float offset = get_offset(sd, ss);
+ float offset = SCULPT_brush_plane_offset_get(sd, ss);
float displace;
float area_no[3];
float area_co[3];
float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
+ SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
SculptThreadedTaskData sample_data = {
.sd = NULL,
@@ -5072,13 +4520,13 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
ClaySampleData csd = {{0}};
- PBVHParallelSettings sample_settings;
+ TaskParallelSettings sample_settings;
BKE_pbvh_parallel_range_settings(&sample_settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
sample_settings.func_reduce = calc_clay_surface_reduce;
sample_settings.userdata_chunk = &csd;
sample_settings.userdata_chunk_size = sizeof(ClaySampleData);
- BKE_pbvh_parallel_range(0, totnode, &sample_data, calc_clay_surface_task_cb, &sample_settings);
+ BLI_task_parallel_range(0, totnode, &sample_data, calc_clay_surface_task_cb, &sample_settings);
float d_offset = (csd.plane_dist[0] + csd.plane_dist[1]);
d_offset = min_ff(radius, d_offset);
@@ -5103,167 +4551,57 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.area_co = area_co,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings);
}
-/* -------------------------------------------------------------------- */
-
-/** \name Sculpt Multiplane Scrape Brush
- * \{ */
-
-typedef struct MultiplaneScrapeSampleData {
- float area_cos[2][3];
- float area_nos[2][3];
- int area_count[2];
-} MultiplaneScrapeSampleData;
-
-static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict tls)
+static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
const Brush *brush = data->brush;
- MultiplaneScrapeSampleData *mssd = tls->userdata_chunk;
float(*mat)[4] = data->mat;
+ const float *area_no_sp = data->area_no_sp;
+ const float *area_co = data->area_co;
PBVHVertexIter vd;
-
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
- ss, &test, brush->falloff_shape);
-
- /* Apply the brush normal radius to the test before sampling */
- float test_radius = sqrtf(test.radius_squared);
- test_radius *= brush->normal_radius_factor;
- test.radius_squared = test_radius * test_radius;
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
-
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- float local_co[3];
- float normal[3];
- if (vd.no) {
- normal_short_to_float_v3(normal, vd.no);
- }
- else {
- copy_v3_v3(normal, vd.fno);
- }
- mul_v3_m4v3(local_co, mat, vd.co);
- /* Use the brush falloff to weight the sampled normals */
- const float fade = tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
-
- /* Sample the normal and area of the +X and -X axis individually */
- if (local_co[0] > 0.0f) {
- madd_v3_v3fl(mssd->area_nos[0], normal, fade);
- add_v3_v3(mssd->area_cos[0], vd.co);
- mssd->area_count[0]++;
- }
- else {
- madd_v3_v3fl(mssd->area_nos[1], normal, fade);
- add_v3_v3(mssd->area_cos[1], vd.co);
- mssd->area_count[1]++;
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
-}
-
-static void calc_multiplane_scrape_surface_reduce(const void *__restrict UNUSED(userdata),
- void *__restrict chunk_join,
- void *__restrict chunk)
-{
- MultiplaneScrapeSampleData *join = chunk_join;
- MultiplaneScrapeSampleData *mssd = chunk;
-
- add_v3_v3(join->area_cos[0], mssd->area_cos[0]);
- add_v3_v3(join->area_cos[1], mssd->area_cos[1]);
-
- add_v3_v3(join->area_nos[0], mssd->area_nos[0]);
- add_v3_v3(join->area_nos[1], mssd->area_nos[1]);
-
- join->area_count[0] += mssd->area_count[0];
- join->area_count[1] += mssd->area_count[1];
-}
-
-static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- const Brush *brush = data->brush;
- float(*mat)[4] = data->mat;
- float(*scrape_planes)[4] = data->multiplane_scrape_planes;
-
- float angle = data->multiplane_scrape_angle;
-
- PBVHVertexIter vd;
float(*proxy)[3];
- const float bstrength = fabsf(ss->cache->bstrength);
+ const bool flip = (ss->cache->bstrength < 0.0f);
+ const float bstrength = flip ? -ss->cache->bstrength : ss->cache->bstrength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
- ss, &test, data->brush->falloff_shape);
+ SCULPT_brush_test_init(ss, &test);
+ plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
-
- if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- float local_co[3];
- bool deform = false;
-
- mul_v3_m4v3(local_co, mat, vd.co);
-
- if (local_co[0] > 0.0f) {
- deform = !plane_point_side(vd.co, scrape_planes[0]);
- }
- else {
- deform = !plane_point_side(vd.co, scrape_planes[1]);
- }
-
- if (angle < 0.0f) {
- deform = true;
- }
-
- if (deform) {
+ if (SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness)) {
+ if (plane_point_side_flip(vd.co, test.plane_tool, flip)) {
float intr[3];
float val[3];
- if (local_co[0] > 0.0f) {
- closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co);
- }
- else {
- closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co);
- }
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
sub_v3_v3v3(val, intr, vd.co);
- if (plane_trim(ss->cache, brush, val)) {
- /* Deform the local space along the Y axis to avoid artifacts on curved strokes */
- /* This produces a not round brush tip */
- local_co[1] *= 2.0f;
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- len_v3(local_co),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+
+ if (SCULPT_plane_trim(ss->cache, brush, val)) {
+ /* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */
+ const float fade = bstrength *
+ SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ ss->cache->radius * test.dist,
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5277,33 +4615,38 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
const bool flip = (ss->cache->bstrength < 0.0f);
const float radius = flip ? -ss->cache->radius : ss->cache->radius;
- const float offset = get_offset(sd, ss);
- const float displace = -radius * offset;
+ const float offset = SCULPT_brush_plane_offset_get(sd, ss);
+ const float displace = radius * (0.18f + offset);
- float area_no_sp[3]; /* the sculpt-plane normal (whatever its set to) */
- float area_no[3]; /* geometry normal */
+ /* The sculpt-plane normal (whatever its set to). */
+ float area_no_sp[3];
+
+ /* Geometry normal */
+ float area_no[3];
float area_co[3];
float temp[3];
float mat[4][4];
+ float scale[4][4];
+ float tmat[4][4];
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
+ SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
- calc_area_normal(sd, ob, nodes, totnode, area_no);
+ SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no);
}
else {
copy_v3_v3(area_no, area_no_sp);
}
- /* delay the first daub because grab delta is not setup */
+ /* Delay the first daub because grab delta is not setup. */
if (ss->cache->first_time) {
return;
}
@@ -5316,161 +4659,64 @@ static void do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes,
mul_v3_fl(temp, displace);
add_v3_v3(area_co, temp);
- /* Init brush local space matrix */
+ /* Init brush local space matrix. */
cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
- mat[0][3] = 0;
+ mat[0][3] = 0.0f;
cross_v3_v3v3(mat[1], area_no, mat[0]);
- mat[1][3] = 0;
+ mat[1][3] = 0.0f;
copy_v3_v3(mat[2], area_no);
- mat[2][3] = 0;
+ mat[2][3] = 0.0f;
copy_v3_v3(mat[3], ss->cache->location);
- mat[3][3] = 1;
+ mat[3][3] = 1.0f;
normalize_m4(mat);
- invert_m4(mat);
-
- float angle = brush->multiplane_scrape_angle;
-
- /* Update matrix for the cursor preview */
- if (ss->cache->mirror_symmetry_pass == 0) {
- copy_m4_m4(ss->cache->stroke_local_mat, mat);
- }
-
- /* Dynamic mode */
-
- if (brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_DYNAMIC) {
- /* Sample the individual normal and area center of the two areas at both sides of the cursor */
- SculptThreadedTaskData sample_data = {
- .sd = NULL,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .totnode = totnode,
- .mat = mat,
- };
-
- MultiplaneScrapeSampleData mssd = {{{0}}};
-
- PBVHParallelSettings sample_settings;
- BKE_pbvh_parallel_range_settings(&sample_settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- sample_settings.func_reduce = calc_multiplane_scrape_surface_reduce;
- sample_settings.userdata_chunk = &mssd;
- sample_settings.userdata_chunk_size = sizeof(MultiplaneScrapeSampleData);
-
- BKE_pbvh_parallel_range(
- 0, totnode, &sample_data, calc_multiplane_scrape_surface_task_cb, &sample_settings);
- float sampled_plane_normals[2][3];
- float sampled_plane_co[2][3];
- float sampled_cv[2][3];
- float mid_co[3];
-
- /* Use the area center of both planes to detect if we are sculpting along a concave or convex
- * edge */
- mul_v3_v3fl(sampled_plane_co[0], mssd.area_cos[0], 1.0f / (float)mssd.area_count[0]);
- mul_v3_v3fl(sampled_plane_co[1], mssd.area_cos[1], 1.0f / (float)mssd.area_count[1]);
- mid_v3_v3v3(mid_co, sampled_plane_co[0], sampled_plane_co[1]);
-
- /* Calculate the scrape planes angle based on the sampled normals */
- mul_v3_v3fl(sampled_plane_normals[0], mssd.area_nos[0], 1.0f / (float)mssd.area_count[0]);
- mul_v3_v3fl(sampled_plane_normals[1], mssd.area_nos[1], 1.0f / (float)mssd.area_count[1]);
- normalize_v3(sampled_plane_normals[0]);
- normalize_v3(sampled_plane_normals[1]);
-
- float sampled_angle = angle_v3v3(sampled_plane_normals[0], sampled_plane_normals[1]);
- copy_v3_v3(sampled_cv[0], area_no);
- sub_v3_v3v3(sampled_cv[1], ss->cache->location, mid_co);
-
- sampled_angle += DEG2RADF(brush->multiplane_scrape_angle) * ss->cache->pressure;
-
- /* Invert the angle if we are sculpting along a concave edge */
- if (dot_v3v3(sampled_cv[0], sampled_cv[1]) < 0.0f) {
- sampled_angle = -sampled_angle;
- }
-
- /* In dynamic mode, set the angle to 0 when inverting the brush, so you can trim plane surfaces
- * without changing the brush */
- if (flip) {
- sampled_angle = 0.0f;
- }
- else {
- copy_v3_v3(area_co, ss->cache->location);
- }
-
- angle = RAD2DEGF(sampled_angle);
- }
- else {
-
- /* Standard mode: Scrape with the brush property fixed angle */
- copy_v3_v3(area_co, ss->cache->location);
- if (flip) {
- angle = -angle;
- }
- }
-
- /* Set the angle for the cursor preview */
- ss->cache->multiplane_scrape_sampled_angle = angle;
+ /* Scale brush local space matrix. */
+ scale_m4_fl(scale, ss->cache->radius);
+ mul_m4_m4m4(tmat, mat, scale);
+ invert_m4_m4(mat, tmat);
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
+ .area_no_sp = area_no_sp,
+ .area_co = area_co,
.mat = mat,
- .multiplane_scrape_angle = angle,
};
- /* Calculate the final left and right scrape planes */
- float plane_no[3];
- float plane_no_rot[3];
- float y_axis[3] = {0.0f, 1.0f, 0.0f};
- float mat_inv[4][4];
- invert_m4_m4(mat_inv, mat);
-
- mul_v3_mat3_m4v3(plane_no, mat, area_no);
- rotate_v3_v3v3fl(plane_no_rot, plane_no, y_axis, DEG2RADF(-angle * 0.5f));
- mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot);
- normalize_v3(plane_no);
- plane_from_point_normal_v3(data.multiplane_scrape_planes[1], area_co, plane_no);
-
- mul_v3_mat3_m4v3(plane_no, mat, area_no);
- rotate_v3_v3v3fl(plane_no_rot, plane_no, y_axis, DEG2RADF(angle * 0.5f));
- mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot);
- normalize_v3(plane_no);
- plane_from_point_normal_v3(data.multiplane_scrape_planes[0], area_co, plane_no);
-
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_multiplane_scrape_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings);
}
-/** \} */
-
-static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict tls)
+static void do_fill_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
const Brush *brush = data->brush;
- float(*mat)[4] = data->mat;
- const float *area_no_sp = data->area_no_sp;
+ const float *area_no = data->area_no;
const float *area_co = data->area_co;
PBVHVertexIter vd;
- SculptBrushTest test;
float(*proxy)[3];
- const bool flip = (ss->cache->bstrength < 0);
- const float bstrength = flip ? -ss->cache->bstrength : ss->cache->bstrength;
+ const float bstrength = ss->cache->bstrength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
- plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_cube(&test, vd.co, mat)) {
- if (plane_point_side_flip(vd.co, test.plane_tool, flip)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ if (SCULPT_plane_point_side(vd.co, test.plane_tool)) {
float intr[3];
float val[3];
@@ -5478,18 +4724,16 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
sub_v3_v3v3(val, intr, vd.co);
- if (plane_trim(ss->cache, brush, val)) {
- /* note, the normal from the vertices is ignored,
- * causes glitch with planes, see: T44390 */
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- ss->cache->radius * test.dist,
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ if (SCULPT_plane_trim(ss->cache, brush, val)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5503,81 +4747,46 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- const bool flip = (ss->cache->bstrength < 0);
- const float radius = flip ? -ss->cache->radius : ss->cache->radius;
- const float offset = get_offset(sd, ss);
- const float displace = radius * (0.25f + offset);
+ const float radius = ss->cache->radius;
- float area_no_sp[3]; /* the sculpt-plane normal (whatever its set to) */
- float area_no[3]; /* geometry normal */
+ float area_no[3];
float area_co[3];
+ float offset = SCULPT_brush_plane_offset_get(sd, ss);
- float temp[3];
- float mat[4][4];
- float scale[4][4];
- float tmat[4][4];
-
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
+ float displace;
- if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
- calc_area_normal(sd, ob, nodes, totnode, area_no);
- }
- else {
- copy_v3_v3(area_no, area_no_sp);
- }
+ float temp[3];
- /* delay the first daub because grab delta is not setup */
- if (ss->cache->first_time) {
- return;
- }
+ SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
- if (is_zero_v3(ss->cache->grab_delta_symmetry)) {
- return;
- }
+ displace = radius * offset;
- mul_v3_v3v3(temp, area_no_sp, ss->cache->scale);
+ mul_v3_v3v3(temp, area_no, ss->cache->scale);
mul_v3_fl(temp, displace);
add_v3_v3(area_co, temp);
- /* init mat */
- cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
- mat[0][3] = 0;
- cross_v3_v3v3(mat[1], area_no, mat[0]);
- mat[1][3] = 0;
- copy_v3_v3(mat[2], area_no);
- mat[2][3] = 0;
- copy_v3_v3(mat[3], ss->cache->location);
- mat[3][3] = 1;
- normalize_m4(mat);
-
- /* scale mat */
- scale_m4_fl(scale, ss->cache->radius);
- mul_m4_m4m4(tmat, mat, scale);
- invert_m4_m4(mat, tmat);
-
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
- .area_no_sp = area_no_sp,
+ .area_no = area_no,
.area_co = area_co,
- .mat = mat,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings);
}
-static void do_fill_brush_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict tls)
+static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
@@ -5592,15 +4801,15 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
-
+ const int thread_id = BLI_task_parallel_thread_id(tls);
plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- if (plane_point_side(vd.co, test.plane_tool)) {
+ if (!SCULPT_plane_point_side(vd.co, test.plane_tool)) {
float intr[3];
float val[3];
@@ -5608,16 +4817,16 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
sub_v3_v3v3(val, intr, vd.co);
- if (plane_trim(ss->cache, brush, val)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ if (SCULPT_plane_trim(ss->cache, brush, val)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5631,7 +4840,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -5640,15 +4849,15 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
float area_no[3];
float area_co[3];
- float offset = get_offset(sd, ss);
+ float offset = SCULPT_brush_plane_offset_get(sd, ss);
float displace;
float temp[3];
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
+ SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
- displace = radius * offset;
+ displace = -radius * offset;
mul_v3_v3v3(temp, area_no, ss->cache->scale);
mul_v3_fl(temp, displace);
@@ -5663,103 +4872,186 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.area_co = area_co,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings);
}
-static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
- const int n,
- const TaskParallelTLS *__restrict tls)
+/* -------------------------------------------------------------------- */
+
+/** \name Sculpt Clay Thumb Brush
+ * \{ */
+
+static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
const Brush *brush = data->brush;
- const float *area_no = data->area_no;
+ float(*mat)[4] = data->mat;
+ const float *area_no_sp = data->area_no_sp;
const float *area_co = data->area_co;
PBVHVertexIter vd;
float(*proxy)[3];
- const float bstrength = ss->cache->bstrength;
+ const float bstrength = data->clay_strength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
- plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ float plane_tilt[4];
+ float normal_tilt[3];
+ float imat[4][4];
+
+ invert_m4_m4(imat, mat);
+ rotate_v3_v3v3fl(normal_tilt, area_no_sp, imat[0], DEG2RADF(-ss->cache->clay_thumb_front_angle));
+
+ /* Plane aligned to the geometry normal (back part of the brush). */
+ plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp);
+ /* Tilted plane (front part of the brush). */
+ plane_from_point_normal_v3(plane_tilt, area_co, normal_tilt);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- if (!plane_point_side(vd.co, test.plane_tool)) {
- float intr[3];
- float val[3];
-
- closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
-
- sub_v3_v3v3(val, intr, vd.co);
+ float local_co[3];
+ mul_v3_m4v3(local_co, mat, vd.co);
+ float intr[3], intr_tilt[3];
+ float val[3];
- if (plane_trim(ss->cache, brush, val)) {
- const float fade = bstrength * tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
+ closest_to_plane_normalized_v3(intr_tilt, plane_tilt, vd.co);
+
+ /* Mix the deformation of the aligned and the tilted plane based on the brush space vertex
+ * coordinates. */
+ /* We can also control the mix with a curve if it produces noticeable artifacts in the center
+ * of the brush. */
+ const float tilt_mix = local_co[1] > 0.0f ? 0.0f : 1.0f;
+ interp_v3_v3v3(intr, intr, intr_tilt, tilt_mix);
+ sub_v3_v3v3(val, intr_tilt, vd.co);
+
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
- mul_v3_v3fl(proxy[vd.i], val, fade);
+ mul_v3_v3fl(proxy[vd.i], val, fade);
- if (vd.mvert) {
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
}
BKE_pbvh_vertex_iter_end;
}
-static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+static float sculpt_clay_thumb_get_stabilized_pressure(StrokeCache *cache)
+{
+ float final_pressure = 0.0f;
+ for (int i = 0; i < SCULPT_CLAY_STABILIZER_LEN; i++) {
+ final_pressure += cache->clay_pressure_stabilizer[i];
+ }
+ return final_pressure / (float)SCULPT_CLAY_STABILIZER_LEN;
+}
+
+static void do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
const float radius = ss->cache->radius;
+ const float offset = SCULPT_brush_plane_offset_get(sd, ss);
+ const float displace = radius * (0.25f + offset);
+ /* Sampled geometry normal and area center. */
+ float area_no_sp[3];
float area_no[3];
float area_co[3];
- float offset = get_offset(sd, ss);
-
- float displace;
float temp[3];
+ float mat[4][4];
+ float scale[4][4];
+ float tmat[4][4];
- calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
+ SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
- displace = -radius * offset;
+ if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
+ SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no);
+ }
+ else {
+ copy_v3_v3(area_no, area_no_sp);
+ }
- mul_v3_v3v3(temp, area_no, ss->cache->scale);
+ /* Delay the first daub because grab delta is not setup. */
+ if (ss->cache->first_time) {
+ ss->cache->clay_thumb_front_angle = 0.0f;
+ return;
+ }
+
+ /* Simulate the clay accumulation by increasing the plane angle as more samples are added to the
+ * stroke. */
+ if (ss->cache->mirror_symmetry_pass == 0) {
+ ss->cache->clay_thumb_front_angle += 0.8f;
+ CLAMP(ss->cache->clay_thumb_front_angle, 0.0f, 60.0f);
+ }
+
+ if (is_zero_v3(ss->cache->grab_delta_symmetry)) {
+ return;
+ }
+
+ /* Displace the brush planes. */
+ copy_v3_v3(area_co, ss->cache->location);
+ mul_v3_v3v3(temp, area_no_sp, ss->cache->scale);
mul_v3_fl(temp, displace);
add_v3_v3(area_co, temp);
+ /* Init brush local space matrix. */
+ cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
+ mat[0][3] = 0.0f;
+ cross_v3_v3v3(mat[1], area_no, mat[0]);
+ mat[1][3] = 0.0f;
+ copy_v3_v3(mat[2], area_no);
+ mat[2][3] = 0.0f;
+ copy_v3_v3(mat[3], ss->cache->location);
+ mat[3][3] = 1.0f;
+ normalize_m4(mat);
+
+ /* Scale brush local space matrix. */
+ scale_m4_fl(scale, ss->cache->radius);
+ mul_m4_m4m4(tmat, mat, scale);
+ invert_m4_m4(mat, tmat);
+
+ float clay_strength = ss->cache->bstrength *
+ sculpt_clay_thumb_get_stabilized_pressure(ss->cache);
+
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
- .area_no = area_no,
- .area_co = area_co,
+ .area_no_sp = area_no_sp,
+ .area_co = ss->cache->location,
+ .mat = mat,
+ .clay_strength = clay_strength,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_clay_thumb_brush_task_cb_ex, &settings);
}
+/** \} */
+
static void do_gravity_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
@@ -5775,21 +5067,22 @@ static void do_gravity_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
SculptBrushTest test;
- SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- const float fade = tex_strength(ss,
- brush,
- vd.co,
- sqrtf(test.dist),
- vd.no,
- vd.fno,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- tls->thread_id);
+ const float fade = SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -5806,16 +5099,16 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- float offset[3] /*, area_no[3]*/;
+ float offset[3];
float gravity_vector[3];
mul_v3_v3fl(gravity_vector, ss->cache->gravity_direction, -ss->cache->radius_squared);
- /* offset with as much as possible factored in already */
+ /* Offset with as much as possible factored in already. */
mul_v3_v3v3(offset, gravity_vector, ss->cache->scale);
mul_v3_fl(offset, bstrength);
- /* threaded loop over nodes */
+ /* Threaded loop over nodes. */
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
@@ -5824,12 +5117,12 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
.offset = offset,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings);
}
-void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
+void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
{
Mesh *me = (Mesh *)ob->data;
float(*ofs)[3] = NULL;
@@ -5837,16 +5130,16 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
const int kb_act_idx = ob->shapenr - 1;
KeyBlock *currkey;
- /* for relative keys editing of base should update other keys */
+ /* For relative keys editing of base should update other keys. */
if (BKE_keyblock_is_basis(me->key, kb_act_idx)) {
ofs = BKE_keyblock_convert_to_vertcos(ob, kb);
- /* calculate key coord offsets (from previous location) */
+ /* Calculate key coord offsets (from previous location). */
for (a = 0; a < me->totvert; a++) {
sub_v3_v3v3(ofs[a], vertCos[a], ofs[a]);
}
- /* apply offsets on other keys */
+ /* Apply offsets on other keys. */
for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
if ((currkey != kb) && (currkey->relative == kb_act_idx)) {
BKE_keyblock_update_from_offset(ob, currkey, ofs);
@@ -5856,7 +5149,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
MEM_freeN(ofs);
}
- /* modifying of basis key should update mesh */
+ /* Modifying of basis key should update mesh. */
if (kb == me->key->refkey) {
MVert *mvert = me->mvert;
@@ -5867,7 +5160,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
BKE_mesh_calc_normals(me);
}
- /* apply new coords on active key block, no need to re-allocate kb->data here! */
+ /* Apply new coords on active key block, no need to re-allocate kb->data here! */
BKE_keyblock_update_from_vertcos(ob, kb, vertCos);
}
@@ -5882,14 +5175,14 @@ static void sculpt_topology_update(Sculpt *sd,
SculptSession *ss = ob->sculpt;
int n, totnode;
- /* Build a list of all nodes that are potentially within the brush's area of influence */
+ /* Build a list of all nodes that are potentially within the brush's area of influence. */
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
ss->cache->original;
const float radius_scale = 1.25f;
PBVHNode **nodes = sculpt_pbvh_gather_generic(
ob, sd, brush, use_original, radius_scale, &totnode);
- /* Only act if some verts are inside the brush area */
+ /* Only act if some verts are inside the brush area. */
if (totnode) {
PBVHTopologyUpdateMode mode = 0;
float location[3];
@@ -5905,7 +5198,7 @@ static void sculpt_topology_update(Sculpt *sd,
}
for (n = 0; n < totnode; n++) {
- sculpt_undo_push_node(ob,
+ SCULPT_undo_push_node(ob,
nodes[n],
brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK :
SCULPT_UNDO_COORDS);
@@ -5929,7 +5222,7 @@ static void sculpt_topology_update(Sculpt *sd,
MEM_SAFE_FREE(nodes);
- /* update average stroke position */
+ /* Update average stroke position. */
copy_v3_v3(location, ss->cache->true_location);
mul_m4_v3(ob->obmat, location);
}
@@ -5940,11 +5233,23 @@ static void do_brush_action_task_cb(void *__restrict userdata,
const TaskParallelTLS *__restrict UNUSED(tls))
{
SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+
+ /* Face Sets modifications do a single undo push */
+ if (data->brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) {
+ /* Draw face sets in smooth mode moves the vertices. */
+ if (ss->cache->alt_smooth) {
+ SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
+ BKE_pbvh_node_mark_update(data->nodes[n]);
+ }
+ }
+ else {
+ SCULPT_undo_push_node(data->ob,
+ data->nodes[n],
+ data->brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK :
+ SCULPT_UNDO_COORDS);
+ }
- sculpt_undo_push_node(data->ob,
- data->nodes[n],
- data->brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK :
- SCULPT_UNDO_COORDS);
if (data->brush->sculpt_tool == SCULPT_TOOL_MASK) {
BKE_pbvh_node_mark_update_mask(data->nodes[n]);
}
@@ -5959,30 +5264,58 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
int totnode;
PBVHNode **nodes;
- /* Build a list of all nodes that are potentially within the brush's area of influence */
+ /* Build a list of all nodes that are potentially within the brush's area of influence. */
/* These brushes need to update all nodes as they are not constrained by the brush radius */
/* Elastic deform needs all nodes to avoid artifacts as the effect of the brush is not
- * constrained by the radius */
+ * constrained by the radius. */
/* Pose needs all nodes because it applies all symmetry iterations at the same time and the IK
* chain can grow to any area of the model. */
/* This can be optimized by filtering the nodes after calculating the chain. */
if (ELEM(brush->sculpt_tool, SCULPT_TOOL_ELASTIC_DEFORM, SCULPT_TOOL_POSE)) {
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
}
+ else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
+ SculptSearchSphereData data = {
+ .ss = ss,
+ .sd = sd,
+ .radius_squared = square_f(ss->cache->radius * (1.0 + brush->cloth_sim_limit)),
+ .original = false,
+ .ignore_fully_masked = false,
+ .center = ss->cache->initial_location,
+ };
+ BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
+ }
else {
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
ss->cache->original;
float radius_scale = 1.0f;
/* With these options enabled not all required nodes are inside the original brush radius, so
- * the brush can produce artifacts in some situations */
+ * the brush can produce artifacts in some situations. */
if (brush->sculpt_tool == SCULPT_TOOL_DRAW && brush->flag & BRUSH_ORIGINAL_NORMAL) {
radius_scale = 2.0f;
}
nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
}
- /* Only act if some verts are inside the brush area */
+ /* Draw Face Sets in draw mode makes a single undo push, in alt-smooth mode deforms the
+ * vertices and uses regular coords undo. */
+ /* It also assigns the paint_face_set here as it needs to be done regardless of the stroke type
+ * and the number of nodes under the brush influence. */
+ if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS && ss->cache->first_time &&
+ ss->cache->mirror_symmetry_pass == 0 && !ss->cache->alt_smooth) {
+ SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_FACE_SETS);
+ if (ss->cache->invert) {
+ /* When inverting the brush, pick the paint face mask ID from the mesh. */
+ ss->cache->paint_face_set = SCULPT_active_face_set_get(ss);
+ }
+ else {
+ /* By default create a new Face Sets. */
+ ss->cache->paint_face_set = SCULPT_face_set_next_available_get(ss);
+ }
+ }
+
+ /* Only act if some verts are inside the brush area. */
if (totnode) {
float location[3];
@@ -5993,9 +5326,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
.nodes = nodes,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
if (sculpt_brush_needs_normal(ss, brush)) {
update_sculpt_normal(sd, ob, nodes, totnode);
@@ -6006,25 +5339,30 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
}
if (ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0) {
- if (sculpt_automasking_enabled(ss, brush)) {
- sculpt_automasking_init(sd, ob);
+ if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
+ SCULPT_automasking_init(sd, ob);
}
}
if (brush->sculpt_tool == SCULPT_TOOL_POSE && ss->cache->first_time &&
ss->cache->mirror_symmetry_pass == 0) {
- sculpt_pose_brush_init(sd, ob, ss, brush);
+ SCULPT_pose_brush_init(sd, ob, ss, brush);
}
bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN;
- /* Apply one type of brush action */
+ /* Apply one type of brush action. */
switch (brush->sculpt_tool) {
case SCULPT_TOOL_DRAW:
do_draw_brush(sd, ob, nodes, totnode);
break;
case SCULPT_TOOL_SMOOTH:
- do_smooth_brush(sd, ob, nodes, totnode);
+ if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) {
+ SCULPT_do_smooth_brush(sd, ob, nodes, totnode);
+ }
+ else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) {
+ SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode);
+ }
break;
case SCULPT_TOOL_CREASE:
do_crease_brush(sd, ob, nodes, totnode);
@@ -6066,7 +5404,10 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
do_clay_strips_brush(sd, ob, nodes, totnode);
break;
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
- do_multiplane_scrape_brush(sd, ob, nodes, totnode);
+ SCULPT_do_multiplane_scrape_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_CLAY_THUMB:
+ do_clay_thumb_brush(sd, ob, nodes, totnode);
break;
case SCULPT_TOOL_FILL:
if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
@@ -6088,7 +5429,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
do_mask_brush(sd, ob, nodes, totnode);
break;
case SCULPT_TOOL_POSE:
- do_pose_brush(sd, ob, nodes, totnode);
+ SCULPT_do_pose_brush(sd, ob, nodes, totnode);
break;
case SCULPT_TOOL_DRAW_SHARP:
do_draw_sharp_brush(sd, ob, nodes, totnode);
@@ -6099,16 +5440,26 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
case SCULPT_TOOL_SLIDE_RELAX:
do_slide_relax_brush(sd, ob, nodes, totnode);
break;
+ case SCULPT_TOOL_CLOTH:
+ SCULPT_do_cloth_brush(sd, ob, nodes, totnode);
+ break;
+ case SCULPT_TOOL_DRAW_FACE_SETS:
+ SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode);
+ break;
}
if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK) &&
brush->autosmooth_factor > 0) {
if (brush->flag & BRUSH_INVERSE_SMOOTH_PRESSURE) {
- smooth(
- sd, ob, nodes, totnode, brush->autosmooth_factor * (1 - ss->cache->pressure), false);
+ SCULPT_smooth(sd,
+ ob,
+ nodes,
+ totnode,
+ brush->autosmooth_factor * (1.0f - ss->cache->pressure),
+ false);
}
else {
- smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false);
+ SCULPT_smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false);
}
}
@@ -6116,24 +5467,25 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor);
}
- if (ss->cache->supports_gravity) {
+ /* The cloth brush adds the gravity as a regular force and it is processed in the solver. */
+ if (ss->cache->supports_gravity && brush->sculpt_tool != SCULPT_TOOL_CLOTH) {
do_gravity(sd, ob, nodes, totnode, sd->gravity_factor);
}
MEM_SAFE_FREE(nodes);
- /* update average stroke position */
+ /* Update average stroke position. */
copy_v3_v3(location, ss->cache->true_location);
mul_m4_v3(ob->obmat, location);
add_v3_v3(ups->average_stroke_accum, location);
ups->average_stroke_counter++;
- /* update last stroke position */
+ /* Update last stroke position. */
ups->last_stroke_valid = true;
}
}
-/* flush displacement from deformed PBVH vertex to original mesh */
+/* Flush displacement from deformed PBVH vertex to original mesh. */
static void sculpt_flush_pbvhvert_deform(Object *ob, PBVHVertexIter *vd)
{
SculptSession *ss = ob->sculpt;
@@ -6162,7 +5514,7 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
Sculpt *sd = data->sd;
Object *ob = data->ob;
- /* these brushes start from original coordinates */
+ /* These brushes start from original coordinates. */
const bool use_orco = ELEM(data->brush->sculpt_tool,
SCULPT_TOOL_GRAB,
SCULPT_TOOL_ROTATE,
@@ -6176,7 +5528,7 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
float(*orco)[3] = NULL;
if (use_orco && !ss->bm) {
- orco = sculpt_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS)->co;
+ orco = SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS)->co;
}
BKE_pbvh_node_get_proxies(data->nodes[n], &proxies, &proxy_count);
@@ -6184,7 +5536,6 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
float val[3];
- int p;
if (use_orco) {
if (ss->bm) {
@@ -6198,11 +5549,11 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
copy_v3_v3(val, vd.co);
}
- for (p = 0; p < proxy_count; p++) {
+ for (int p = 0; p < proxy_count; p++) {
add_v3_v3(val, proxies[p].co[vd.i]);
}
- sculpt_clip(sd, ss, vd.co, val);
+ SCULPT_clip(sd, ss, vd.co, val);
if (ss->deform_modifiers_active) {
sculpt_flush_pbvhvert_deform(ob, &vd);
@@ -6222,7 +5573,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
- /* first line is tools that don't support proxies */
+ /* First line is tools that don't support proxies. */
if (ss->cache->supports_gravity || (sculpt_tool_is_proxy_used(brush->sculpt_tool) == false)) {
SculptThreadedTaskData data = {
.sd = sd,
@@ -6231,22 +5582,22 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
.nodes = nodes,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings);
}
MEM_SAFE_FREE(nodes);
}
-/* copy the modified vertices from bvh to the active key */
+/*Copy the modified vertices from bvh to the active key. */
static void sculpt_update_keyblock(Object *ob)
{
SculptSession *ss = ob->sculpt;
float(*vertCos)[3];
/* Keyblock update happens after handling deformation caused by modifiers,
- * so ss->orig_cos would be updated with new stroke */
+ * so ss->orig_cos would be updated with new stroke. */
if (ss->orig_cos) {
vertCos = ss->orig_cos;
}
@@ -6255,7 +5606,7 @@ static void sculpt_update_keyblock(Object *ob)
}
if (vertCos) {
- sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos);
+ SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos);
if (vertCos != ss->orig_cos) {
MEM_freeN(vertCos);
@@ -6263,7 +5614,7 @@ static void sculpt_update_keyblock(Object *ob)
}
}
-static void sculpt_flush_stroke_deform_task_cb(void *__restrict userdata,
+static void SCULPT_flush_stroke_deform_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
{
@@ -6286,15 +5637,15 @@ static void sculpt_flush_stroke_deform_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-/* flush displacement from deformed PBVH to original layer */
-static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
+/* Flush displacement from deformed PBVH to original layer. */
+void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
if (is_proxy_used) {
- /* this brushes aren't using proxies, so sculpt_combine_proxies() wouldn't
- * propagate needed deformation to original base */
+ /* This brushes aren't using proxies, so sculpt_combine_proxies() wouldn't propagate needed
+ * deformation to original base. */
int totnode;
Mesh *me = (Mesh *)ob->data;
@@ -6304,10 +5655,8 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_use
if (ss->shapekey_active) {
vertCos = MEM_mallocN(sizeof(*vertCos) * me->totvert, "flushStrokeDeofrm keyVerts");
- /* mesh could have isolated verts which wouldn't be in BVH,
- * to deal with this we copy old coordinates over new ones
- * and then update coordinates for all vertices from BVH
- */
+ /* Mesh could have isolated verts which wouldn't be in BVH, to deal with this we copy old
+ * coordinates over new ones and then update coordinates for all vertices from BVH. */
memcpy(vertCos, ss->orig_cos, sizeof(*vertCos) * me->totvert);
}
@@ -6321,20 +5670,20 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_use
.vertCos = vertCos,
};
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, sculpt_flush_stroke_deform_task_cb, &settings);
+ BLI_task_parallel_range(0, totnode, &data, SCULPT_flush_stroke_deform_task_cb, &settings);
if (vertCos) {
- sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos);
+ SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos);
MEM_freeN(vertCos);
}
MEM_SAFE_FREE(nodes);
- /* Modifiers could depend on mesh normals, so we should update them/
- * Note, then if sculpting happens on locked key, normals should be re-calculated
- * after applying coords from keyblock on base mesh */
+ /* Modifiers could depend on mesh normals, so we should update them.
+ * Note, then if sculpting happens on locked key, normals should be re-calculate after applying
+ * coords from keyblock on base mesh. */
BKE_mesh_calc_normals(me);
}
else if (ss->shapekey_active) {
@@ -6344,7 +5693,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_use
/* Flip all the editdata across the axis/axes specified by symm. Used to
* calculate multiple modifications to the mesh when symmetry is enabled. */
-void sculpt_cache_calc_brushdata_symm(StrokeCache *cache,
+void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
const char symm,
const char axis,
const float angle)
@@ -6354,16 +5703,19 @@ void sculpt_cache_calc_brushdata_symm(StrokeCache *cache,
flip_v3_v3(cache->grab_delta_symmetry, cache->grab_delta, symm);
flip_v3_v3(cache->view_normal, cache->true_view_normal, symm);
+ flip_v3_v3(cache->initial_location, cache->true_initial_location, symm);
+ flip_v3_v3(cache->initial_normal, cache->true_initial_normal, symm);
+
/* XXX This reduces the length of the grab delta if it approaches the line of symmetry
- * XXX However, a different approach appears to be needed */
+ * XXX However, a different approach appears to be needed. */
#if 0
if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) {
float frac = 1.0f / max_overlap_count(sd);
- float reduce = (feather - frac) / (1 - frac);
+ float reduce = (feather - frac) / (1.0f - frac);
printf("feather: %f frac: %f reduce: %f\n", feather, frac, reduce);
- if (frac < 1) {
+ if (frac < 1.0f) {
mul_v3_fl(cache->grab_delta_symmetry, reduce);
}
}
@@ -6373,7 +5725,8 @@ void sculpt_cache_calc_brushdata_symm(StrokeCache *cache,
unit_m4(cache->symm_rot_mat_inv);
zero_v3(cache->plane_offset);
- if (axis) { /* expects XYZ */
+ /* Expects XYZ. */
+ if (axis) {
rotate_m4(cache->symm_rot_mat, axis, angle);
rotate_m4(cache->symm_rot_mat_inv, axis, -angle);
}
@@ -6403,7 +5756,6 @@ static void do_tiled(
const float *bbMin = bb->vec[0];
const float *bbMax = bb->vec[6];
const float *step = sd->paint.tile_offset;
- int dim;
/* These are integer locations, for real location: multiply with step and add orgLoc.
* So 0,0,0 is at orgLoc. */
@@ -6411,10 +5763,11 @@ static void do_tiled(
int end[3];
int cur[3];
- float orgLoc[3]; /* position of the "prototype" stroke for tiling */
+ /* Position of the "prototype" stroke for tiling. */
+ float orgLoc[3];
copy_v3_v3(orgLoc, cache->location);
- for (dim = 0; dim < 3; dim++) {
+ for (int dim = 0; dim < 3; dim++) {
if ((sd->paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) {
start[dim] = (bbMin[dim] - orgLoc[dim] - radius) / step[dim];
end[dim] = (bbMax[dim] - orgLoc[dim] + radius) / step[dim];
@@ -6424,22 +5777,23 @@ static void do_tiled(
}
}
- /* first do the "untiled" position to initialize the stroke for this location */
+ /* First do the "untiled" position to initialize the stroke for this location. */
cache->tile_pass = 0;
action(sd, ob, brush, ups);
- /* now do it for all the tiles */
+ /* Now do it for all the tiles. */
copy_v3_v3_int(cur, start);
for (cur[0] = start[0]; cur[0] <= end[0]; cur[0]++) {
for (cur[1] = start[1]; cur[1] <= end[1]; cur[1]++) {
for (cur[2] = start[2]; cur[2] <= end[2]; cur[2]++) {
if (!cur[0] && !cur[1] && !cur[2]) {
- continue; /* skip tile at orgLoc, this was already handled before all others */
+ /* Skip tile at orgLoc, this was already handled before all others. */
+ continue;
}
++cache->tile_pass;
- for (dim = 0; dim < 3; dim++) {
+ for (int dim = 0; dim < 3; dim++) {
cache->location[dim] = cur[dim] * step[dim] + orgLoc[dim];
cache->plane_offset[dim] = cur[dim] * step[dim];
}
@@ -6459,26 +5813,25 @@ static void do_radial_symmetry(Sculpt *sd,
const float UNUSED(feather))
{
SculptSession *ss = ob->sculpt;
- int i;
- for (i = 1; i < sd->radial_symm[axis - 'X']; i++) {
- const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X'];
+ for (int i = 1; i < sd->radial_symm[axis - 'X']; i++) {
+ const float angle = 2.0f * M_PI * i / sd->radial_symm[axis - 'X'];
ss->cache->radial_symmetry_pass = i;
- sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
+ SCULPT_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
do_tiled(sd, ob, brush, ups, action);
}
}
-/* noise texture gives different values for the same input coord; this
+/* Noise texture gives different values for the same input coord; this
* can tear a multires mesh during sculpting so do a stitch in this
- * case */
+ * case. */
static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
MTex *mtex = &brush->mtex;
- if (ss->multires && mtex->tex && mtex->tex->type == TEX_NOISE) {
+ if (ss->multires.active && mtex->tex && mtex->tex->type == TEX_NOISE) {
multires_stitch_grids(ob);
}
}
@@ -6492,7 +5845,6 @@ static void do_symmetrical_brush_actions(Sculpt *sd,
SculptSession *ss = ob->sculpt;
StrokeCache *cache = ss->cache;
const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- int i;
float feather = calc_symmetry_feather(sd, ss->cache);
@@ -6501,12 +5853,12 @@ static void do_symmetrical_brush_actions(Sculpt *sd,
/* symm is a bit combination of XYZ -
* 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
- for (i = 0; i <= symm; i++) {
+ for (int i = 0; i <= symm; i++) {
if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) {
cache->mirror_symmetry_pass = i;
cache->radial_symmetry_pass = 0;
- sculpt_cache_calc_brushdata_symm(cache, i, 0, 0);
+ SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
do_tiled(sd, ob, brush, ups, action);
do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather);
@@ -6531,7 +5883,7 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
ss->tex_pool = NULL;
}
- /* Need to allocate a bigger buffer for bigger brush size */
+ /* Need to allocate a bigger buffer for bigger brush size. */
ss->texcache_side = 2 * radius;
if (!ss->texcache || ss->texcache_side > ss->texcache_actual) {
ss->texcache = BKE_brush_gen_texture_cache(brush, radius, false);
@@ -6540,25 +5892,25 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
}
}
-bool sculpt_mode_poll(bContext *C)
+bool SCULPT_mode_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
return ob && ob->mode & OB_MODE_SCULPT;
}
-bool sculpt_mode_poll_view3d(bContext *C)
+bool SCULPT_mode_poll_view3d(bContext *C)
{
- return (sculpt_mode_poll(C) && CTX_wm_region_view3d(C));
+ return (SCULPT_mode_poll(C) && CTX_wm_region_view3d(C));
}
-bool sculpt_poll_view3d(bContext *C)
+bool SCULPT_poll_view3d(bContext *C)
{
- return (sculpt_poll(C) && CTX_wm_region_view3d(C));
+ return (SCULPT_poll(C) && CTX_wm_region_view3d(C));
}
-bool sculpt_poll(bContext *C)
+bool SCULPT_poll(bContext *C)
{
- return sculpt_mode_poll(C) && paint_poll(C);
+ return SCULPT_mode_poll(C) && paint_poll(C);
}
static const char *sculpt_tool_name(Sculpt *sd)
@@ -6592,6 +5944,8 @@ static const char *sculpt_tool_name(Sculpt *sd)
return "Clay Brush";
case SCULPT_TOOL_CLAY_STRIPS:
return "Clay Strips Brush";
+ case SCULPT_TOOL_CLAY_THUMB:
+ return "Clay Thumb Brush";
case SCULPT_TOOL_FILL:
return "Fill Brush";
case SCULPT_TOOL_SCRAPE:
@@ -6611,9 +5965,13 @@ static const char *sculpt_tool_name(Sculpt *sd)
case SCULPT_TOOL_POSE:
return "Pose Brush";
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
- return "Multiplane Scrape Brush";
+ return "Multi-plane Scrape Brush";
case SCULPT_TOOL_SLIDE_RELAX:
return "Slide/Relax Brush";
+ case SCULPT_TOOL_CLOTH:
+ return "Cloth Brush";
+ case SCULPT_TOOL_DRAW_FACE_SETS:
+ return "Draw Face Sets";
}
return "Sculpting";
@@ -6623,35 +5981,40 @@ static const char *sculpt_tool_name(Sculpt *sd)
* Operator for applying a stroke (various attributes including mouse path)
* using the current brush. */
-void sculpt_cache_free(StrokeCache *cache)
+void SCULPT_cache_free(StrokeCache *cache)
{
- if (cache->dial) {
- MEM_freeN(cache->dial);
- }
+ MEM_SAFE_FREE(cache->dial);
+ MEM_SAFE_FREE(cache->surface_smooth_laplacian_disp);
+ MEM_SAFE_FREE(cache->layer_displacement_factor);
+
if (cache->pose_ik_chain) {
- sculpt_pose_ik_chain_free(cache->pose_ik_chain);
+ SCULPT_pose_ik_chain_free(cache->pose_ik_chain);
+ }
+
+ if (cache->cloth_sim) {
+ SCULPT_cloth_simulation_free(cache->cloth_sim);
}
+
MEM_freeN(cache);
}
-/* Initialize mirror modifier clipping */
+/* Initialize mirror modifier clipping. */
static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss)
{
ModifierData *md;
- int i;
for (md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
MirrorModifierData *mmd = (MirrorModifierData *)md;
if (mmd->flag & MOD_MIR_CLIPPING) {
- /* check each axis for mirroring */
- for (i = 0; i < 3; i++) {
+ /* Check each axis for mirroring. */
+ for (int i = 0; i < 3; i++) {
if (mmd->flag & (MOD_MIR_AXIS_X << i)) {
- /* enable sculpt clipping */
+ /* Enable sculpt clipping. */
ss->cache->flag |= CLIP_X << i;
- /* update the clip tolerance */
+ /* Update the clip tolerance. */
if (mmd->tolerance > ss->cache->clip_tolerance[i]) {
ss->cache->clip_tolerance[i] = mmd->tolerance;
}
@@ -6662,7 +6025,7 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss)
}
}
-/* Initialize the stroke cache invariants from operator properties */
+/* Initialize the stroke cache invariants from operator properties. */
static void sculpt_update_cache_invariants(
bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2])
{
@@ -6676,20 +6039,14 @@ static void sculpt_update_cache_invariants(
float mat[3][3];
float viewDir[3] = {0.0f, 0.0f, 1.0f};
float max_scale;
- int i;
int mode;
ss->cache = cache;
- /* Set scaling adjustment */
- if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
- max_scale = 1.0f;
- }
- else {
- max_scale = 0.0f;
- for (i = 0; i < 3; i++) {
- max_scale = max_ff(max_scale, fabsf(ob->scale[i]));
- }
+ /* Set scaling adjustment. */
+ max_scale = 0.0f;
+ for (int i = 0; i < 3; i++) {
+ max_scale = max_ff(max_scale, fabsf(ob->scale[i]));
}
cache->scale[0] = max_scale / ob->scale[0];
cache->scale[1] = max_scale / ob->scale[1];
@@ -6701,7 +6058,7 @@ static void sculpt_update_cache_invariants(
sculpt_init_mirror_clipping(ob, ss);
- /* Initial mouse location */
+ /* Initial mouse location. */
if (mouse) {
copy_v2_v2(cache->initial_mouse, mouse);
}
@@ -6709,12 +6066,18 @@ static void sculpt_update_cache_invariants(
zero_v2(cache->initial_mouse);
}
+ copy_v3_v3(cache->initial_location, ss->cursor_location);
+ copy_v3_v3(cache->true_initial_location, ss->cursor_location);
+
+ copy_v3_v3(cache->initial_normal, ss->cursor_normal);
+ copy_v3_v3(cache->true_initial_normal, ss->cursor_normal);
+
mode = RNA_enum_get(op->ptr, "mode");
cache->invert = mode == BRUSH_STROKE_INVERT;
cache->alt_smooth = mode == BRUSH_STROKE_SMOOTH;
cache->normal_weight = brush->normal_weight;
- /* interpret invert as following normal, for grab brushes */
+ /* Interpret invert as following normal, for grab brushes. */
if (SCULPT_TOOL_HAS_NORMAL_WEIGHT(brush->sculpt_tool)) {
if (cache->invert) {
cache->invert = false;
@@ -6722,8 +6085,8 @@ static void sculpt_update_cache_invariants(
}
}
- /* not very nice, but with current events system implementation
- * we can't handle brush appearance inversion hotkey separately (sergey) */
+ /* Not very nice, but with current events system implementation
+ * we can't handle brush appearance inversion hotkey separately (sergey). */
if (cache->invert) {
ups->draw_inverted = true;
}
@@ -6731,14 +6094,14 @@ static void sculpt_update_cache_invariants(
ups->draw_inverted = false;
}
- /* Alt-Smooth */
+ /* Alt-Smooth. */
if (cache->alt_smooth) {
if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
cache->saved_mask_brush_tool = brush->mask_tool;
brush->mask_tool = BRUSH_MASK_SMOOTH;
}
- else if (brush->sculpt_tool == SCULPT_TOOL_SLIDE_RELAX) {
- /* Do nothing, this tool has its own smooth mode */
+ else if (ELEM(brush->sculpt_tool, SCULPT_TOOL_SLIDE_RELAX, SCULPT_TOOL_DRAW_FACE_SETS)) {
+ /* Do nothing, this tool has its own smooth mode. */
}
else {
Paint *p = &sd->paint;
@@ -6763,13 +6126,13 @@ static void sculpt_update_cache_invariants(
copy_v2_v2(cache->mouse, cache->initial_mouse);
copy_v2_v2(ups->tex_mouse, cache->initial_mouse);
- /* Truly temporary data that isn't stored in properties */
+ /* Truly temporary data that isn't stored in properties. */
cache->vc = vc;
cache->brush = brush;
- /* cache projection matrix */
+ /* Cache projection matrix. */
ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
invert_m4_m4(ob->imat, ob->obmat);
@@ -6782,7 +6145,7 @@ static void sculpt_update_cache_invariants(
cache->supports_gravity =
(!ELEM(brush->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SIMPLIFY) &&
(sd->gravity_factor > 0.0f));
- /* get gravity vector in world space */
+ /* Get gravity vector in world space. */
if (cache->supports_gravity) {
if (sd->gravity_object) {
Object *gravity_object = sd->gravity_object;
@@ -6790,42 +6153,16 @@ static void sculpt_update_cache_invariants(
copy_v3_v3(cache->true_gravity_direction, gravity_object->obmat[2]);
}
else {
- cache->true_gravity_direction[0] = cache->true_gravity_direction[1] = 0.0;
- cache->true_gravity_direction[2] = 1.0;
+ cache->true_gravity_direction[0] = cache->true_gravity_direction[1] = 0.0f;
+ cache->true_gravity_direction[2] = 1.0f;
}
- /* transform to sculpted object space */
+ /* Transform to sculpted object space. */
mul_m3_v3(mat, cache->true_gravity_direction);
normalize_v3(cache->true_gravity_direction);
}
- /* Initialize layer brush displacements and persistent coords */
- if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
- /* not supported yet for multires or dynamic topology */
- if (!ss->multires && !ss->bm && !ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) {
- if (!ss->layer_co) {
- ss->layer_co = MEM_mallocN(sizeof(float) * 3 * ss->totvert, "sculpt mesh vertices copy");
- }
-
- if (ss->deform_cos) {
- memcpy(ss->layer_co, ss->deform_cos, ss->totvert);
- }
- else {
- for (i = 0; i < ss->totvert; i++) {
- copy_v3_v3(ss->layer_co[i], ss->mvert[i].co);
- }
- }
- }
-
- if (ss->bm) {
- /* Free any remaining layer displacements from nodes. If not and topology changes
- * from using another tool, then next layer toolstroke
- * can access past disp array bounds */
- BKE_pbvh_free_layer_disp(ss->pbvh);
- }
- }
-
- /* Make copies of the mesh vertex locations and normals for some tools */
+ /* Make copies of the mesh vertex locations and normals for some tools. */
if (brush->flag & BRUSH_ANCHORED) {
cache->original = true;
}
@@ -6845,7 +6182,7 @@ static void sculpt_update_cache_invariants(
}
}
- cache->first_time = 1;
+ cache->first_time = true;
#define PIXEL_INPUT_THRESHHOLD 5
if (brush->sculpt_tool == SCULPT_TOOL_ROTATE) {
@@ -6861,7 +6198,11 @@ static float sculpt_brush_dynamic_size_get(Brush *brush, StrokeCache *cache, flo
case SCULPT_TOOL_CLAY:
return max_ff(initial_size * 0.20f, initial_size * pow3f(cache->pressure));
case SCULPT_TOOL_CLAY_STRIPS:
- return max_ff(initial_size * 0.35f, initial_size * pow2f(cache->pressure));
+ return max_ff(initial_size * 0.30f, initial_size * powf(cache->pressure, 1.5f));
+ case SCULPT_TOOL_CLAY_THUMB: {
+ float clay_stabilized_pressure = sculpt_clay_thumb_get_stabilized_pressure(cache);
+ return initial_size * clay_stabilized_pressure;
+ }
default:
return initial_size * cache->pressure;
}
@@ -6880,9 +6221,12 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
if (ELEM(tool,
SCULPT_TOOL_GRAB,
SCULPT_TOOL_ELASTIC_DEFORM,
+ SCULPT_TOOL_CLOTH,
SCULPT_TOOL_NUDGE,
SCULPT_TOOL_CLAY_STRIPS,
+ SCULPT_TOOL_PINCH,
SCULPT_TOOL_MULTIPLANE_SCRAPE,
+ SCULPT_TOOL_CLAY_THUMB,
SCULPT_TOOL_SNAKE_HOOK,
SCULPT_TOOL_POSE,
SCULPT_TOOL_THUMB) ||
@@ -6891,7 +6235,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
if (cache->first_time) {
if (tool == SCULPT_TOOL_GRAB && brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) {
- copy_v3_v3(cache->orig_grab_location, sculpt_active_vertex_co_get(ss));
+ copy_v3_v3(cache->orig_grab_location, SCULPT_active_vertex_co_get(ss));
}
else {
copy_v3_v3(cache->orig_grab_location, cache->true_location);
@@ -6901,11 +6245,11 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
add_v3_v3(cache->true_location, cache->grab_delta);
}
- /* compute 3d coordinate at same z from original location + mouse */
+ /* Compute 3d coordinate at same z from original location + mouse. */
mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location);
- ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->ar, loc, mouse, grab_location);
+ ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mouse, grab_location);
- /* compute delta to move verts by */
+ /* Compute delta to move verts by. */
if (!cache->first_time) {
switch (tool) {
case SCULPT_TOOL_GRAB:
@@ -6918,7 +6262,10 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
add_v3_v3(cache->grab_delta, delta);
break;
case SCULPT_TOOL_CLAY_STRIPS:
+ case SCULPT_TOOL_PINCH:
+ case SCULPT_TOOL_CLOTH:
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
+ case SCULPT_TOOL_CLAY_THUMB:
case SCULPT_TOOL_NUDGE:
case SCULPT_TOOL_SNAKE_HOOK:
if (brush->flag & BRUSH_ANCHORED) {
@@ -6968,7 +6315,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
SCULPT_TOOL_THUMB,
SCULPT_TOOL_ELASTIC_DEFORM,
SCULPT_TOOL_POSE)) {
- /* location stays the same for finding vertices in brush radius */
+ /* Location stays the same for finding vertices in brush radius. */
copy_v3_v3(cache->true_location, cache->orig_grab_location);
ups->draw_anchored = true;
@@ -6976,9 +6323,12 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
ups->anchored_size = ups->pixel_radius;
}
- /* handle 'rake' */
+ /* Handle 'rake' */
cache->is_rake_rotation_valid = false;
+ invert_m4_m4(imat, ob->obmat);
+ mul_mat3_m4_v3(imat, grab_location);
+
if (cache->first_time) {
copy_v3_v3(cache->rake_data.follow_co, grab_location);
}
@@ -7001,7 +6351,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
if ((normalize_v3(v2) > eps) && (normalize_v3(v1) > eps) &&
(len_squared_v3v3(v1, v2) > eps)) {
const float rake_dist_sq = len_squared_v3v3(cache->rake_data.follow_co, grab_location);
- const float rake_fade = (rake_dist_sq > SQUARE(cache->rake_data.follow_dist)) ?
+ const float rake_fade = (rake_dist_sq > square_f(cache->rake_data.follow_dist)) ?
1.0f :
sqrtf(rake_dist_sq) / cache->rake_data.follow_dist;
@@ -7010,7 +6360,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
rotation_between_vecs_to_quat(tquat, v1, v2);
- /* use axis-angle to scale rotation since the factor may be above 1 */
+ /* Use axis-angle to scale rotation since the factor may be above 1. */
quat_to_axis_angle(axis, &angle, tquat);
normalize_v3(axis);
@@ -7024,7 +6374,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
}
}
-/* Initialize the stroke cache variants from operator properties */
+/* Initialize the stroke cache variants from operator properties. */
static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
@@ -7033,27 +6383,26 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
StrokeCache *cache = ss->cache;
Brush *brush = BKE_paint_brush(&sd->paint);
- /* RNA_float_get_array(ptr, "location", cache->traced_location); */
-
if (cache->first_time ||
!((brush->flag & BRUSH_ANCHORED) || (brush->sculpt_tool == SCULPT_TOOL_SNAKE_HOOK) ||
- (brush->sculpt_tool == SCULPT_TOOL_ROTATE))) {
+ (brush->sculpt_tool == SCULPT_TOOL_ROTATE) ||
+ (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
+ brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB))) {
RNA_float_get_array(ptr, "location", cache->true_location);
}
cache->pen_flip = RNA_boolean_get(ptr, "pen_flip");
RNA_float_get_array(ptr, "mouse", cache->mouse);
- /* XXX: Use pressure value from first brush step for brushes which don't
- * support strokes (grab, thumb). They depends on initial state and
- * brush coord/pressure/etc.
- * It's more an events design issue, which doesn't split coordinate/pressure/angle
- * changing events. We should avoid this after events system re-design */
+ /* XXX: Use pressure value from first brush step for brushes which don't support strokes (grab,
+ * thumb). They depends on initial state and brush coord/pressure/etc.
+ * It's more an events design issue, which doesn't split coordinate/pressure/angle changing
+ * events. We should avoid this after events system re-design. */
if (paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT) || cache->first_time) {
cache->pressure = RNA_float_get(ptr, "pressure");
}
- /* Truly temporary data that isn't stored in properties */
+ /* Truly temporary data that isn't stored in properties. */
if (cache->first_time) {
if (!BKE_brush_use_locked_size(scene, brush)) {
cache->initial_radius = paint_calc_object_space_radius(
@@ -7065,6 +6414,23 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
}
}
+ /* Clay stabilized pressure. */
+ if (brush->sculpt_tool == SCULPT_TOOL_CLAY_THUMB) {
+ if (ss->cache->first_time) {
+ for (int i = 0; i < SCULPT_CLAY_STABILIZER_LEN; i++) {
+ ss->cache->clay_pressure_stabilizer[i] = 0.0f;
+ }
+ ss->cache->clay_pressure_stabilizer_index = 0;
+ }
+ else {
+ cache->clay_pressure_stabilizer[cache->clay_pressure_stabilizer_index] = cache->pressure;
+ cache->clay_pressure_stabilizer_index += 1;
+ if (cache->clay_pressure_stabilizer_index >= SCULPT_CLAY_STABILIZER_LEN) {
+ cache->clay_pressure_stabilizer_index = 0;
+ }
+ }
+ }
+
if (BKE_brush_use_size_pressure(brush) &&
paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) {
cache->radius = sculpt_brush_dynamic_size_get(brush, cache, cache->initial_radius);
@@ -7079,7 +6445,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
cache->radius_squared = cache->radius * cache->radius;
if (brush->flag & BRUSH_ANCHORED) {
- /* true location has been calculated as part of the stroke system already here */
+ /* True location has been calculated as part of the stroke system already here. */
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
RNA_float_get_array(ptr, "location", cache->true_location);
}
@@ -7103,29 +6469,37 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
}
cache->special_rotation = ups->brush_rotation;
+
+ cache->iteration_count++;
}
/* Returns true if any of the smoothing modes are active (currently
* one of smooth brush, autosmooth, mask smooth, or shift-key
- * smooth) */
-static bool sculpt_needs_connectivity_info(const Brush *brush, SculptSession *ss, int stroke_mode)
+ * smooth). */
+static bool sculpt_needs_connectivity_info(const Sculpt *sd,
+ const Brush *brush,
+ SculptSession *ss,
+ int stroke_mode)
{
- if (ss && ss->pbvh && sculpt_automasking_enabled(ss, brush)) {
+ if (ss && ss->pbvh && SCULPT_is_automasking_enabled(sd, ss, brush)) {
return true;
}
return ((stroke_mode == BRUSH_STROKE_SMOOTH) || (ss && ss->cache && ss->cache->alt_smooth) ||
(brush->sculpt_tool == SCULPT_TOOL_SMOOTH) || (brush->autosmooth_factor > 0) ||
((brush->sculpt_tool == SCULPT_TOOL_MASK) && (brush->mask_tool == BRUSH_MASK_SMOOTH)) ||
(brush->sculpt_tool == SCULPT_TOOL_POSE) ||
- (brush->sculpt_tool == SCULPT_TOOL_SLIDE_RELAX));
+ (brush->sculpt_tool == SCULPT_TOOL_SLIDE_RELAX) ||
+ (brush->sculpt_tool == SCULPT_TOOL_CLOTH) ||
+ (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS));
}
-static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush)
+void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush)
{
SculptSession *ss = ob->sculpt;
View3D *v3d = CTX_wm_view3d(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- bool need_pmap = sculpt_needs_connectivity_info(brush, ss, 0);
+ bool need_pmap = sculpt_needs_connectivity_info(sd, brush, ss, 0);
if (ss->shapekey_active || ss->deform_modifiers_active ||
(!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) {
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
@@ -7145,8 +6519,8 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
use_origco = true;
}
else {
- /* intersect with coordinates from before we started stroke */
- SculptUndoNode *unode = sculpt_undo_get_node(node);
+ /* Intersect with coordinates from before we started stroke. */
+ SculptUndoNode *unode = SCULPT_undo_get_node(node);
origco = (unode) ? unode->co : NULL;
use_origco = origco ? true : false;
}
@@ -7161,8 +6535,9 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
&srd->isect_precalc,
&srd->depth,
&srd->active_vertex_index,
+ &srd->active_face_grid_index,
srd->face_normal)) {
- srd->hit = 1;
+ srd->hit = true;
*tmin = srd->depth;
}
}
@@ -7180,8 +6555,8 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *t
use_origco = true;
}
else {
- /* intersect with coordinates from before we started stroke */
- SculptUndoNode *unode = sculpt_undo_get_node(node);
+ /* Intersect with coordinates from before we started stroke. */
+ SculptUndoNode *unode = SCULPT_undo_get_node(node);
origco = (unode) ? unode->co : NULL;
use_origco = origco ? true : false;
}
@@ -7195,40 +6570,28 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *t
srd->ray_normal,
&srd->depth,
&srd->dist_sq_to_ray)) {
- srd->hit = 1;
+ srd->hit = true;
*tmin = srd->dist_sq_to_ray;
}
}
}
-static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
-{
- if (BKE_pbvh_node_get_tmin(node) < *tmin) {
- SculptDetailRaycastData *srd = data_v;
- if (BKE_pbvh_bmesh_node_raycast_detail(
- node, srd->ray_start, &srd->isect_precalc, &srd->depth, &srd->edge_length)) {
- srd->hit = 1;
- *tmin = srd->depth;
- }
- }
-}
-
-static float sculpt_raycast_init(ViewContext *vc,
- const float mouse[2],
- float ray_start[3],
- float ray_end[3],
- float ray_normal[3],
- bool original)
+float SCULPT_raycast_init(ViewContext *vc,
+ const float mouse[2],
+ float ray_start[3],
+ float ray_end[3],
+ float ray_normal[3],
+ bool original)
{
float obimat[4][4];
float dist;
Object *ob = vc->obact;
- RegionView3D *rv3d = vc->ar->regiondata;
+ RegionView3D *rv3d = vc->region->regiondata;
View3D *v3d = vc->v3d;
- /* TODO: what if the segment is totally clipped? (return == 0) */
+ /* TODO: what if the segment is totally clipped? (return == 0). */
ED_view3d_win_to_segment_clipped(
- vc->depsgraph, vc->ar, vc->v3d, mouse, ray_start, ray_end, true);
+ vc->depsgraph, vc->region, vc->v3d, mouse, ray_start, ray_end, true);
invert_m4_m4(obimat, ob->obmat);
mul_m4_v3(obimat, ray_start);
@@ -7238,11 +6601,11 @@ static float sculpt_raycast_init(ViewContext *vc,
dist = normalize_v3(ray_normal);
if ((rv3d->is_persp == false) &&
- /* if the ray is clipped, don't adjust its start/end */
+ /* If the ray is clipped, don't adjust its start/end. */
RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
BKE_pbvh_raycast_project_ray_root(ob->sculpt->pbvh, original, ray_start, ray_end, ray_normal);
- /* recalculate the normal */
+ /* rRecalculate the normal. */
sub_v3_v3v3(ray_normal, ray_end, ray_start);
dist = normalize_v3(ray_normal);
}
@@ -7251,9 +6614,9 @@ static float sculpt_raycast_init(ViewContext *vc,
}
/* Gets the normal, location and active vertex location of the geometry under the cursor. This also
- * updates
- * the active vertex and cursor related data of the SculptSession using the mouse position */
-bool sculpt_cursor_geometry_info_update(bContext *C,
+ * updates the active vertex and cursor related data of the SculptSession using the mouse position
+ */
+bool SCULPT_cursor_geometry_info_update(bContext *C,
SculptCursorGeometryInfo *out,
const float mouse[2],
bool use_sampled_normal)
@@ -7283,14 +6646,14 @@ bool sculpt_cursor_geometry_info_update(bContext *C,
return false;
}
- /* PBVH raycast to get active vertex and face normal */
- depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
- sculpt_stroke_modifiers_check(C, ob, brush);
+ /* PBVH raycast to get active vertex and face normal. */
+ depth = SCULPT_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
+ SCULPT_stroke_modifiers_check(C, ob, brush);
SculptRaycastData srd = {
.original = original,
.ss = ob->sculpt,
- .hit = 0,
+ .hit = false,
.ray_start = ray_start,
.ray_normal = ray_normal,
.depth = depth,
@@ -7299,7 +6662,7 @@ bool sculpt_cursor_geometry_info_update(bContext *C,
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
- /* Cursor is not over the mesh, return default values */
+ /* Cursor is not over the mesh, return default values. */
if (!srd.hit) {
zero_v3(out->location);
zero_v3(out->normal);
@@ -7307,24 +6670,39 @@ bool sculpt_cursor_geometry_info_update(bContext *C,
return false;
}
- /* Update the active vertex of the SculptSession */
+ /* Update the active vertex of the SculptSession. */
ss->active_vertex_index = srd.active_vertex_index;
- copy_v3_v3(out->active_vertex_co, sculpt_active_vertex_co_get(ss));
+ copy_v3_v3(out->active_vertex_co, SCULPT_active_vertex_co_get(ss));
+
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ ss->active_face_index = srd.active_face_grid_index;
+ ss->active_grid_index = 0;
+ break;
+ case PBVH_GRIDS:
+ ss->active_face_index = 0;
+ ss->active_grid_index = srd.active_face_grid_index;
+ break;
+ case PBVH_BMESH:
+ ss->active_face_index = 0;
+ ss->active_grid_index = 0;
+ break;
+ }
copy_v3_v3(out->location, ray_normal);
mul_v3_fl(out->location, srd.depth);
add_v3_v3(out->location, ray_start);
- /* Option to return the face normal directly for performance o accuracy reasons */
+ /* Option to return the face normal directly for performance o accuracy reasons. */
if (!use_sampled_normal) {
copy_v3_v3(out->normal, srd.face_normal);
return hit;
}
- /* Sampled normal calculation */
+ /* Sampled normal calculation. */
float radius;
- /* Update cursor data in SculptSession */
+ /* Update cursor data in SculptSession. */
invert_m4_m4(ob->imat, ob->obmat);
copy_m3_m4(mat, vc.rv3d->viewinv);
mul_m3_v3(mat, viewDir);
@@ -7346,19 +6724,20 @@ bool sculpt_cursor_geometry_info_update(bContext *C,
PBVHNode **nodes = sculpt_pbvh_gather_cursor_update(ob, sd, original, &totnode);
- /* In case there are no nodes under the cursor, return the face normal */
+ /* In case there are no nodes under the cursor, return the face normal. */
if (!totnode) {
MEM_SAFE_FREE(nodes);
copy_v3_v3(out->normal, srd.face_normal);
return true;
}
- /* Calculate the sampled normal */
- if (sculpt_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, sampled_normal)) {
+ /* Calculate the sampled normal. */
+ if (SCULPT_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, sampled_normal)) {
copy_v3_v3(out->normal, sampled_normal);
+ copy_v3_v3(ss->cursor_sampled_normal, sampled_normal);
}
else {
- /* Use face normal when there are no vertices to sample inside the cursor radius */
+ /* Use face normal when there are no vertices to sample inside the cursor radius. */
copy_v3_v3(out->normal, srd.face_normal);
}
MEM_SAFE_FREE(nodes);
@@ -7367,9 +6746,8 @@ bool sculpt_cursor_geometry_info_update(bContext *C,
/* Do a raycast in the tree to find the 3d brush location
* (This allows us to ignore the GL depth buffer)
- * Returns 0 if the ray doesn't hit the mesh, non-zero otherwise
- */
-bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
+ * Returns 0 if the ray doesn't hit the mesh, non-zero otherwise. */
+bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2])
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Object *ob;
@@ -7389,9 +6767,9 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
- sculpt_stroke_modifiers_check(C, ob, brush);
+ SCULPT_stroke_modifiers_check(C, ob, brush);
- depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
+ depth = SCULPT_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
BM_mesh_elem_table_ensure(ss->bm, BM_VERT);
@@ -7404,7 +6782,7 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
srd.ss = ob->sculpt;
srd.ray_start = ray_start;
srd.ray_normal = ray_normal;
- srd.hit = 0;
+ srd.hit = false;
srd.depth = depth;
srd.original = original;
srd.face_normal = face_normal;
@@ -7419,12 +6797,12 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
}
}
- if (hit == false) {
+ if (!hit) {
if (ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) {
SculptFindNearestToRayData srd = {
.original = original,
.ss = ob->sculpt,
- .hit = 0,
+ .hit = false,
.ray_start = ray_start,
.ray_normal = ray_normal,
.depth = FLT_MAX,
@@ -7449,15 +6827,14 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession
Brush *brush = BKE_paint_brush(&sd->paint);
MTex *mtex = &brush->mtex;
- /* init mtex nodes */
+ /* Init mtex nodes. */
if (mtex->tex && mtex->tex->nodetree) {
- /* has internal flag to detect it only does it once */
+ /* Has internal flag to detect it only does it once. */
ntreeTexBeginExecTree(mtex->tex->nodetree);
}
- /* TODO: Shouldn't really have to do this at the start of every
- * stroke, but sculpt would need some sort of notification when
- * changes are made to the texture. */
+ /* TODO: Shouldn't really have to do this at the start of every stroke, but sculpt would need
+ * some sort of notification when changes are made to the texture. */
sculpt_update_tex(scene, sd, ss);
}
@@ -7477,29 +6854,47 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op)
need_mask = true;
}
+ if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
+ need_mask = true;
+ }
+
view3d_operator_needs_opengl(C);
sculpt_brush_init_tex(scene, sd, ss);
- is_smooth = sculpt_needs_connectivity_info(brush, ss, mode);
+ is_smooth = sculpt_needs_connectivity_info(sd, brush, ss, mode);
BKE_sculpt_update_object_for_edit(depsgraph, ob, is_smooth, need_mask);
}
static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
{
+ SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- /* Restore the mesh before continuing with anchored stroke */
+ /* Restore the mesh before continuing with anchored stroke. */
if ((brush->flag & BRUSH_ANCHORED) ||
((brush->sculpt_tool == SCULPT_TOOL_GRAB ||
- brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM) &&
+ brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM ||
+ brush->sculpt_tool == SCULPT_TOOL_CLOTH) &&
BKE_brush_use_size_pressure(brush)) ||
(brush->flag & BRUSH_DRAG_DOT)) {
+
+ SculptUndoNode *unode = SCULPT_undo_get_first_node();
+ if (unode && unode->type == SCULPT_UNDO_FACE_SETS) {
+ for (int i = 0; i < ss->totfaces; i++) {
+ ss->face_sets[i] = unode->face_sets[i];
+ }
+ }
+
paint_mesh_restore_co(sd, ob);
+
+ if (ss->cache) {
+ MEM_SAFE_FREE(ss->cache->layer_displacement_factor);
+ }
}
}
-/* Copy the PBVH bounding box into the object's bounding box */
-void sculpt_update_object_bounding_box(Object *ob)
+/* Copy the PBVH bounding box into the object's bounding box. */
+void SCULPT_update_object_bounding_box(Object *ob)
{
if (ob->runtime.bb) {
float bb_min[3], bb_max[3];
@@ -7509,13 +6904,13 @@ void sculpt_update_object_bounding_box(Object *ob)
}
}
-static void sculpt_flush_update_step(bContext *C, SculptUpdateType update_flags)
+void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
- ARegion *ar = CTX_wm_region(C);
- MultiresModifierData *mmd = ss->multires;
+ ARegion *region = CTX_wm_region(C);
+ MultiresModifierData *mmd = ss->multires.modifier;
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -7536,24 +6931,40 @@ static void sculpt_flush_update_step(bContext *C, SculptUpdateType update_flags)
/* Slow update with full dependency graph update and all that comes with it.
* Needed when there are modifiers or full shading in the 3D viewport. */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
else {
- /* Fast path where we just update the BVH nodes that changed. */
+ /* Fast path where we just update the BVH nodes that changed, and redraw
+ * only the part of the 3D viewport where changes happened. */
+ rcti r;
if (update_flags & SCULPT_UPDATE_COORDS) {
BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB);
/* Update the object's bounding box too so that the object
* doesn't get incorrectly clipped during drawing in
* draw_mesh_object(). [#33790] */
- sculpt_update_object_bounding_box(ob);
+ SCULPT_update_object_bounding_box(ob);
}
- ED_region_tag_redraw(ar);
+ if (SCULPT_get_redraw_rect(region, CTX_wm_region_view3d(C), ob, &r)) {
+ if (ss->cache) {
+ ss->cache->current_r = r;
+ }
+
+ /* previous is not set in the current cache else
+ * the partial rect will always grow */
+ sculpt_extend_redraw_rect_previous(ob, &r);
+
+ r.xmin += region->winrct.xmin - 2;
+ r.xmax += region->winrct.xmin + 2;
+ r.ymin += region->winrct.ymin - 2;
+ r.ymax += region->winrct.ymin + 2;
+ ED_region_tag_redraw_partial(region, &r, true);
+ }
}
}
-static void sculpt_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags)
+void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags)
{
/* After we are done drawing the stroke, check if we need to do a more
* expensive depsgraph tag to update geometry. */
@@ -7562,16 +6973,18 @@ static void sculpt_flush_update_done(const bContext *C, Object *ob, SculptUpdate
RegionView3D *rv3d = CTX_wm_region_view3d(C);
SculptSession *ss = ob->sculpt;
Mesh *mesh = ob->data;
- bool need_tag = (ID_REAL_USERS(&mesh->id) > 1); /* Always needed for linked duplicates. */
+
+ /* Always needed for linked duplicates. */
+ bool need_tag = (ID_REAL_USERS(&mesh->id) > 1);
if (rv3d) {
rv3d->rflag &= ~RV3D_PAINTING;
}
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
bScreen *screen = WM_window_get_active_screen(win);
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl = sa->spacedata.first;
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ SpaceLink *sl = area->spacedata.first;
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
if (v3d != current_v3d) {
@@ -7581,9 +6994,9 @@ static void sculpt_flush_update_done(const bContext *C, Object *ob, SculptUpdate
/* Tag all 3D viewports for redraw now that we are done. Others
* viewports did not get a full redraw, and anti-aliasing for the
* current viewport was deactivated. */
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- ED_region_tag_redraw(ar);
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ ED_region_tag_redraw(region);
}
}
}
@@ -7602,9 +7015,9 @@ static void sculpt_flush_update_done(const bContext *C, Object *ob, SculptUpdate
BKE_pbvh_bmesh_after_stroke(ss->pbvh);
}
- /* optimization: if there is locked key and active modifiers present in */
+ /* Optimization: if there is locked key and active modifiers present in */
/* the stack, keyblock is updating at each step. otherwise we could update */
- /* keyblock only when stroke is finished */
+ /* keyblock only when stroke is finished. */
if (ss->shapekey_active && !ss->deform_modifiers_active) {
sculpt_update_keyblock(ob);
}
@@ -7615,7 +7028,7 @@ static void sculpt_flush_update_done(const bContext *C, Object *ob, SculptUpdate
}
/* Returns whether the mouse/stylus is over the mesh (1)
- * or over the background (0) */
+ * or over the background (0). */
static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), float x, float y)
{
float mouse[2], co[3];
@@ -7623,7 +7036,7 @@ static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), float x, float
mouse[0] = x;
mouse[1] = y;
- return sculpt_stroke_get_location(C, co, mouse);
+ return SCULPT_stroke_get_location(C, co, mouse);
}
static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
@@ -7642,12 +7055,12 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
sculpt_update_cache_invariants(C, sd, ss, op, mouse);
- sculpt_undo_push_begin(sculpt_tool_name(sd));
+ SCULPT_undo_push_begin(sculpt_tool_name(sd));
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
@@ -7661,7 +7074,7 @@ static void sculpt_stroke_update_step(bContext *C,
SculptSession *ss = ob->sculpt;
const Brush *brush = BKE_paint_brush(&sd->paint);
- sculpt_stroke_modifiers_check(C, ob, brush);
+ SCULPT_stroke_modifiers_check(C, ob, brush);
sculpt_update_cache_variants(C, sd, ob, itemptr);
sculpt_restore_mesh(sd, ob);
@@ -7678,14 +7091,14 @@ static void sculpt_stroke_update_step(bContext *C,
(float)(sd->detail_size * U.pixelsize) / 0.4f);
}
- if (sculpt_stroke_is_dynamic_topology(ss, brush)) {
+ if (SCULPT_stroke_is_dynamic_topology(ss, brush)) {
do_symmetrical_brush_actions(sd, ob, sculpt_topology_update, ups);
}
do_symmetrical_brush_actions(sd, ob, do_brush_action, ups);
sculpt_combine_proxies(sd, ob);
- /* hack to fix noise texture tearing mesh */
+ /* Hack to fix noise texture tearing mesh. */
sculpt_fix_noise_tear(sd, ob);
/* TODO(sergey): This is not really needed for the solid shading,
@@ -7699,7 +7112,7 @@ static void sculpt_stroke_update_step(bContext *C,
* sculpt_flush_update_step().
*/
if (ss->deform_modifiers_active) {
- sculpt_flush_stroke_deform(sd, ob, sculpt_tool_is_proxy_used(brush->sculpt_tool));
+ SCULPT_flush_stroke_deform(sd, ob, sculpt_tool_is_proxy_used(brush->sculpt_tool));
}
else if (ss->shapekey_active) {
sculpt_update_keyblock(ob);
@@ -7708,12 +7121,12 @@ static void sculpt_stroke_update_step(bContext *C,
ss->cache->first_time = false;
copy_v3_v3(ss->cache->true_last_location, ss->cache->true_location);
- /* Cleanup */
+ /* Cleanup. */
if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
- sculpt_flush_update_step(C, SCULPT_UPDATE_MASK);
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
}
else {
- sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS);
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
}
}
@@ -7735,22 +7148,22 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
SculptSession *ss = ob->sculpt;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- /* Finished */
+ /* Finished. */
if (ss->cache) {
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
Brush *brush = BKE_paint_brush(&sd->paint);
BLI_assert(brush == ss->cache->brush); /* const, so we shouldn't change. */
ups->draw_inverted = false;
- sculpt_stroke_modifiers_check(C, ob, brush);
+ SCULPT_stroke_modifiers_check(C, ob, brush);
- /* Alt-Smooth */
+ /* Alt-Smooth. */
if (ss->cache->alt_smooth) {
if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
brush->mask_tool = ss->cache->saved_mask_brush_tool;
}
- else if (brush->sculpt_tool == SCULPT_TOOL_SLIDE_RELAX) {
- /* Do nothing */
+ else if (ELEM(brush->sculpt_tool, SCULPT_TOOL_SLIDE_RELAX, SCULPT_TOOL_DRAW_FACE_SETS)) {
+ /* Do nothing. */
}
else {
BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size);
@@ -7761,20 +7174,20 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
}
}
- if (sculpt_automasking_enabled(ss, brush)) {
- sculpt_automasking_end(ob);
+ if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
+ SCULPT_automasking_end(ob);
}
- sculpt_cache_free(ss->cache);
+ SCULPT_cache_free(ss->cache);
ss->cache = NULL;
- sculpt_undo_push_end();
+ SCULPT_undo_push_end();
if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
- sculpt_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
}
else {
- sculpt_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
}
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -7793,7 +7206,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
stroke = paint_stroke_new(C,
op,
- sculpt_stroke_get_location,
+ SCULPT_stroke_get_location,
sculpt_stroke_test_start,
sculpt_stroke_update_step,
NULL,
@@ -7802,7 +7215,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
op->customdata = stroke;
- /* For tablet rotation */
+ /* For tablet rotation. */
ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click");
if (ignore_background_click && !over_mesh(C, op, event->x, event->y)) {
@@ -7814,7 +7227,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
paint_stroke_free(C, op);
return OPERATOR_FINISHED;
}
- /* add modal handler */
+ /* Add modal handler. */
WM_event_add_modal_handler(C, op);
OPERATOR_RETVAL_CHECK(retval);
@@ -7829,14 +7242,14 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
op->customdata = paint_stroke_new(C,
op,
- sculpt_stroke_get_location,
+ SCULPT_stroke_get_location,
sculpt_stroke_test_start,
sculpt_stroke_update_step,
NULL,
sculpt_stroke_done,
0);
- /* frees op->customdata */
+ /* Frees op->customdata. */
paint_stroke_exec(C, op);
return OPERATOR_FINISHED;
@@ -7851,14 +7264,14 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
/* XXX Canceling strokes that way does not work with dynamic topology,
* user will have to do real undo for now. See T46456. */
- if (ss->cache && !sculpt_stroke_is_dynamic_topology(ss, brush)) {
+ if (ss->cache && !SCULPT_stroke_is_dynamic_topology(ss, brush)) {
paint_mesh_restore_co(sd, ob);
}
paint_stroke_cancel(C, op);
if (ss->cache) {
- sculpt_cache_free(ss->cache);
+ SCULPT_cache_free(ss->cache);
ss->cache = NULL;
}
@@ -7867,22 +7280,22 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Sculpt";
ot->idname = "SCULPT_OT_brush_stroke";
ot->description = "Sculpt a stroke into the geometry";
- /* api callbacks */
+ /* API callbacks. */
ot->invoke = sculpt_brush_stroke_invoke;
ot->modal = paint_stroke_modal;
ot->exec = sculpt_brush_stroke_exec;
- ot->poll = sculpt_poll;
+ ot->poll = SCULPT_poll;
ot->cancel = sculpt_brush_stroke_cancel;
- /* flags (sculpt does own undo? (ton) */
+ /* Flags (sculpt does own undo? (ton)). */
ot->flag = OPTYPE_BLOCKING;
- /* properties */
+ /* Properties. */
paint_stroke_operator_properties(ot);
@@ -7893,17 +7306,29 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
"Clicks on the background do not start the stroke");
}
-/* Reset the copy of the mesh that is being sculpted on (currently just for the layer brush) */
+/* Reset the copy of the mesh that is being sculpted on (currently just for the layer brush). */
static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
{
- SculptSession *ss = CTX_data_active_object(C)->sculpt;
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
if (ss) {
- if (ss->layer_co) {
- MEM_freeN(ss->layer_co);
+ SCULPT_vertex_random_access_init(ss);
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false);
+
+ MEM_SAFE_FREE(ss->layer_base);
+
+ const int totvert = SCULPT_vertex_count_get(ss);
+ ss->layer_base = MEM_mallocN(sizeof(SculptLayerPersistentBase) * totvert,
+ "layer persistent base");
+
+ for (int i = 0; i < totvert; i++) {
+ copy_v3_v3(ss->layer_base[i].co, SCULPT_vertex_co_get(ss, i));
+ SCULPT_vertex_normal_get(ss, i, ss->layer_base[i].no);
+ ss->layer_base[i].disp = 0.0f;
}
- ss->layer_co = NULL;
}
return OPERATOR_FINISHED;
@@ -7911,373 +7336,14 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
static void SCULPT_OT_set_persistent_base(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Set Persistent Base";
ot->idname = "SCULPT_OT_set_persistent_base";
ot->description = "Reset the copy of the mesh that is being sculpted on";
- /* api callbacks */
+ /* API callbacks. */
ot->exec = sculpt_set_persistent_base_exec;
- ot->poll = sculpt_mode_poll;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/************************** Dynamic Topology **************************/
-
-static void sculpt_dynamic_topology_triangulate(BMesh *bm)
-{
- if (bm->totloop != bm->totface * 3) {
- BM_mesh_triangulate(
- bm, MOD_TRIANGULATE_QUAD_BEAUTY, MOD_TRIANGULATE_NGON_EARCLIP, 4, false, NULL, NULL, NULL);
- }
-}
-
-void sculpt_pbvh_clear(Object *ob)
-{
- SculptSession *ss = ob->sculpt;
-
- /* Clear out any existing DM and PBVH */
- if (ss->pbvh) {
- BKE_pbvh_free(ss->pbvh);
- ss->pbvh = NULL;
- }
-
- if (ss->pmap) {
- MEM_freeN(ss->pmap);
- ss->pmap = NULL;
- }
-
- if (ss->pmap_mem) {
- MEM_freeN(ss->pmap_mem);
- ss->pmap_mem = NULL;
- }
-
- BKE_object_free_derived_caches(ob);
-
- /* Tag to rebuild PBVH in depsgraph. */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-}
-
-void sculpt_dyntopo_node_layers_add(SculptSession *ss)
-{
- int cd_node_layer_index;
-
- char layer_id[] = "_dyntopo_node_id";
-
- cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id);
- if (cd_node_layer_index == -1) {
- BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_INT, layer_id);
- cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id);
- }
-
- ss->cd_vert_node_offset = CustomData_get_n_offset(
- &ss->bm->vdata,
- CD_PROP_INT,
- cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT));
-
- ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
-
- cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id);
- if (cd_node_layer_index == -1) {
- BM_data_layer_add_named(ss->bm, &ss->bm->pdata, CD_PROP_INT, layer_id);
- cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id);
- }
-
- ss->cd_face_node_offset = CustomData_get_n_offset(
- &ss->bm->pdata,
- CD_PROP_INT,
- cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT));
-
- ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
-}
-
-static void sculpt_dynamic_topology_enable_ex(Main *bmain,
- Depsgraph *depsgraph,
- Scene *scene,
- Object *ob)
-{
- SculptSession *ss = ob->sculpt;
- Mesh *me = ob->data;
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
-
- sculpt_pbvh_clear(ob);
-
- ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags & SCULPT_DYNTOPO_SMOOTH_SHADING) !=
- 0;
-
- /* Dynamic topology doesn't ensure selection state is valid, so remove [#36280] */
- BKE_mesh_mselect_clear(me);
-
- /* Create triangles-only BMesh */
- ss->bm = BM_mesh_create(&allocsize,
- &((struct BMeshCreateParams){
- .use_toolflags = false,
- }));
-
- BM_mesh_bm_from_me(ss->bm,
- me,
- (&(struct BMeshFromMeshParams){
- .calc_face_normal = true,
- .use_shapekey = true,
- .active_shapekey = ob->shapenr,
- }));
- sculpt_dynamic_topology_triangulate(ss->bm);
- BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
- sculpt_dyntopo_node_layers_add(ss);
- /* make sure the data for existing faces are initialized */
- if (me->totpoly != ss->bm->totface) {
- BM_mesh_normals_update(ss->bm);
- }
-
- /* Enable dynamic topology */
- me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
-
- /* Enable logging for undo/redo */
- ss->bm_log = BM_log_create(ss->bm);
-
- /* Update dependency graph, so modifiers that depend on dyntopo being enabled
- * are re-evaluated and the PBVH is re-created */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- BKE_scene_graph_update_tagged(depsgraph, bmain);
-}
-
-/* Free the sculpt BMesh and BMLog
- *
- * If 'unode' is given, the BMesh's data is copied out to the unode
- * before the BMesh is deleted so that it can be restored from */
-static void sculpt_dynamic_topology_disable_ex(
- Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, SculptUndoNode *unode)
-{
- SculptSession *ss = ob->sculpt;
- Mesh *me = ob->data;
-
- sculpt_pbvh_clear(ob);
-
- if (unode) {
- /* Free all existing custom data */
- CustomData_free(&me->vdata, me->totvert);
- CustomData_free(&me->edata, me->totedge);
- CustomData_free(&me->fdata, me->totface);
- CustomData_free(&me->ldata, me->totloop);
- CustomData_free(&me->pdata, me->totpoly);
-
- /* Copy over stored custom data */
- me->totvert = unode->geom_totvert;
- me->totloop = unode->geom_totloop;
- me->totpoly = unode->geom_totpoly;
- me->totedge = unode->geom_totedge;
- me->totface = 0;
- CustomData_copy(
- &unode->geom_vdata, &me->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, unode->geom_totvert);
- CustomData_copy(
- &unode->geom_edata, &me->edata, CD_MASK_MESH.emask, CD_DUPLICATE, unode->geom_totedge);
- CustomData_copy(
- &unode->geom_ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, unode->geom_totloop);
- CustomData_copy(
- &unode->geom_pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, unode->geom_totpoly);
-
- BKE_mesh_update_customdata_pointers(me, false);
- }
- else {
- BKE_sculptsession_bm_to_me(ob, true);
- }
-
- /* Clear data */
- me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
-
- /* typically valid but with global-undo they can be NULL, [#36234] */
- if (ss->bm) {
- BM_mesh_free(ss->bm);
- ss->bm = NULL;
- }
- if (ss->bm_log) {
- BM_log_free(ss->bm_log);
- ss->bm_log = NULL;
- }
-
- BKE_particlesystem_reset_all(ob);
- BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED);
-
- /* Update dependency graph, so modifiers that depend on dyntopo being enabled
- * are re-evaluated and the PBVH is re-created */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- BKE_scene_graph_update_tagged(depsgraph, bmain);
-}
-
-void sculpt_dynamic_topology_disable(bContext *C, SculptUndoNode *unode)
-{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- sculpt_dynamic_topology_disable_ex(bmain, depsgraph, scene, ob, unode);
-}
-
-static void sculpt_dynamic_topology_disable_with_undo(Main *bmain,
- Depsgraph *depsgraph,
- Scene *scene,
- Object *ob)
-{
- SculptSession *ss = ob->sculpt;
- if (ss->bm) {
- sculpt_undo_push_begin("Dynamic topology disable");
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
- sculpt_dynamic_topology_disable_ex(bmain, depsgraph, scene, ob, NULL);
- sculpt_undo_push_end();
- }
-}
-
-static void sculpt_dynamic_topology_enable_with_undo(Main *bmain,
- Depsgraph *depsgraph,
- Scene *scene,
- Object *ob)
-{
- SculptSession *ss = ob->sculpt;
- if (ss->bm == NULL) {
- sculpt_undo_push_begin("Dynamic topology enable");
- sculpt_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob);
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
- sculpt_undo_push_end();
- }
-}
-
-static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
-
- WM_cursor_wait(1);
-
- if (ss->bm) {
- sculpt_dynamic_topology_disable_with_undo(bmain, depsgraph, scene, ob);
- }
- else {
- sculpt_dynamic_topology_enable_with_undo(bmain, depsgraph, scene, ob);
- }
-
- WM_cursor_wait(0);
- WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-enum eDynTopoWarnFlag {
- DYNTOPO_WARN_VDATA = (1 << 0),
- DYNTOPO_WARN_EDATA = (1 << 1),
- DYNTOPO_WARN_LDATA = (1 << 2),
- DYNTOPO_WARN_MODIFIER = (1 << 3),
-};
-
-static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum eDynTopoWarnFlag flag)
-{
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Warning!"), ICON_ERROR);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- if (flag & (DYNTOPO_WARN_VDATA | DYNTOPO_WARN_EDATA | DYNTOPO_WARN_LDATA)) {
- const char *msg_error = TIP_("Vertex Data Detected!");
- const char *msg = TIP_("Dyntopo will not preserve vertex colors, UVs, or other customdata");
- uiItemL(layout, msg_error, ICON_INFO);
- uiItemL(layout, msg, ICON_NONE);
- uiItemS(layout);
- }
-
- if (flag & DYNTOPO_WARN_MODIFIER) {
- const char *msg_error = TIP_("Generative Modifiers Detected!");
- const char *msg = TIP_(
- "Keeping the modifiers will increase polycount when returning to object mode");
-
- uiItemL(layout, msg_error, ICON_INFO);
- uiItemL(layout, msg, ICON_NONE);
- uiItemS(layout);
- }
-
- uiItemFullO_ptr(layout, ot, IFACE_("OK"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, NULL);
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
-}
-
-static enum eDynTopoWarnFlag sculpt_dynamic_topology_check(Scene *scene, Object *ob)
-{
- Mesh *me = ob->data;
- SculptSession *ss = ob->sculpt;
-
- enum eDynTopoWarnFlag flag = 0;
-
- BLI_assert(ss->bm == NULL);
- UNUSED_VARS_NDEBUG(ss);
-
- for (int i = 0; i < CD_NUMTYPES; i++) {
- if (!ELEM(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX)) {
- if (CustomData_has_layer(&me->vdata, i)) {
- flag |= DYNTOPO_WARN_VDATA;
- }
- if (CustomData_has_layer(&me->edata, i)) {
- flag |= DYNTOPO_WARN_EDATA;
- }
- if (CustomData_has_layer(&me->ldata, i)) {
- flag |= DYNTOPO_WARN_LDATA;
- }
- }
- }
-
- {
- VirtualModifierData virtualModifierData;
- ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
-
- /* exception for shape keys because we can edit those */
- for (; md; md = md->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
- continue;
- }
-
- if (mti->type == eModifierTypeType_Constructive) {
- flag |= DYNTOPO_WARN_MODIFIER;
- break;
- }
- }
- }
-
- return flag;
-}
-
-static int sculpt_dynamic_topology_toggle_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
-{
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
-
- if (!ss->bm) {
- Scene *scene = CTX_data_scene(C);
- enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(scene, ob);
-
- if (flag) {
- /* The mesh has customdata that will be lost, let the user confirm this is OK */
- return dyntopo_warning_popup(C, op->type, flag);
- }
- }
-
- return sculpt_dynamic_topology_toggle_exec(C, op);
-}
-
-static void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Dynamic Topology Toggle";
- ot->idname = "SCULPT_OT_dynamic_topology_toggle";
- ot->description = "Dynamic topology alters the mesh topology while sculpting";
-
- /* api callbacks */
- ot->invoke = sculpt_dynamic_topology_toggle_invoke;
- ot->exec = sculpt_dynamic_topology_toggle_exec;
- ot->poll = sculpt_mode_poll;
+ ot->poll = SCULPT_mode_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -8288,33 +7354,26 @@ static int sculpt_optimize_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_active_object(C);
- sculpt_pbvh_clear(ob);
+ SCULPT_pbvh_clear(ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
-static bool sculpt_and_dynamic_topology_poll(bContext *C)
-{
- Object *ob = CTX_data_active_object(C);
-
- return sculpt_mode_poll(C) && ob->sculpt->bm;
-}
-
/* The BVH gets less optimal more quickly with dynamic topology than
* regular sculpting. There is no doubt more clever stuff we can do to
* optimize it on the fly, but for now this gives the user a nicer way
* to recalculate it than toggling modes. */
static void SCULPT_OT_optimize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Optimize";
+ /* Identifiers. */
+ ot->name = "Rebuild BVH";
ot->idname = "SCULPT_OT_optimize";
ot->description = "Recalculate the sculpt BVH to improve performance";
- /* api callbacks */
+ /* API callbacks. */
ot->exec = sculpt_optimize_exec;
- ot->poll = sculpt_and_dynamic_topology_poll;
+ ot->poll = SCULPT_mode_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -8324,9 +7383,8 @@ static void SCULPT_OT_optimize(wmOperatorType *ot)
static bool sculpt_no_multires_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- if (ss && ss->pbvh && sculpt_mode_poll(C)) {
- return BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS;
+ if (SCULPT_mode_poll(C) && ob->sculpt && ob->sculpt->pbvh) {
+ return BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_GRIDS;
}
return false;
}
@@ -8344,38 +7402,38 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
switch (BKE_pbvh_type(pbvh)) {
case PBVH_BMESH:
- /* Dyntopo Symmetrize */
+ /* Dyntopo Symmetrize. */
/* To simplify undo for symmetrize, all BMesh elements are logged
* as deleted, then after symmetrize operation all BMesh elements
* are logged as added (as opposed to attempting to store just the
- * parts that symmetrize modifies) */
- sculpt_undo_push_begin("Dynamic topology symmetrize");
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_SYMMETRIZE);
+ * parts that symmetrize modifies). */
+ SCULPT_undo_push_begin("Dynamic topology symmetrize");
+ SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_SYMMETRIZE);
BM_log_before_all_removed(ss->bm, ss->bm_log);
BM_mesh_toolflags_set(ss->bm, true);
- /* Symmetrize and re-triangulate */
+ /* Symmetrize and re-triangulate. */
BMO_op_callf(ss->bm,
(BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
"symmetrize input=%avef direction=%i dist=%f",
sd->symmetrize_direction,
0.00001f);
- sculpt_dynamic_topology_triangulate(ss->bm);
+ SCULPT_dynamic_topology_triangulate(ss->bm);
- /* bisect operator flags edges (keep tags clean for edge queue) */
+ /* Bisect operator flags edges (keep tags clean for edge queue). */
BM_mesh_elem_hflag_disable_all(ss->bm, BM_EDGE, BM_ELEM_TAG, false);
BM_mesh_toolflags_set(ss->bm, false);
- /* Finish undo */
+ /* Finish undo. */
BM_log_all_added(ss->bm, ss->bm_log);
- sculpt_undo_push_end();
+ SCULPT_undo_push_end();
break;
case PBVH_FACES:
- /* Mesh Symmetrize */
+ /* Mesh Symmetrize. */
ED_sculpt_undo_geometry_begin(ob, "mesh symmetrize");
Mesh *mesh = ob->data;
Mesh *mesh_mirror;
@@ -8422,8 +7480,8 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- /* Redraw */
- sculpt_pbvh_clear(ob);
+ /* Redraw. */
+ SCULPT_pbvh_clear(ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -8431,12 +7489,12 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
static void SCULPT_OT_symmetrize(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Symmetrize";
ot->idname = "SCULPT_OT_symmetrize";
ot->description = "Symmetrize the topology modifications";
- /* api callbacks */
+ /* API callbacks. */
ot->exec = sculpt_symmetrize_exec;
ot->poll = sculpt_no_multires_poll;
}
@@ -8445,12 +7503,34 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot)
static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- /* Create persistent sculpt mode data */
+ /* Create persistent sculpt mode data. */
BKE_sculpt_toolsettings_data_ensure(scene);
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
ob->sculpt->mode_type = OB_MODE_SCULPT;
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false);
+
+ /* Here we can detect geometry that was just added to Sculpt Mode as it has the
+ * SCULPT_FACE_SET_NONE assigned, so we can create a new Face Set for it. */
+ /* In sculpt mode all geometry that is assigned to SCULPT_FACE_SET_NONE is considered as not
+ * initialized, which is used is some operators that modify the mesh topology to preform certain
+ * actions in the new polys. After these operations are finished, all polys should have a valid
+ * face set ID assigned (different from SCULPT_FACE_SET_NONE) to manage their visibility
+ * correctly. */
+ /* TODO(pablodp606): Based on this we can improve the UX in future tools for creating new
+ * objects, like moving the transform pivot position to the new area or masking existing
+ * geometry. */
+ SculptSession *ss = ob->sculpt;
+ const int new_face_set = SCULPT_face_set_next_available_get(ss);
+ for (int i = 0; i < ss->totfaces; i++) {
+ if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) {
+ ss->face_sets[i] = new_face_set;
+ }
+ }
+
+ /* Update the Face Sets visibility with the vertex visibility changes that may have been done
+ * outside Sculpt Mode */
+ SCULPT_visibility_sync_all_vertex_to_face_sets(ob->sculpt);
}
static int ed_object_sculptmode_flush_recalc_flag(Scene *scene,
@@ -8458,9 +7538,9 @@ static int ed_object_sculptmode_flush_recalc_flag(Scene *scene,
MultiresModifierData *mmd)
{
int flush_recalc = 0;
- /* multires in sculpt mode could have different from object mode subdivision level */
- flush_recalc |= mmd && BKE_multires_sculpt_level_get(mmd) != mmd->lvl;
- /* if object has got active modifiers, it's dm could be different in sculpt mode */
+ /* Multires in sculpt mode could have different from object mode subdivision level. */
+ flush_recalc |= mmd && mmd->sculptlvl != mmd->lvl;
+ /* If object has got active modifiers, it's dm could be different in sculpt mode. */
flush_recalc |= sculpt_has_active_modifiers(scene, ob);
return flush_recalc;
}
@@ -8475,7 +7555,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
const int mode_flag = OB_MODE_SCULPT;
Mesh *me = BKE_mesh_from_object(ob);
- /* Enter sculptmode */
+ /* Enter sculpt mode. */
ob->mode |= mode_flag;
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
@@ -8486,22 +7566,21 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
- /* Create sculpt mode session data */
+ /* Create sculpt mode session data. */
if (ob->sculpt) {
BKE_sculptsession_free(ob);
}
/* Make sure derived final from original object does not reference possibly
- * freed memory.
- */
+ * freed memory. */
BKE_object_free_derived_caches(ob);
sculpt_init_session(depsgraph, scene, ob);
- /* Mask layer is required */
+ /* Mask layer is required. */
if (mmd) {
/* XXX, we could attempt to support adding mask data mid-sculpt mode (with multi-res)
- * but this ends up being quite tricky (and slow) */
+ * but this ends up being quite tricky (and slow). */
BKE_sculpt_mask_layers_ensure(ob, mmd);
}
@@ -8517,7 +7596,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
Paint *paint = BKE_paint_get_active_from_paintmode(scene, PAINT_MODE_SCULPT);
BKE_paint_init(bmain, scene, PAINT_MODE_SCULPT, PAINT_CURSOR_SCULPT);
- paint_cursor_start_explicit(paint, bmain->wm.first, sculpt_poll_view3d);
+ paint_cursor_start_explicit(paint, bmain->wm.first, SCULPT_poll_view3d);
/* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
* As long as no data was added that is not supported. */
@@ -8530,7 +7609,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
message_unsupported = TIP_("multi-res modifier");
}
else {
- enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(scene, ob);
+ enum eDynTopoWarnFlag flag = SCULPT_dynamic_topology_check(scene, ob);
if (flag == 0) {
/* pass */
}
@@ -8555,14 +7634,14 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
/* Needed because we may be entering this mode before the undo system loads. */
wmWindowManager *wm = bmain->wm.first;
bool has_undo = wm->undo_stack != NULL;
- /* undo push is needed to prevent memory leak */
+ /* Undo push is needed to prevent memory leak. */
if (has_undo) {
- sculpt_undo_push_begin("Dynamic topology enable");
+ SCULPT_undo_push_begin("Dynamic topology enable");
}
- sculpt_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob);
+ SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob);
if (has_undo) {
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
- sculpt_undo_push_end();
+ SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ SCULPT_undo_push_end();
}
}
else {
@@ -8599,8 +7678,7 @@ void ED_object_sculptmode_exit_ex(Main *bmain, Depsgraph *depsgraph, Scene *scen
#endif
/* Always for now, so leaving sculpt mode always ensures scene is in
- * a consistent state.
- */
+ * a consistent state. */
if (true || /* flush_recalc || */ (ob->sculpt && ob->sculpt->bm)) {
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
@@ -8608,14 +7686,14 @@ void ED_object_sculptmode_exit_ex(Main *bmain, Depsgraph *depsgraph, Scene *scen
if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
/* Dynamic topology must be disabled before exiting sculpt
* mode to ensure the undo stack stays in a consistent
- * state */
+ * state. */
sculpt_dynamic_topology_disable_with_undo(bmain, depsgraph, scene, ob);
- /* store so we know to re-enable when entering sculpt mode */
+ /* Store so we know to re-enable when entering sculpt mode. */
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
}
- /* Leave sculptmode */
+ /* Leave sculpt mode. */
ob->mode &= ~mode_flag;
BKE_sculptsession_free(ob);
@@ -8674,7 +7752,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
* while it works it causes lag when undoing the first undo step, see T71564. */
wmWindowManager *wm = CTX_wm_manager(C);
if (wm->op_undo_depth <= 1) {
- sculpt_undo_push_begin(op->type->name);
+ SCULPT_undo_push_begin(op->type->name);
}
}
}
@@ -8691,1545 +7769,19 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
static void SCULPT_OT_sculptmode_toggle(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Sculpt Mode";
ot->idname = "SCULPT_OT_sculptmode_toggle";
ot->description = "Toggle sculpt mode in 3D view";
- /* api callbacks */
+ /* API callbacks. */
ot->exec = sculpt_mode_toggle_exec;
ot->poll = ED_operator_object_active_editable_mesh;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static bool sculpt_and_constant_or_manual_detail_poll(bContext *C)
-{
- Object *ob = CTX_data_active_object(C);
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
-
- return sculpt_mode_poll(C) && ob->sculpt->bm &&
- (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL));
-}
-
-static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- float size;
- float bb_min[3], bb_max[3], center[3], dim[3];
- int i, totnodes;
- PBVHNode **nodes;
-
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnodes);
-
- if (!totnodes) {
- return OPERATOR_CANCELLED;
- }
-
- for (i = 0; i < totnodes; i++) {
- BKE_pbvh_node_mark_topology_update(nodes[i]);
- }
- /* get the bounding box, it's center and size */
- BKE_pbvh_bounding_box(ob->sculpt->pbvh, bb_min, bb_max);
- add_v3_v3v3(center, bb_min, bb_max);
- mul_v3_fl(center, 0.5f);
- sub_v3_v3v3(dim, bb_max, bb_min);
- size = max_fff(dim[0], dim[1], dim[2]);
-
- /* update topology size */
- float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat));
- BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
-
- sculpt_undo_push_begin("Dynamic topology flood fill");
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS);
-
- while (BKE_pbvh_bmesh_update_topology(
- ss->pbvh, PBVH_Collapse | PBVH_Subdivide, center, NULL, size, false, false)) {
- for (i = 0; i < totnodes; i++) {
- BKE_pbvh_node_mark_topology_update(nodes[i]);
- }
- }
-
- MEM_SAFE_FREE(nodes);
- sculpt_undo_push_end();
-
- /* force rebuild of pbvh for better BB placement */
- sculpt_pbvh_clear(ob);
- /* Redraw */
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
-}
-
-static void SCULPT_OT_detail_flood_fill(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Detail Flood Fill";
- ot->idname = "SCULPT_OT_detail_flood_fill";
- ot->description = "Flood fill the mesh with the selected detail setting";
-
- /* api callbacks */
- ot->exec = sculpt_detail_flood_fill_exec;
- ot->poll = sculpt_and_constant_or_manual_detail_poll;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-typedef enum eSculptSampleDetailModeTypes {
- SAMPLE_DETAIL_DYNTOPO = 0,
- SAMPLE_DETAIL_VOXEL = 1,
-} eSculptSampleDetailModeTypes;
-
-static EnumPropertyItem prop_sculpt_sample_detail_mode_types[] = {
- {SAMPLE_DETAIL_DYNTOPO, "DYNTOPO", 0, "Dyntopo", "Sample dyntopo detail"},
- {SAMPLE_DETAIL_VOXEL, "VOXEL", 0, "Voxel", "Sample mesh voxel size"},
- {0, NULL, 0, NULL, NULL},
-};
-
-static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my)
-{
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- Object *ob = vc->obact;
- Mesh *mesh = ob->data;
-
- SculptSession *ss = ob->sculpt;
- SculptCursorGeometryInfo sgi;
- sculpt_vertex_random_access_init(ss);
-
- /* Update the active vertex */
- float mouse[2] = {mx, my};
- sculpt_cursor_geometry_info_update(C, &sgi, mouse, false);
- BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false);
-
- /* Average the edge length of the connected edges to the active vertex */
- int active_vertex = sculpt_active_vertex_get(ss);
- const float *active_vertex_co = sculpt_active_vertex_co_get(ss);
- float edge_length = 0.0f;
- int tot = 0;
- SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, active_vertex, ni)
- {
- edge_length += len_v3v3(active_vertex_co, sculpt_vertex_co_get(ss, ni.index));
- tot += 1;
- }
- sculpt_vertex_neighbors_iter_end(ni);
- if (tot > 0) {
- mesh->remesh_voxel_size = edge_length / (float)tot;
- }
-}
-
-static void sample_detail_dyntopo(bContext *C, ViewContext *vc, ARegion *ar, int mx, int my)
-{
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- Object *ob = vc->obact;
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- sculpt_stroke_modifiers_check(C, ob, brush);
-
- float mouse[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
- float ray_start[3], ray_end[3], ray_normal[3];
- float depth = sculpt_raycast_init(vc, mouse, ray_start, ray_end, ray_normal, false);
-
- SculptDetailRaycastData srd;
- srd.hit = 0;
- srd.ray_start = ray_start;
- srd.depth = depth;
- srd.edge_length = 0.0f;
- isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
-
- BKE_pbvh_raycast(ob->sculpt->pbvh, sculpt_raycast_detail_cb, &srd, ray_start, ray_normal, false);
-
- if (srd.hit && srd.edge_length > 0.0f) {
- /* Convert edge length to world space detail resolution. */
- sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat));
- }
-}
-
-static int sample_detail(bContext *C, int mx, int my, int mode)
-{
- /* Find 3D view to pick from. */
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_VIEW3D, mx, my);
- ARegion *ar = (sa) ? BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my) : NULL;
- if (ar == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- /* Set context to 3D view. */
- ScrArea *prev_sa = CTX_wm_area(C);
- ARegion *prev_ar = CTX_wm_region(C);
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
-
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc, depsgraph);
-
- Object *ob = vc.obact;
- SculptSession *ss = ob->sculpt;
-
- if (!ss->pbvh) {
- return OPERATOR_CANCELLED;
- }
-
- /* Pick sample detail. */
- switch (mode) {
- case SAMPLE_DETAIL_DYNTOPO:
- if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
- CTX_wm_area_set(C, prev_sa);
- CTX_wm_region_set(C, prev_ar);
- return OPERATOR_CANCELLED;
- }
- sample_detail_dyntopo(C, &vc, ar, mx, my);
- break;
- case SAMPLE_DETAIL_VOXEL:
- if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
- CTX_wm_area_set(C, prev_sa);
- CTX_wm_region_set(C, prev_ar);
- return OPERATOR_CANCELLED;
- }
- sample_detail_voxel(C, &vc, mx, my);
- break;
- }
-
- /* Restore context. */
- CTX_wm_area_set(C, prev_sa);
- CTX_wm_region_set(C, prev_ar);
-
- return OPERATOR_FINISHED;
-}
-
-static int sculpt_sample_detail_size_exec(bContext *C, wmOperator *op)
-{
- int ss_co[2];
- RNA_int_get_array(op->ptr, "location", ss_co);
- int mode = RNA_enum_get(op->ptr, "mode");
- return sample_detail(C, ss_co[0], ss_co[1], mode);
-}
-
-static int sculpt_sample_detail_size_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e))
-{
- ED_workspace_status_text(C, TIP_("Click on the mesh to set the detail"));
- WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EYEDROPPER);
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int sculpt_sample_detail_size_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- switch (event->type) {
- case LEFTMOUSE:
- if (event->val == KM_PRESS) {
- int ss_co[2] = {event->x, event->y};
-
- int mode = RNA_enum_get(op->ptr, "mode");
- sample_detail(C, ss_co[0], ss_co[1], mode);
-
- RNA_int_set_array(op->ptr, "location", ss_co);
- WM_cursor_modal_restore(CTX_wm_window(C));
- ED_workspace_status_text(C, NULL);
- WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
-
- return OPERATOR_FINISHED;
- }
- break;
-
- case RIGHTMOUSE: {
- WM_cursor_modal_restore(CTX_wm_window(C));
- ED_workspace_status_text(C, NULL);
-
- return OPERATOR_CANCELLED;
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Sample Detail Size";
- ot->idname = "SCULPT_OT_sample_detail_size";
- ot->description = "Sample the mesh detail on clicked point";
-
- /* api callbacks */
- ot->invoke = sculpt_sample_detail_size_invoke;
- ot->exec = sculpt_sample_detail_size_exec;
- ot->modal = sculpt_sample_detail_size_modal;
- ot->poll = sculpt_mode_poll;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int_array(ot->srna,
- "location",
- 2,
- NULL,
- 0,
- SHRT_MAX,
- "Location",
- "Screen Coordinates of sampling",
- 0,
- SHRT_MAX);
- RNA_def_enum(ot->srna,
- "mode",
- prop_sculpt_sample_detail_mode_types,
- SAMPLE_DETAIL_DYNTOPO,
- "Detail Mode",
- "Target sculpting workflow that is going to use the sampled size");
-}
-
-/* Dynamic-topology detail size
- *
- * This should be improved further, perhaps by showing a triangle
- * grid rather than brush alpha */
-static void set_brush_rc_props(PointerRNA *ptr, const char *prop)
-{
- char *path = BLI_sprintfN("tool_settings.sculpt.brush.%s", prop);
- RNA_string_set(ptr, "data_path_primary", path);
- MEM_freeN(path);
-}
-
-static int sculpt_set_detail_size_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
-
- PointerRNA props_ptr;
- wmOperatorType *ot = WM_operatortype_find("WM_OT_radial_control", true);
-
- WM_operator_properties_create_ptr(&props_ptr, ot);
-
- if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
- set_brush_rc_props(&props_ptr, "constant_detail_resolution");
- RNA_string_set(
- &props_ptr, "data_path_primary", "tool_settings.sculpt.constant_detail_resolution");
- }
- else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
- set_brush_rc_props(&props_ptr, "constant_detail_resolution");
- RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_percent");
- }
- else {
- set_brush_rc_props(&props_ptr, "detail_size");
- RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_size");
- }
-
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
-
- WM_operator_properties_free(&props_ptr);
-
- return OPERATOR_FINISHED;
-}
-
-static void SCULPT_OT_set_detail_size(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Detail Size";
- ot->idname = "SCULPT_OT_set_detail_size";
- ot->description =
- "Set the mesh detail (either relative or constant one, depending on current dyntopo mode)";
-
- /* api callbacks */
- ot->exec = sculpt_set_detail_size_exec;
- ot->poll = sculpt_and_dynamic_topology_poll;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-static void filter_cache_init_task_cb(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- PBVHNode *node = data->nodes[i];
-
- sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
-}
-
-static void sculpt_filter_cache_init(Object *ob, Sculpt *sd)
-{
- SculptSession *ss = ob->sculpt;
- PBVH *pbvh = ob->sculpt->pbvh;
-
- ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
-
- ss->filter_cache->random_seed = rand();
-
- float center[3] = {0.0f};
- SculptSearchSphereData search_data = {
- .original = true,
- .center = center,
- .radius_squared = FLT_MAX,
- .ignore_fully_masked = true,
-
- };
- BKE_pbvh_search_gather(pbvh,
- sculpt_search_sphere_cb,
- &search_data,
- &ss->filter_cache->nodes,
- &ss->filter_cache->totnode);
-
- for (int i = 0; i < ss->filter_cache->totnode; i++) {
- BKE_pbvh_node_mark_normals_update(ss->filter_cache->nodes[i]);
- }
-
- /* mesh->runtime.subdiv_ccg is not available. Updating of the normals is done during drawing.
- * Filters can't use normals in multires. */
- if (BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) {
- BKE_pbvh_update_normals(ss->pbvh, NULL);
- }
-
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = ss->filter_cache->nodes,
- };
-
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(
- &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BKE_pbvh_parallel_range(
- 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
-}
-
-static void sculpt_filter_cache_free(SculptSession *ss)
-{
- if (ss->filter_cache->nodes) {
- MEM_freeN(ss->filter_cache->nodes);
- }
- if (ss->filter_cache->mask_update_it) {
- MEM_freeN(ss->filter_cache->mask_update_it);
- }
- if (ss->filter_cache->prev_mask) {
- MEM_freeN(ss->filter_cache->prev_mask);
- }
- if (ss->filter_cache->normal_factor) {
- MEM_freeN(ss->filter_cache->normal_factor);
- }
- MEM_freeN(ss->filter_cache);
- ss->filter_cache = NULL;
-}
-
-typedef enum eSculptMeshFilterTypes {
- MESH_FILTER_SMOOTH = 0,
- MESH_FILTER_SCALE = 1,
- MESH_FILTER_INFLATE = 2,
- MESH_FILTER_SPHERE = 3,
- MESH_FILTER_RANDOM = 4,
- MESH_FILTER_RELAX = 5,
-} eSculptMeshFilterTypes;
-
-static EnumPropertyItem prop_mesh_filter_types[] = {
- {MESH_FILTER_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth mesh"},
- {MESH_FILTER_SCALE, "SCALE", 0, "Scale", "Scale mesh"},
- {MESH_FILTER_INFLATE, "INFLATE", 0, "Inflate", "Inflate mesh"},
- {MESH_FILTER_SPHERE, "SPHERE", 0, "Sphere", "Morph into sphere"},
- {MESH_FILTER_RANDOM, "RANDOM", 0, "Random", "Randomize vertex positions"},
- {MESH_FILTER_RELAX, "RELAX", 0, "Relax", "Relax mesh"},
- {0, NULL, 0, NULL, NULL},
-};
-
-typedef enum eMeshFilterDeformAxis {
- MESH_FILTER_DEFORM_X = 1 << 0,
- MESH_FILTER_DEFORM_Y = 1 << 1,
- MESH_FILTER_DEFORM_Z = 1 << 2,
-} eMeshFilterDeformAxis;
-
-static EnumPropertyItem prop_mesh_filter_deform_axis_items[] = {
- {MESH_FILTER_DEFORM_X, "X", 0, "X", "Deform in the X axis"},
- {MESH_FILTER_DEFORM_Y, "Y", 0, "Y", "Deform in the Y axis"},
- {MESH_FILTER_DEFORM_Z, "Z", 0, "Z", "Deform in the Z axis"},
- {0, NULL, 0, NULL, NULL},
-};
-
-static bool sculpt_mesh_filter_needs_pmap(int filter_type)
-{
- return ELEM(filter_type, MESH_FILTER_SMOOTH, MESH_FILTER_RELAX);
-}
-
-static void mesh_filter_task_cb(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- PBVHNode *node = data->nodes[i];
-
- const int filter_type = data->filter_type;
-
- SculptOrigVertData orig_data;
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[i]);
-
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
- {
- sculpt_orig_vert_data_update(&orig_data, &vd);
- float orig_co[3], val[3], avg[3], normal[3], disp[3], disp2[3], transform[3][3], final_pos[3];
- float fade = vd.mask ? *vd.mask : 0.0f;
- fade = 1 - fade;
- fade *= data->filter_strength;
-
- if (fade == 0.0f) {
- continue;
- }
-
- if (filter_type == MESH_FILTER_RELAX) {
- copy_v3_v3(orig_co, vd.co);
- }
- else {
- copy_v3_v3(orig_co, orig_data.co);
- }
- switch (filter_type) {
- case MESH_FILTER_SMOOTH:
- CLAMP(fade, -1.0f, 1.0f);
- switch (BKE_pbvh_type(ss->pbvh)) {
- case PBVH_FACES:
- neighbor_average(ss, avg, vd.index);
- break;
- case PBVH_BMESH:
- bmesh_neighbor_average(avg, vd.bm_vert);
- break;
- case PBVH_GRIDS:
- grids_neighbor_average(ss, avg, vd.index);
- break;
- }
- sub_v3_v3v3(val, avg, orig_co);
- madd_v3_v3v3fl(val, orig_co, val, fade);
- sub_v3_v3v3(disp, val, orig_co);
- break;
- case MESH_FILTER_INFLATE:
- normal_short_to_float_v3(normal, orig_data.no);
- mul_v3_v3fl(disp, normal, fade);
- break;
- case MESH_FILTER_SCALE:
- unit_m3(transform);
- scale_m3_fl(transform, 1 + fade);
- copy_v3_v3(val, orig_co);
- mul_m3_v3(transform, val);
- sub_v3_v3v3(disp, val, orig_co);
- break;
- case MESH_FILTER_SPHERE:
- normalize_v3_v3(disp, orig_co);
- if (fade > 0) {
- mul_v3_v3fl(disp, disp, fade);
- }
- else {
- mul_v3_v3fl(disp, disp, -fade);
- }
-
- unit_m3(transform);
- if (fade > 0) {
- scale_m3_fl(transform, 1 - fade);
- }
- else {
- scale_m3_fl(transform, 1 + fade);
- }
- copy_v3_v3(val, orig_co);
- mul_m3_v3(transform, val);
- sub_v3_v3v3(disp2, val, orig_co);
-
- mid_v3_v3v3(disp, disp, disp2);
- break;
- case MESH_FILTER_RANDOM: {
- normal_short_to_float_v3(normal, orig_data.no);
- /* Index is not unique for multires, so hash by vertex coordinates. */
- const uint *hash_co = (const uint *)orig_co;
- const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^
- BLI_hash_int_2d(hash_co[2], ss->filter_cache->random_seed);
- mul_v3_fl(normal, hash * (1.0f / (float)0xFFFFFFFF) - 0.5f);
- mul_v3_v3fl(disp, normal, fade);
- break;
- }
- case MESH_FILTER_RELAX: {
- sculpt_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), val);
- sub_v3_v3v3(disp, val, vd.co);
- break;
- }
- }
-
- for (int it = 0; it < 3; it++) {
- if (!ss->filter_cache->enabled_axis[it]) {
- disp[it] = 0.0f;
- }
- }
-
- add_v3_v3v3(final_pos, orig_co, disp);
- copy_v3_v3(vd.co, final_pos);
- if (vd.mvert) {
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
-
- BKE_pbvh_node_mark_update(node);
-}
-
-static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Object *ob = CTX_data_active_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- SculptSession *ss = ob->sculpt;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- int filter_type = RNA_enum_get(op->ptr, "type");
- float filter_strength = RNA_float_get(op->ptr, "strength");
-
- if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- sculpt_filter_cache_free(ss);
- sculpt_undo_push_end();
- sculpt_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
- return OPERATOR_FINISHED;
- }
-
- if (event->type != MOUSEMOVE) {
- return OPERATOR_RUNNING_MODAL;
- }
-
- float len = event->prevclickx - event->mval[0];
- filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
-
- sculpt_vertex_random_access_init(ss);
-
- bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type);
- BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false);
-
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = ss->filter_cache->nodes,
- .filter_type = filter_type,
- .filter_strength = filter_strength,
- };
-
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(
- &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings);
-
- if (ss->deform_modifiers_active || ss->shapekey_active) {
- sculpt_flush_stroke_deform(sd, ob, true);
- }
-
- /* The relax mesh filter needs the updated normals of the modified mesh after each iteration */
- if (filter_type == MESH_FILTER_RELAX) {
- BKE_pbvh_update_normals(ss->pbvh, ss->subdiv_ccg);
- }
-
- sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- Object *ob = CTX_data_active_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- int filter_type = RNA_enum_get(op->ptr, "type");
- SculptSession *ss = ob->sculpt;
- PBVH *pbvh = ob->sculpt->pbvh;
-
- int deform_axis = RNA_enum_get(op->ptr, "deform_axis");
- if (deform_axis == 0) {
- return OPERATOR_CANCELLED;
- }
-
- sculpt_vertex_random_access_init(ss);
-
- bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type);
- BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false);
-
- if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_pmap && !ob->sculpt->pmap) {
- return OPERATOR_CANCELLED;
- }
-
- sculpt_undo_push_begin("Mesh filter");
-
- sculpt_filter_cache_init(ob, sd);
-
- ss->filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
- ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
- ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
-
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Filter mesh";
- ot->idname = "SCULPT_OT_mesh_filter";
- ot->description = "Applies a filter to modify the current mesh";
-
- /* api callbacks */
- ot->invoke = sculpt_mesh_filter_invoke;
- ot->modal = sculpt_mesh_filter_modal;
- ot->poll = sculpt_mode_poll;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* rna */
- RNA_def_enum(ot->srna,
- "type",
- prop_mesh_filter_types,
- MESH_FILTER_INFLATE,
- "Filter type",
- "Operation that is going to be applied to the mesh");
- RNA_def_float(
- ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f);
- RNA_def_enum_flag(ot->srna,
- "deform_axis",
- prop_mesh_filter_deform_axis_items,
- MESH_FILTER_DEFORM_X | MESH_FILTER_DEFORM_Y | MESH_FILTER_DEFORM_Z,
- "Deform axis",
- "Apply the deformation in the selected axis");
-}
-
-typedef enum eSculptMaskFilterTypes {
- MASK_FILTER_SMOOTH = 0,
- MASK_FILTER_SHARPEN = 1,
- MASK_FILTER_GROW = 2,
- MASK_FILTER_SHRINK = 3,
- MASK_FILTER_CONTRAST_INCREASE = 5,
- MASK_FILTER_CONTRAST_DECREASE = 6,
-} eSculptMaskFilterTypes;
-
-static EnumPropertyItem prop_mask_filter_types[] = {
- {MASK_FILTER_SMOOTH, "SMOOTH", 0, "Smooth Mask", "Smooth mask"},
- {MASK_FILTER_SHARPEN, "SHARPEN", 0, "Sharpen Mask", "Sharpen mask"},
- {MASK_FILTER_GROW, "GROW", 0, "Grow Mask", "Grow mask"},
- {MASK_FILTER_SHRINK, "SHRINK", 0, "Shrink Mask", "Shrink mask"},
- {MASK_FILTER_CONTRAST_INCREASE,
- "CONTRAST_INCREASE",
- 0,
- "Increase contrast",
- "Increase the contrast of the paint mask"},
- {MASK_FILTER_CONTRAST_DECREASE,
- "CONTRAST_DECREASE",
- 0,
- "Decrease contrast",
- "Decrease the contrast of the paint mask"},
- {0, NULL, 0, NULL, NULL},
-};
-
-static void mask_filter_task_cb(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- PBVHNode *node = data->nodes[i];
- bool update = false;
-
- const int mode = data->filter_type;
- float contrast = 0.0f;
-
- PBVHVertexIter vd;
-
- if (mode == MASK_FILTER_CONTRAST_INCREASE) {
- contrast = 0.1f;
- }
-
- if (mode == MASK_FILTER_CONTRAST_DECREASE) {
- contrast = -0.1f;
- }
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
- {
- float delta, gain, offset, max, min;
- float prev_val = *vd.mask;
- SculptVertexNeighborIter ni;
- switch (mode) {
- case MASK_FILTER_SMOOTH:
- case MASK_FILTER_SHARPEN: {
- float val = 0.0f;
-
- switch (BKE_pbvh_type(ss->pbvh)) {
- case PBVH_FACES:
- val = neighbor_average_mask(ss, vd.index);
- break;
- case PBVH_BMESH:
- val = bmesh_neighbor_average_mask(vd.bm_vert, vd.cd_vert_mask_offset);
- break;
- case PBVH_GRIDS:
- val = grids_neighbor_average_mask(ss, vd.index);
- break;
- }
-
- val -= *vd.mask;
-
- if (mode == MASK_FILTER_SMOOTH) {
- *vd.mask += val;
- }
- else if (mode == MASK_FILTER_SHARPEN) {
- if (*vd.mask > 0.5f) {
- *vd.mask += 0.05f;
- }
- else {
- *vd.mask -= 0.05f;
- }
- *vd.mask += val / 2;
- }
- break;
- }
- case MASK_FILTER_GROW:
- max = 0.0f;
- sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni)
- {
- float vmask_f = data->prev_mask[ni.index];
- if (vmask_f > max) {
- max = vmask_f;
- }
- }
- sculpt_vertex_neighbors_iter_end(ni);
- *vd.mask = max;
- break;
- case MASK_FILTER_SHRINK:
- min = 1.0f;
- sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni)
- {
- float vmask_f = data->prev_mask[ni.index];
- if (vmask_f < min) {
- min = vmask_f;
- }
- }
- sculpt_vertex_neighbors_iter_end(ni);
- *vd.mask = min;
- break;
- case MASK_FILTER_CONTRAST_INCREASE:
- case MASK_FILTER_CONTRAST_DECREASE:
- delta = contrast / 2.0f;
- gain = 1.0f - delta * 2.0f;
- if (contrast > 0) {
- gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON);
- offset = gain * (-delta);
- }
- else {
- delta *= -1;
- offset = gain * (delta);
- }
- *vd.mask = gain * (*vd.mask) + offset;
- break;
- }
- CLAMP(*vd.mask, 0.0f, 1.0f);
- if (*vd.mask != prev_val) {
- update = true;
- }
- if (vd.mvert) {
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
-
- if (update) {
- BKE_pbvh_node_mark_update_mask(node);
- }
-}
-
-static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
-{
- ARegion *ar = CTX_wm_region(C);
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- PBVH *pbvh = ob->sculpt->pbvh;
- PBVHNode **nodes;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- int totnode;
- int filter_type = RNA_enum_get(op->ptr, "filter_type");
-
- BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
-
- sculpt_vertex_random_access_init(ss);
-
- if (!ob->sculpt->pmap) {
- return OPERATOR_CANCELLED;
- }
-
- int num_verts = sculpt_vertex_count_get(ss);
-
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
- sculpt_undo_push_begin("Mask filter");
-
- for (int i = 0; i < totnode; i++) {
- sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
- }
-
- float *prev_mask = NULL;
- int iterations = RNA_int_get(op->ptr, "iterations");
-
- /* Auto iteration count calculates the number of iteration based on the vertices of the mesh to
- * avoid adding an unnecessary amount of undo steps when using the operator from a shortcut.
- * One iteration per 50000 vertices in the mesh should be fine in most cases.
- * Maybe we want this to be configurable. */
- if (RNA_boolean_get(op->ptr, "auto_iteration_count")) {
- iterations = (int)(num_verts / 50000.0f) + 1;
- }
-
- for (int i = 0; i < iterations; i++) {
- if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) {
- prev_mask = MEM_mallocN(num_verts * sizeof(float), "prevmask");
- for (int j = 0; j < num_verts; j++) {
- prev_mask[j] = sculpt_vertex_mask_get(ss, j);
- }
- }
-
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = nodes,
- .filter_type = filter_type,
- .prev_mask = prev_mask,
- };
-
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings);
-
- if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) {
- MEM_freeN(prev_mask);
- }
- }
-
- MEM_SAFE_FREE(nodes);
-
- sculpt_undo_push_end();
-
- ED_region_tag_redraw(ar);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
-}
-
-static void SCULPT_OT_mask_filter(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Mask Filter";
- ot->idname = "SCULPT_OT_mask_filter";
- ot->description = "Applies a filter to modify the current mask";
-
- /* api callbacks */
- ot->exec = sculpt_mask_filter_exec;
- ot->poll = sculpt_mode_poll;
-
- ot->flag = OPTYPE_REGISTER;
-
- /* rna */
- RNA_def_enum(ot->srna,
- "filter_type",
- prop_mask_filter_types,
- MASK_FILTER_SMOOTH,
- "Type",
- "Filter that is going to be applied to the mask");
- RNA_def_int(ot->srna,
- "iterations",
- 1,
- 1,
- 100,
- "Iterations",
- "Number of times that the filter is going to be applied",
- 1,
- 100);
- RNA_def_boolean(
- ot->srna,
- "auto_iteration_count",
- false,
- "Auto Iteration Count",
- "Use a automatic number of iterations based on the number of vertices of the sculpt");
-}
-
-static float neighbor_dirty_mask(SculptSession *ss, PBVHVertexIter *vd)
-{
- int total = 0;
- float avg[3];
- zero_v3(avg);
-
- SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, vd->index, ni)
- {
- float normalized[3];
- sub_v3_v3v3(normalized, sculpt_vertex_co_get(ss, ni.index), vd->co);
- normalize_v3(normalized);
- add_v3_v3(avg, normalized);
- total++;
- }
- sculpt_vertex_neighbors_iter_end(ni);
-
- if (total > 0) {
- mul_v3_fl(avg, 1.0f / total);
- float normal[3];
- if (vd->no) {
- normal_short_to_float_v3(normal, vd->no);
- }
- else {
- copy_v3_v3(normal, vd->fno);
- }
- float dot = dot_v3v3(avg, normal);
- float angle = max_ff(saacosf(dot), 0.0f);
- return angle;
- }
- return 0;
-}
-
-typedef struct DirtyMaskRangeData {
- float min, max;
-} DirtyMaskRangeData;
-
-static void dirty_mask_compute_range_task_cb(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- PBVHNode *node = data->nodes[i];
- DirtyMaskRangeData *range = tls->userdata_chunk;
- PBVHVertexIter vd;
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
- {
- float dirty_mask = neighbor_dirty_mask(ss, &vd);
- range->min = min_ff(dirty_mask, range->min);
- range->max = max_ff(dirty_mask, range->max);
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static void dirty_mask_compute_range_reduce(const void *__restrict UNUSED(userdata),
- void *__restrict chunk_join,
- void *__restrict chunk)
-{
- DirtyMaskRangeData *join = chunk_join;
- DirtyMaskRangeData *range = chunk;
- join->min = min_ff(range->min, join->min);
- join->max = max_ff(range->max, join->max);
-}
-
-static void dirty_mask_apply_task_cb(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- PBVHNode *node = data->nodes[i];
- PBVHVertexIter vd;
-
- const bool dirty_only = data->dirty_mask_dirty_only;
- const float min = data->dirty_mask_min;
- const float max = data->dirty_mask_max;
-
- float range = max - min;
- if (range < 0.0001f) {
- range = 0;
- }
- else {
- range = 1.0f / range;
- }
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
- {
- float dirty_mask = neighbor_dirty_mask(ss, &vd);
- float mask = *vd.mask + (1 - ((dirty_mask - min) * range));
- if (dirty_only) {
- mask = fminf(mask, 0.5f) * 2.0f;
- }
- *vd.mask = CLAMPIS(mask, 0.0f, 1.0f);
-
- if (vd.mvert) {
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
- BKE_pbvh_node_mark_update_mask(node);
-}
-
-static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
-{
- ARegion *ar = CTX_wm_region(C);
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- PBVH *pbvh = ob->sculpt->pbvh;
- PBVHNode **nodes;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- int totnode;
-
- BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
-
- sculpt_vertex_random_access_init(ss);
-
- if (!ob->sculpt->pmap) {
- return OPERATOR_CANCELLED;
- }
-
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
- sculpt_undo_push_begin("Dirty Mask");
-
- for (int i = 0; i < totnode; i++) {
- sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
- }
-
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = nodes,
- .dirty_mask_dirty_only = RNA_boolean_get(op->ptr, "dirty_only"),
- };
- DirtyMaskRangeData range = {
- .min = FLT_MAX,
- .max = -FLT_MAX,
- };
-
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
-
- settings.func_reduce = dirty_mask_compute_range_reduce;
- settings.userdata_chunk = &range;
- settings.userdata_chunk_size = sizeof(DirtyMaskRangeData);
-
- BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings);
- data.dirty_mask_min = range.min;
- data.dirty_mask_max = range.max;
- BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings);
-
- MEM_SAFE_FREE(nodes);
-
- BKE_pbvh_update_vertex_data(pbvh, SCULPT_UPDATE_MASK);
-
- sculpt_undo_push_end();
-
- ED_region_tag_redraw(ar);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
-}
-
-static void SCULPT_OT_dirty_mask(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Dirty Mask";
- ot->idname = "SCULPT_OT_dirty_mask";
- ot->description = "Generates a mask based on the geometry cavity and pointiness";
-
- /* api callbacks */
- ot->exec = sculpt_dirty_mask_exec;
- ot->poll = sculpt_mode_poll;
-
- ot->flag = OPTYPE_REGISTER;
-
- /* rna */
- RNA_def_boolean(
- ot->srna, "dirty_only", false, "Dirty Only", "Don't calculate cleans for convex areas");
-}
-
-static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op)
-{
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
-
- MEM_freeN(op->customdata);
-
- for (int n = 0; n < ss->filter_cache->totnode; n++) {
- PBVHNode *node = ss->filter_cache->nodes[n];
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
- {
- *vd.mask = ss->filter_cache->prev_mask[vd.index];
- }
- BKE_pbvh_vertex_iter_end;
-
- BKE_pbvh_node_mark_redraw(node);
- }
-
- sculpt_flush_update_step(C, SCULPT_UPDATE_MASK);
- sculpt_filter_cache_free(ss);
- sculpt_undo_push_end();
- sculpt_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
- ED_workspace_status_text(C, NULL);
-}
-
-static void sculpt_expand_task_cb(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- PBVHNode *node = data->nodes[i];
- PBVHVertexIter vd;
- int update_it = data->mask_expand_update_it;
-
- BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
- {
- int vi = vd.index;
- float final_mask = *vd.mask;
- if (data->mask_expand_use_normals) {
- if (ss->filter_cache->normal_factor[sculpt_active_vertex_get(ss)] <
- ss->filter_cache->normal_factor[vd.index]) {
- final_mask = 1.0f;
- }
- else {
- final_mask = 0.0f;
- }
- }
- else {
- if (ss->filter_cache->mask_update_it[vi] <= update_it &&
- ss->filter_cache->mask_update_it[vi] != 0) {
- final_mask = 1.0f;
- }
- else {
- final_mask = 0.0f;
- }
- }
-
- if (data->mask_expand_keep_prev_mask) {
- final_mask = MAX2(ss->filter_cache->prev_mask[vd.index], final_mask);
- }
-
- if (data->mask_expand_invert_mask) {
- final_mask = 1.0f - final_mask;
- }
-
- if (*vd.mask != final_mask) {
- if (vd.mvert) {
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- *vd.mask = final_mask;
- BKE_pbvh_node_mark_update_mask(node);
- }
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- float prevclick_f[2];
- copy_v2_v2(prevclick_f, op->customdata);
- int prevclick[2] = {(int)prevclick_f[0], (int)prevclick_f[1]};
- int len = (int)len_v2v2_int(prevclick, event->mval);
- len = ABS(len);
- int mask_speed = RNA_int_get(op->ptr, "mask_speed");
- int mask_expand_update_it = len / mask_speed;
- mask_expand_update_it = mask_expand_update_it + 1;
-
- if (RNA_boolean_get(op->ptr, "use_cursor")) {
- SculptCursorGeometryInfo sgi;
- float mouse[2];
- mouse[0] = event->mval[0];
- mouse[1] = event->mval[1];
- sculpt_cursor_geometry_info_update(C, &sgi, mouse, false);
- mask_expand_update_it = ss->filter_cache->mask_update_it[(int)sculpt_active_vertex_get(ss)];
- }
-
- if ((event->type == ESCKEY && event->val == KM_PRESS) ||
- (event->type == RIGHTMOUSE && event->val == KM_PRESS)) {
- /* Returning OPERATOR_CANCELLED will leak memory due to not finishing
- * undo. Better solution could be to make paint_mesh_restore_co work
- * for this case. */
- sculpt_mask_expand_cancel(C, op);
- return OPERATOR_FINISHED;
- }
-
- if ((event->type == LEFTMOUSE && event->val == KM_RELEASE) ||
- (event->type == RETKEY && event->val == KM_PRESS) ||
- (event->type == PADENTER && event->val == KM_PRESS)) {
-
- /* Smooth iterations */
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = ss->filter_cache->nodes,
- .filter_type = MASK_FILTER_SMOOTH,
- };
-
- int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations");
- BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false);
- for (int i = 0; i < smooth_iterations; i++) {
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(
- &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mask_filter_task_cb, &settings);
- }
-
- /* Pivot position */
- if (RNA_boolean_get(op->ptr, "update_pivot")) {
- const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- const float threshold = 0.2f;
- float avg[3];
- int total = 0;
- zero_v3(avg);
-
- for (int n = 0; n < ss->filter_cache->totnode; n++) {
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, ss->filter_cache->nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- const float mask = (vd.mask) ? *vd.mask : 0.0f;
- if (mask < (0.5f + threshold) && mask > (0.5f - threshold)) {
- if (check_vertex_pivot_symmetry(
- vd.co, ss->filter_cache->mask_expand_initial_co, symm)) {
- add_v3_v3(avg, vd.co);
- total++;
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
-
- if (total > 0) {
- mul_v3_fl(avg, 1.0f / total);
- copy_v3_v3(ss->pivot_pos, avg);
- }
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
- }
-
- MEM_freeN(op->customdata);
-
- for (int i = 0; i < ss->filter_cache->totnode; i++) {
- BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]);
- }
-
- sculpt_filter_cache_free(ss);
-
- sculpt_undo_push_end();
- sculpt_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
- ED_workspace_status_text(C, NULL);
- return OPERATOR_FINISHED;
- }
-
- if (event->type != MOUSEMOVE) {
- return OPERATOR_RUNNING_MODAL;
- }
-
- if (mask_expand_update_it == ss->filter_cache->mask_update_current_it) {
- return OPERATOR_RUNNING_MODAL;
- }
-
- if (mask_expand_update_it < ss->filter_cache->mask_update_last_it) {
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = ss->filter_cache->nodes,
- .mask_expand_update_it = mask_expand_update_it,
- .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"),
- .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
- .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
- };
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(
- &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
- ss->filter_cache->mask_update_current_it = mask_expand_update_it;
- }
-
- sculpt_flush_update_step(C, SCULPT_UPDATE_MASK);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-typedef struct MaskExpandFloodFillData {
- float original_normal[3];
- float edge_sensitivity;
- bool use_normals;
-} MaskExpandFloodFillData;
-
-static bool mask_expand_floodfill_cb(
- SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
-{
- MaskExpandFloodFillData *data = userdata;
-
- if (!is_duplicate) {
- int to_it = ss->filter_cache->mask_update_it[from_v] + 1;
- ss->filter_cache->mask_update_it[to_v] = to_it;
- if (to_it > ss->filter_cache->mask_update_last_it) {
- ss->filter_cache->mask_update_last_it = to_it;
- }
-
- if (data->use_normals) {
- float current_normal[3], prev_normal[3];
- sculpt_vertex_normal_get(ss, to_v, current_normal);
- sculpt_vertex_normal_get(ss, from_v, prev_normal);
- const float from_edge_factor = ss->filter_cache->edge_factor[from_v];
- ss->filter_cache->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) *
- from_edge_factor;
- ss->filter_cache->normal_factor[to_v] = dot_v3v3(data->original_normal, current_normal) *
- powf(from_edge_factor, data->edge_sensitivity);
- CLAMP(ss->filter_cache->normal_factor[to_v], 0.0f, 1.0f);
- }
- }
- else {
- /* PBVH_GRIDS duplicate handling */
- ss->filter_cache->mask_update_it[to_v] = ss->filter_cache->mask_update_it[from_v];
- if (data->use_normals) {
- ss->filter_cache->edge_factor[to_v] = ss->filter_cache->edge_factor[from_v];
- ss->filter_cache->normal_factor[to_v] = ss->filter_cache->normal_factor[from_v];
- }
- }
-
- return true;
-}
-
-static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- PBVH *pbvh = ob->sculpt->pbvh;
-
- bool use_normals = RNA_boolean_get(op->ptr, "use_normals");
-
- SculptCursorGeometryInfo sgi;
- float mouse[2];
- mouse[0] = event->mval[0];
- mouse[1] = event->mval[1];
-
- sculpt_vertex_random_access_init(ss);
-
- op->customdata = MEM_mallocN(2 * sizeof(float), "initial mouse position");
- copy_v2_v2(op->customdata, mouse);
-
- sculpt_cursor_geometry_info_update(C, &sgi, mouse, false);
-
- BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
-
- int vertex_count = sculpt_vertex_count_get(ss);
-
- ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
-
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &ss->filter_cache->nodes, &ss->filter_cache->totnode);
-
- sculpt_undo_push_begin("Mask Expand");
-
- for (int i = 0; i < ss->filter_cache->totnode; i++) {
- sculpt_undo_push_node(ob, ss->filter_cache->nodes[i], SCULPT_UNDO_MASK);
- BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]);
- }
-
- ss->filter_cache->mask_update_it = MEM_callocN(sizeof(int) * vertex_count,
- "mask update iteration");
- if (use_normals) {
- ss->filter_cache->normal_factor = MEM_callocN(sizeof(float) * vertex_count,
- "mask update normal factor");
- ss->filter_cache->edge_factor = MEM_callocN(sizeof(float) * vertex_count,
- "mask update normal factor");
- for (int i = 0; i < vertex_count; i++) {
- ss->filter_cache->edge_factor[i] = 1.0f;
- }
- }
-
- ss->filter_cache->prev_mask = MEM_callocN(sizeof(float) * vertex_count, "prev mask");
- for (int i = 0; i < vertex_count; i++) {
- ss->filter_cache->prev_mask[i] = sculpt_vertex_mask_get(ss, i);
- }
-
- ss->filter_cache->mask_update_last_it = 1;
- ss->filter_cache->mask_update_current_it = 1;
- ss->filter_cache->mask_update_it[sculpt_active_vertex_get(ss)] = 1;
-
- copy_v3_v3(ss->filter_cache->mask_expand_initial_co, sculpt_active_vertex_co_get(ss));
-
- SculptFloodFill flood;
- sculpt_floodfill_init(ss, &flood);
- sculpt_floodfill_add_active(sd, ob, ss, &flood, FLT_MAX);
-
- MaskExpandFloodFillData fdata = {
- .use_normals = use_normals,
- .edge_sensitivity = RNA_int_get(op->ptr, "edge_sensitivity"),
- };
- sculpt_active_vertex_normal_get(ss, fdata.original_normal);
- sculpt_floodfill_execute(ss, &flood, mask_expand_floodfill_cb, &fdata);
- sculpt_floodfill_free(&flood);
-
- if (use_normals) {
- for (int repeat = 0; repeat < 2; repeat++) {
- for (int i = 0; i < vertex_count; i++) {
- float avg = 0;
- SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, i, ni)
- {
- avg += ss->filter_cache->normal_factor[ni.index];
- }
- sculpt_vertex_neighbors_iter_end(ni);
- ss->filter_cache->normal_factor[i] = avg / ni.size;
- }
- }
-
- MEM_SAFE_FREE(ss->filter_cache->edge_factor);
- }
-
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = ss->filter_cache->nodes,
- .mask_expand_update_it = 0,
- .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"),
- .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
- .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
- };
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(
- &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
-
- const char *status_str = TIP_(
- "Move the mouse to expand the mask from the active vertex. LBM: confirm mask, ESC/RMB: "
- "cancel");
- ED_workspace_status_text(C, status_str);
-
- sculpt_flush_update_step(C, SCULPT_UPDATE_MASK);
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void SCULPT_OT_mask_expand(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Mask Expand";
- ot->idname = "SCULPT_OT_mask_expand";
- ot->description = "Expands a mask from the initial active vertex under the cursor";
-
- /* api callbacks */
- ot->invoke = sculpt_mask_expand_invoke;
- ot->modal = sculpt_mask_expand_modal;
- ot->cancel = sculpt_mask_expand_cancel;
- ot->poll = sculpt_mode_poll;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_boolean(ot->srna, "invert", true, "Invert", "Invert the new mask");
- ot->prop = RNA_def_boolean(
- ot->srna, "use_cursor", true, "Use Cursor", "Expand the mask to the cursor position");
- ot->prop = RNA_def_boolean(ot->srna,
- "update_pivot",
- true,
- "Update Pivot Position",
- "Set the pivot position to the mask border after creating the mask");
- ot->prop = RNA_def_int(ot->srna, "smooth_iterations", 2, 0, 10, "Smooth iterations", "", 0, 10);
- ot->prop = RNA_def_int(ot->srna, "mask_speed", 5, 1, 10, "Mask speed", "", 1, 10);
-
- ot->prop = RNA_def_boolean(ot->srna,
- "use_normals",
- true,
- "Use Normals",
- "Generate the mask using the normals and curvature of the model");
- ot->prop = RNA_def_boolean(ot->srna,
- "keep_previous_mask",
- false,
- "Keep Previous Mask",
- "Generate the new mask on top of the current one");
- ot->prop = RNA_def_int(ot->srna,
- "edge_sensitivity",
- 300,
- 0,
- 2000,
- "Edge Detection Sensitivity",
- "Sensitivity for expanding the mask across sculpted sharp edges when "
- "using normals to generate the mask",
- 0,
- 2000);
-}
-
-void sculpt_geometry_preview_lines_update(bContext *C, SculptSession *ss, float radius)
+void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float radius)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Object *ob = CTX_data_active_object(C);
@@ -10237,7 +7789,7 @@ void sculpt_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
ss->preview_vert_index_count = 0;
int totpoints = 0;
- /* This function is called from the cursor drawing code, so the PBVH may not be build yet */
+ /* This function is called from the cursor drawing code, so the PBVH may not be build yet. */
if (!ss->pbvh) {
return;
}
@@ -10249,28 +7801,27 @@ void sculpt_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
}
float brush_co[3];
- copy_v3_v3(brush_co, sculpt_active_vertex_co_get(ss));
+ copy_v3_v3(brush_co, SCULPT_active_vertex_co_get(ss));
- char *visited_vertices = MEM_callocN(sculpt_vertex_count_get(ss) * sizeof(char),
+ char *visited_vertices = MEM_callocN(SCULPT_vertex_count_get(ss) * sizeof(char),
"visited vertices");
- /* Assuming an average of 6 edges per vertex in a triangulated mesh */
- const int max_preview_vertices = sculpt_vertex_count_get(ss) * 3 * 2;
+ /* Assuming an average of 6 edges per vertex in a triangulated mesh. */
+ const int max_preview_vertices = SCULPT_vertex_count_get(ss) * 3 * 2;
if (ss->preview_vert_index_list == NULL) {
ss->preview_vert_index_list = MEM_callocN(max_preview_vertices * sizeof(int), "preview lines");
}
GSQueue *not_visited_vertices = BLI_gsqueue_new(sizeof(int));
- int active_v = sculpt_active_vertex_get(ss);
+ int active_v = SCULPT_active_vertex_get(ss);
BLI_gsqueue_push(not_visited_vertices, &active_v);
while (!BLI_gsqueue_is_empty(not_visited_vertices)) {
int from_v;
BLI_gsqueue_pop(not_visited_vertices, &from_v);
SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, from_v, ni)
- {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) {
if (totpoints + (ni.size * 2) < max_preview_vertices) {
int to_v = ni.index;
ss->preview_vert_index_list[totpoints] = from_v;
@@ -10279,14 +7830,14 @@ void sculpt_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
totpoints++;
if (visited_vertices[to_v] == 0) {
visited_vertices[to_v] = 1;
- const float *co = sculpt_vertex_co_get(ss, to_v);
+ const float *co = SCULPT_vertex_co_get(ss, to_v);
if (len_squared_v3v3(brush_co, co) < radius * radius) {
BLI_gsqueue_push(not_visited_vertices, &to_v);
}
}
}
}
- sculpt_vertex_neighbors_iter_end(ni);
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
}
BLI_gsqueue_free(not_visited_vertices);
@@ -10295,294 +7846,6 @@ void sculpt_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
ss->preview_vert_index_count = totpoints;
}
-void ED_sculpt_init_transform(struct bContext *C)
-{
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
-
- copy_v3_v3(ss->init_pivot_pos, ss->pivot_pos);
- copy_v4_v4(ss->init_pivot_rot, ss->pivot_rot);
-
- sculpt_undo_push_begin("Transform");
- BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false);
-
- ss->pivot_rot[3] = 1.0f;
-
- sculpt_vertex_random_access_init(ss);
- sculpt_filter_cache_init(ob, sd);
-}
-
-static void sculpt_transform_task_cb(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
-
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- PBVHNode *node = data->nodes[i];
-
- SculptOrigVertData orig_data;
- sculpt_orig_vert_data_init(&orig_data, data->ob, data->nodes[i]);
-
- PBVHVertexIter vd;
-
- sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
- BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
- {
- sculpt_orig_vert_data_update(&orig_data, &vd);
- float transformed_co[3], orig_co[3], disp[3];
- float fade = vd.mask ? *vd.mask : 0.0f;
- copy_v3_v3(orig_co, orig_data.co);
- char symm_area = sculpt_get_vertex_symm_area(orig_co);
-
- copy_v3_v3(transformed_co, orig_co);
- mul_m4_v3(data->transform_mats[(int)symm_area], transformed_co);
- sub_v3_v3v3(disp, transformed_co, orig_co);
- mul_v3_fl(disp, 1.0f - fade);
-
- add_v3_v3v3(vd.co, orig_co, disp);
-
- if (vd.mvert) {
- vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
- }
- }
- BKE_pbvh_vertex_iter_end;
-
- BKE_pbvh_node_mark_update(node);
-}
-
-void ED_sculpt_update_modal_transform(struct bContext *C)
-{
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
-
- sculpt_vertex_random_access_init(ss);
- BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false);
-
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = ss->filter_cache->nodes,
- };
-
- float final_pivot_pos[3], d_t[3], d_r[4];
- float t_mat[4][4], r_mat[4][4], s_mat[4][4], pivot_mat[4][4], pivot_imat[4][4],
- transform_mat[4][4];
-
- copy_v3_v3(final_pivot_pos, ss->pivot_pos);
- for (int i = 0; i < PAINT_SYMM_AREAS; i++) {
- ePaintSymmetryAreas v_symm = i;
-
- copy_v3_v3(final_pivot_pos, ss->pivot_pos);
-
- unit_m4(pivot_mat);
-
- unit_m4(t_mat);
- unit_m4(r_mat);
- unit_m4(s_mat);
-
- /* Translation matrix */
- sub_v3_v3v3(d_t, ss->pivot_pos, ss->init_pivot_pos);
- sculpt_flip_v3_by_symm_area(d_t, symm, v_symm, ss->init_pivot_pos);
- translate_m4(t_mat, d_t[0], d_t[1], d_t[2]);
-
- /* Rotation matrix */
- sub_qt_qtqt(d_r, ss->pivot_rot, ss->init_pivot_rot);
- normalize_qt(d_r);
- sculpt_flip_quat_by_symm_area(d_r, symm, v_symm, ss->init_pivot_pos);
- quat_to_mat4(r_mat, d_r);
-
- /* Scale matrix */
- size_to_mat4(s_mat, ss->pivot_scale);
-
- /* Pivot matrix */
- sculpt_flip_v3_by_symm_area(final_pivot_pos, symm, v_symm, ss->init_pivot_pos);
- translate_m4(pivot_mat, final_pivot_pos[0], final_pivot_pos[1], final_pivot_pos[2]);
- invert_m4_m4(pivot_imat, pivot_mat);
-
- /* Final transform matrix */
- mul_m4_m4m4(transform_mat, r_mat, t_mat);
- mul_m4_m4m4(transform_mat, transform_mat, s_mat);
- mul_m4_m4m4(data.transform_mats[i], transform_mat, pivot_imat);
- mul_m4_m4m4(data.transform_mats[i], pivot_mat, data.transform_mats[i]);
- }
-
- PBVHParallelSettings settings;
- BKE_pbvh_parallel_range_settings(
- &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BKE_pbvh_parallel_range(
- 0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings);
-
- if (ss->deform_modifiers_active || ss->shapekey_active) {
- sculpt_flush_stroke_deform(sd, ob, true);
- }
-
- sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS);
-}
-
-void ED_sculpt_end_transform(struct bContext *C)
-{
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- if (ss->filter_cache) {
- sculpt_filter_cache_free(ss);
- }
- sculpt_undo_push_end();
- sculpt_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
-}
-
-typedef enum eSculptPivotPositionModes {
- SCULPT_PIVOT_POSITION_ORIGIN = 0,
- SCULPT_PIVOT_POSITION_UNMASKED = 1,
- SCULPT_PIVOT_POSITION_MASK_BORDER = 2,
- SCULPT_PIVOT_POSITION_ACTIVE_VERTEX = 3,
- SCULPT_PIVOT_POSITION_CURSOR_SURFACE = 4,
-} eSculptPivotPositionModes;
-
-static EnumPropertyItem prop_sculpt_pivot_position_types[] = {
- {SCULPT_PIVOT_POSITION_ORIGIN,
- "ORIGIN",
- 0,
- "Origin",
- "Sets the pivot to the origin of the sculpt"},
- {SCULPT_PIVOT_POSITION_UNMASKED,
- "UNMASKED",
- 0,
- "Unmasked",
- "Sets the pivot position to the average position of the unmasked vertices"},
- {SCULPT_PIVOT_POSITION_MASK_BORDER,
- "BORDER",
- 0,
- "Mask border",
- "Sets the pivot position to the center of the border of the mask"},
- {SCULPT_PIVOT_POSITION_ACTIVE_VERTEX,
- "ACTIVE",
- 0,
- "Active vertex",
- "Sets the pivot position to the active vertex position"},
- {SCULPT_PIVOT_POSITION_CURSOR_SURFACE,
- "SURFACE",
- 0,
- "Surface",
- "Sets the pivot position to the surface under the cursor"},
- {0, NULL, 0, NULL, NULL},
-};
-
-static int sculpt_set_pivot_position_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- ARegion *ar = CTX_wm_region(C);
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
-
- int mode = RNA_enum_get(op->ptr, "mode");
-
- BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true);
-
- /* Pivot to center */
- if (mode == SCULPT_PIVOT_POSITION_ORIGIN) {
- zero_v3(ss->pivot_pos);
- }
- /* Pivot to active vertex */
- else if (mode == SCULPT_PIVOT_POSITION_ACTIVE_VERTEX) {
- copy_v3_v3(ss->pivot_pos, sculpt_active_vertex_co_get(ss));
- }
- /* Pivot to raycast surface */
- else if (mode == SCULPT_PIVOT_POSITION_CURSOR_SURFACE) {
- float stroke_location[3];
- float mouse[2];
- mouse[0] = event->mval[0];
- mouse[1] = event->mval[1];
- if (sculpt_stroke_get_location(C, stroke_location, mouse)) {
- copy_v3_v3(ss->pivot_pos, stroke_location);
- }
- }
- else {
- PBVHNode **nodes;
- int totnode;
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
-
- float avg[3];
- int total = 0;
- zero_v3(avg);
-
- /* Pivot to unmasked */
- if (mode == SCULPT_PIVOT_POSITION_UNMASKED) {
- for (int n = 0; n < totnode; n++) {
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- const float mask = (vd.mask) ? *vd.mask : 0.0f;
- if (mask < 1.0f) {
- if (check_vertex_pivot_symmetry(vd.co, ss->pivot_pos, symm)) {
- add_v3_v3(avg, vd.co);
- total++;
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
- }
- /* Pivot to mask border */
- else if (mode == SCULPT_PIVOT_POSITION_MASK_BORDER) {
- const float threshold = 0.2f;
-
- for (int n = 0; n < totnode; n++) {
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
- {
- const float mask = (vd.mask) ? *vd.mask : 0.0f;
- if (mask < (0.5f + threshold) && mask > (0.5f - threshold)) {
- if (check_vertex_pivot_symmetry(vd.co, ss->pivot_pos, symm)) {
- add_v3_v3(avg, vd.co);
- total++;
- }
- }
- }
- BKE_pbvh_vertex_iter_end;
- }
- }
-
- if (total > 0) {
- mul_v3_fl(avg, 1.0f / total);
- copy_v3_v3(ss->pivot_pos, avg);
- }
-
- MEM_SAFE_FREE(nodes);
- }
-
- ED_region_tag_redraw(ar);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
-
- return OPERATOR_FINISHED;
-}
-
-static void SCULPT_OT_set_pivot_position(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Pivot Position";
- ot->idname = "SCULPT_OT_set_pivot_position";
- ot->description = "Sets the sculpt transform pivot position";
-
- /* api callbacks */
- ot->invoke = sculpt_set_pivot_position_invoke;
- ot->poll = sculpt_mode_poll;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna,
- "mode",
- prop_sculpt_pivot_position_types,
- SCULPT_PIVOT_POSITION_UNMASKED,
- "Mode",
- "");
-}
void ED_operatortypes_sculpt(void)
{
@@ -10600,4 +7863,8 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_dirty_mask);
WM_operatortype_append(SCULPT_OT_mask_expand);
WM_operatortype_append(SCULPT_OT_set_pivot_position);
+ WM_operatortype_append(SCULPT_OT_face_sets_create);
+ WM_operatortype_append(SCULPT_OT_face_sets_change_visibility);
+ WM_operatortype_append(SCULPT_OT_face_sets_randomize_colors);
+ WM_operatortype_append(SCULPT_OT_face_sets_init);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c
new file mode 100644
index 00000000000..f0f6478d3a6
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c
@@ -0,0 +1,304 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_hash.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+bool SCULPT_is_automasking_mode_enabled(const Sculpt *sd,
+ const Brush *br,
+ const eAutomasking_flag mode)
+{
+ return br->automasking_flags & mode || sd->automasking_flags & mode;
+}
+
+bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, const Brush *br)
+{
+ if (SCULPT_stroke_is_dynamic_topology(ss, br)) {
+ return false;
+ }
+ if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_TOPOLOGY)) {
+ return true;
+ }
+ if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_FACE_SETS)) {
+ return true;
+ }
+ if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
+ return true;
+ }
+ if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
+ return true;
+ }
+ return false;
+}
+
+float SCULPT_automasking_factor_get(SculptSession *ss, int vert)
+{
+ if (ss->cache->automask) {
+ return ss->cache->automask[vert];
+ }
+ else {
+ return 1.0f;
+ }
+}
+
+void SCULPT_automasking_end(Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ if (ss->cache && ss->cache->automask) {
+ MEM_freeN(ss->cache->automask);
+ }
+}
+
+static bool sculpt_automasking_is_constrained_by_radius(Brush *br)
+{
+ /* 2D falloff is not constrained by radius. */
+ if (br->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
+ return false;
+ }
+
+ if (ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE)) {
+ return true;
+ }
+ return false;
+}
+
+typedef struct AutomaskFloodFillData {
+ float *automask_factor;
+ float radius;
+ bool use_radius;
+ float location[3];
+ char symm;
+} AutomaskFloodFillData;
+
+static bool automask_floodfill_cb(
+ SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata)
+{
+ AutomaskFloodFillData *data = userdata;
+
+ data->automask_factor[to_v] = 1.0f;
+ return (!data->use_radius ||
+ SCULPT_is_vertex_inside_brush_radius_symm(
+ SCULPT_vertex_co_get(ss, to_v), data->location, data->radius, data->symm));
+}
+
+static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
+ return NULL;
+ }
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
+ BLI_assert(!"Topology masking: pmap missing");
+ return NULL;
+ }
+
+ const int totvert = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totvert; i++) {
+ ss->cache->automask[i] = 0.0f;
+ }
+
+ /* Flood fill automask to connected vertices. Limited to vertices inside
+ * the brush radius if the tool requires it. */
+ SculptFloodFill flood;
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_active(sd, ob, ss, &flood, ss->cache->radius);
+
+ AutomaskFloodFillData fdata = {
+ .automask_factor = automask_factor,
+ .radius = ss->cache->radius,
+ .use_radius = sculpt_automasking_is_constrained_by_radius(brush),
+ .symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL,
+ };
+ copy_v3_v3(fdata.location, SCULPT_active_vertex_co_get(ss));
+ SCULPT_floodfill_execute(ss, &flood, automask_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ return automask_factor;
+}
+
+static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
+ return NULL;
+ }
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
+ BLI_assert(!"Face Sets automasking: pmap missing");
+ return NULL;
+ }
+
+ int tot_vert = SCULPT_vertex_count_get(ss);
+ int active_face_set = SCULPT_active_face_set_get(ss);
+ for (int i = 0; i < tot_vert; i++) {
+ if (!SCULPT_vertex_has_face_set(ss, i, active_face_set)) {
+ automask_factor[i] *= 0.0f;
+ }
+ }
+
+ return automask_factor;
+}
+
+#define EDGE_DISTANCE_INF -1
+
+float *SCULPT_boundary_automasking_init(Object *ob,
+ eBoundaryAutomaskMode mode,
+ int propagation_steps,
+ float *automask_factor)
+{
+ SculptSession *ss = ob->sculpt;
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
+ BLI_assert(!"Boundary Edges masking: pmap missing");
+ return NULL;
+ }
+
+ const int totvert = SCULPT_vertex_count_get(ss);
+ int *edge_distance = MEM_callocN(sizeof(int) * totvert, "automask_factor");
+
+ for (int i = 0; i < totvert; i++) {
+ edge_distance[i] = EDGE_DISTANCE_INF;
+ switch (mode) {
+ case AUTOMASK_INIT_BOUNDARY_EDGES:
+ if (!SCULPT_vertex_is_boundary(ss, i)) {
+ edge_distance[i] = 0;
+ }
+ break;
+ case AUTOMASK_INIT_BOUNDARY_FACE_SETS:
+ if (!SCULPT_vertex_has_unique_face_set(ss, i)) {
+ edge_distance[i] = 0;
+ }
+ break;
+ }
+ }
+
+ for (int propagation_it = 0; propagation_it < propagation_steps; propagation_it++) {
+ for (int i = 0; i < totvert; i++) {
+ if (edge_distance[i] == EDGE_DISTANCE_INF) {
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+ if (edge_distance[ni.index] == propagation_it) {
+ edge_distance[i] = propagation_it + 1;
+ }
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ }
+ }
+ }
+
+ for (int i = 0; i < totvert; i++) {
+ if (edge_distance[i] != EDGE_DISTANCE_INF) {
+ const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps);
+ const float edge_boundary_automask = pow2f(p);
+ automask_factor[i] *= (1.0f - edge_boundary_automask);
+ }
+ }
+
+ MEM_SAFE_FREE(edge_distance);
+ return automask_factor;
+}
+
+void SCULPT_automasking_init(Sculpt *sd, Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ const int totvert = SCULPT_vertex_count_get(ss);
+
+ if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
+ return;
+ }
+
+ ss->cache->automask = MEM_callocN(sizeof(float) * SCULPT_vertex_count_get(ss),
+ "automask_factor");
+
+ for (int i = 0; i < totvert; i++) {
+ ss->cache->automask[i] = 1.0f;
+ }
+
+ if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) {
+ SCULPT_vertex_random_access_init(ss);
+ SCULPT_topology_automasking_init(sd, ob, ss->cache->automask);
+ }
+ if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) {
+ SCULPT_vertex_random_access_init(ss);
+ sculpt_face_sets_automasking_init(sd, ob, ss->cache->automask);
+ }
+
+ if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
+ SCULPT_vertex_random_access_init(ss);
+ SCULPT_boundary_automasking_init(ob,
+ AUTOMASK_INIT_BOUNDARY_EDGES,
+ brush->automasking_boundary_edges_propagation_steps,
+ ss->cache->automask);
+ }
+ if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
+ SCULPT_vertex_random_access_init(ss);
+ SCULPT_boundary_automasking_init(ob,
+ AUTOMASK_INIT_BOUNDARY_FACE_SETS,
+ brush->automasking_boundary_edges_propagation_steps,
+ ss->cache->automask);
+ }
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
new file mode 100644
index 00000000000..62a7f1925ab
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -0,0 +1,689 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_dial_2d.h"
+#include "BLI_ghash.h"
+#include "BLI_gsqueue.h"
+#include "BLI_hash.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_ccg.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_image.h"
+#include "BKE_kelvinlet.h"
+#include "BKE_key.h"
+#include "BKE_lib_id.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_mirror.h"
+#include "BKE_modifier.h"
+#include "BKE_multires.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pbvh.h"
+#include "BKE_pointcache.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_subdiv_ccg.h"
+#include "BKE_subsurf.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_view3d.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CLOTH_LENGTH_CONSTRAINTS_BLOCK 100000
+#define CLOTH_SIMULATION_ITERATIONS 5
+#define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024
+#define CLOTH_SIMULATION_TIME_STEP 0.01f
+
+static void cloth_brush_add_length_constraint(SculptSession *ss, const int v1, const int v2)
+{
+ SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
+ cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v1 = v1;
+ cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v2 = v2;
+ cloth_sim->length_constraints[cloth_sim->tot_length_constraints].length = len_v3v3(
+ SCULPT_vertex_co_get(ss, v1), SCULPT_vertex_co_get(ss, v2));
+
+ cloth_sim->tot_length_constraints++;
+
+ /* Reallocation if the array capacity is exceeded. */
+ if (cloth_sim->tot_length_constraints >= cloth_sim->capacity_length_constraints) {
+ cloth_sim->capacity_length_constraints += CLOTH_LENGTH_CONSTRAINTS_BLOCK;
+ cloth_sim->length_constraints = MEM_reallocN_id(cloth_sim->length_constraints,
+ cloth_sim->capacity_length_constraints *
+ sizeof(SculptClothLengthConstraint),
+ "length constraints");
+ }
+}
+
+static void do_cloth_brush_build_constraints_task_cb_ex(
+ void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+
+ PBVHVertexIter vd;
+ const float radius = ss->cache->initial_radius;
+ const float limit = radius + (radius * data->brush->cloth_sim_limit);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (len_squared_v3v3(vd.co, ss->cache->initial_location) < limit * limit) {
+
+ SculptVertexNeighborIter ni;
+ int build_indices[CLOTH_MAX_CONSTRAINTS_PER_VERTEX];
+ int tot_indices = 0;
+ build_indices[tot_indices] = vd.index;
+ tot_indices++;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ build_indices[tot_indices] = ni.index;
+ tot_indices++;
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ /* As we don't know the order of the neighbor vertices, we create all possible combinations
+ * between the neighbor and the original vertex as length constraints. */
+ /* This results on a pattern that contains structural, shear and bending constraints for all
+ * vertices, but constraints are repeated taking more memory than necessary. */
+
+ for (int c_i = 0; c_i < tot_indices; c_i++) {
+ for (int c_j = 0; c_j < tot_indices; c_j++) {
+ if (c_i != c_j) {
+ cloth_brush_add_length_constraint(ss, build_indices[c_i], build_indices[c_j]);
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static float cloth_brush_simulation_falloff_get(const Brush *brush,
+ const float radius,
+ const float location[3],
+ const float co[3])
+{
+ const float distance = len_v3v3(location, co);
+ const float limit = radius + (radius * brush->cloth_sim_limit);
+ const float falloff = radius + (radius * brush->cloth_sim_limit * brush->cloth_sim_falloff);
+
+ if (distance > limit) {
+ /* Outiside the limits. */
+ return 0.0f;
+ }
+ else if (distance < falloff) {
+ /* Before the falloff area. */
+ return 1.0f;
+ }
+ else {
+ /* Do a smoothstep transition inside the falloff area. */
+ float p = 1.0f - ((distance - falloff) / (limit - falloff));
+ return 3.0f * p * p - 2.0f * p * p * p;
+ }
+}
+
+static void cloth_brush_apply_force_to_vertex(SculptSession *ss,
+ const float force[3],
+ const int vertex_index)
+{
+ SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
+ madd_v3_v3fl(cloth_sim->acceleration[vertex_index], force, 1.0f / cloth_sim->mass);
+}
+
+static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
+ const float *offset = data->offset;
+ const float *grab_delta = data->grab_delta;
+ float(*imat)[4] = data->mat;
+
+ const bool use_falloff_plane = brush->cloth_force_falloff_type ==
+ BRUSH_CLOTH_FORCE_FALLOFF_PLANE;
+
+ PBVHVertexIter vd;
+ const float bstrength = ss->cache->bstrength;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ /* For Pich Perpendicular Deform Type. */
+ float x_object_space[3];
+ float z_object_space[3];
+ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR) {
+ normalize_v3_v3(x_object_space, imat[0]);
+ normalize_v3_v3(z_object_space, imat[2]);
+ }
+
+ /* For Plane Force Falloff. */
+ float deform_plane[4];
+ float plane_normal[3];
+ if (use_falloff_plane) {
+ normalize_v3_v3(plane_normal, grab_delta);
+ plane_from_point_normal_v3(deform_plane, data->area_co, plane_normal);
+ }
+
+ /* Gravity */
+ float gravity[3] = {0.0f};
+ if (ss->cache->supports_gravity) {
+ madd_v3_v3fl(
+ gravity, ss->cache->gravity_direction, -ss->cache->radius * data->sd->gravity_factor);
+ }
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ float force[3];
+ const float sim_factor = cloth_brush_simulation_falloff_get(
+ brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[vd.index]);
+
+ /* When using the plane falloff mode the falloff is not constrained by the brush radius. */
+ if (sculpt_brush_test_sq_fn(&test, vd.co) || use_falloff_plane) {
+
+ float dist = sqrtf(test.dist);
+
+ if (use_falloff_plane) {
+ dist = dist_to_plane_v3(vd.co, deform_plane);
+ }
+
+ const float fade = sim_factor * bstrength *
+ SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ dist,
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ float brush_disp[3];
+ float normal[3];
+
+ if (vd.no) {
+ normal_short_to_float_v3(normal, vd.no);
+ }
+ else {
+ copy_v3_v3(normal, vd.fno);
+ }
+
+ switch (brush->cloth_deform_type) {
+ case BRUSH_CLOTH_DEFORM_DRAG:
+ sub_v3_v3v3(brush_disp, ss->cache->location, ss->cache->last_location);
+ normalize_v3(brush_disp);
+ mul_v3_v3fl(force, brush_disp, fade);
+ break;
+ case BRUSH_CLOTH_DEFORM_PUSH:
+ /* Invert the fade to push inwards. */
+ mul_v3_v3fl(force, offset, -fade);
+ break;
+ case BRUSH_CLOTH_DEFORM_GRAB:
+ mul_v3_v3fl(force, grab_delta, fade);
+ break;
+ case BRUSH_CLOTH_DEFORM_PINCH_POINT:
+ if (use_falloff_plane) {
+ float distance = dist_signed_to_plane_v3(vd.co, deform_plane);
+ copy_v3_v3(brush_disp, plane_normal);
+ mul_v3_fl(brush_disp, -distance);
+ }
+ else {
+ sub_v3_v3v3(brush_disp, ss->cache->location, vd.co);
+ }
+ normalize_v3(brush_disp);
+ mul_v3_v3fl(force, brush_disp, fade);
+ break;
+ case BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR: {
+ float disp_center[3];
+ float x_disp[3];
+ float z_disp[3];
+ sub_v3_v3v3(disp_center, ss->cache->location, vd.co);
+ normalize_v3(disp_center);
+ mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space));
+ mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space));
+ add_v3_v3v3(disp_center, x_disp, z_disp);
+ mul_v3_v3fl(force, disp_center, fade);
+ } break;
+ case BRUSH_CLOTH_DEFORM_INFLATE:
+ mul_v3_v3fl(force, normal, fade);
+ break;
+ case BRUSH_CLOTH_DEFORM_EXPAND:
+ cloth_sim->length_constraint_tweak[vd.index] += fade * 0.1f;
+ zero_v3(force);
+ break;
+ }
+
+ madd_v3_v3fl(force, gravity, fade);
+
+ cloth_brush_apply_force_to_vertex(ss, force, vd.index);
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, Brush *brush)
+{
+ const int totverts = SCULPT_vertex_count_get(ss);
+ SculptClothSimulation *cloth_sim;
+
+ cloth_sim = MEM_callocN(sizeof(SculptClothSimulation), "cloth constraints");
+
+ cloth_sim->length_constraints = MEM_callocN(sizeof(SculptClothLengthConstraint) *
+ CLOTH_LENGTH_CONSTRAINTS_BLOCK,
+ "cloth length constraints");
+ cloth_sim->capacity_length_constraints = CLOTH_LENGTH_CONSTRAINTS_BLOCK;
+
+ cloth_sim->acceleration = MEM_callocN(sizeof(float) * 3 * totverts, "cloth sim acceleration");
+ cloth_sim->pos = MEM_callocN(sizeof(float) * 3 * totverts, "cloth sim pos");
+ cloth_sim->prev_pos = MEM_callocN(sizeof(float) * 3 * totverts, "cloth sim prev pos");
+ cloth_sim->init_pos = MEM_callocN(sizeof(float) * 3 * totverts, "cloth sim init pos");
+ cloth_sim->length_constraint_tweak = MEM_callocN(sizeof(float) * totverts,
+ "cloth sim length tweak");
+
+ cloth_sim->mass = brush->cloth_mass;
+ cloth_sim->damping = brush->cloth_damping;
+
+ return cloth_sim;
+}
+
+static void do_cloth_brush_solve_simulation_task_cb_ex(
+ void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ PBVHVertexIter vd;
+ SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
+ const float time_step = data->cloth_time_step;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ const float sim_factor = cloth_brush_simulation_falloff_get(
+ brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[vd.index]);
+ if (sim_factor > 0.0f) {
+ int i = vd.index;
+ float temp[3];
+ copy_v3_v3(temp, cloth_sim->pos[i]);
+
+ mul_v3_fl(cloth_sim->acceleration[i], time_step);
+
+ float pos_diff[3];
+ sub_v3_v3v3(pos_diff, cloth_sim->pos[i], cloth_sim->prev_pos[i]);
+ mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping));
+
+ const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) *
+ SCULPT_automasking_factor_get(ss, vd.index);
+ madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v);
+ madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v);
+
+ copy_v3_v3(cloth_sim->prev_pos[i], temp);
+
+ copy_v3_fl(cloth_sim->acceleration[i], 0.0f);
+
+ copy_v3_v3(vd.co, ss->cache->cloth_sim->pos[vd.index]);
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void cloth_brush_build_nodes_constraints(Sculpt *sd,
+ Object *ob,
+ PBVHNode **nodes,
+ int totnode)
+{
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ /* TODO: Multi-threaded needs to be disabled for this task until implementing the optimization of
+ * storing the constraints per node. */
+ /* Currently all constrains are added to the same global array which can't be accessed from
+ * different threads. */
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, false, totnode);
+
+ SculptThreadedTaskData build_constraints_data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
+ BLI_task_parallel_range(
+ 0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
+}
+
+static void cloth_brush_satisfy_constraints(SculptSession *ss,
+ Brush *brush,
+ SculptClothSimulation *cloth_sim)
+{
+ for (int constraint_it = 0; constraint_it < CLOTH_SIMULATION_ITERATIONS; constraint_it++) {
+ for (int i = 0; i < cloth_sim->tot_length_constraints; i++) {
+
+ const SculptClothLengthConstraint *constraint = &cloth_sim->length_constraints[i];
+ const int v1 = constraint->v1;
+ const int v2 = constraint->v2;
+
+ float v1_to_v2[3];
+ sub_v3_v3v3(v1_to_v2, cloth_sim->pos[v2], cloth_sim->pos[v1]);
+ const float current_distance = len_v3(v1_to_v2);
+ float correction_vector[3];
+ float correction_vector_half[3];
+
+ const float constraint_distance = constraint->length +
+ (cloth_sim->length_constraint_tweak[v1] * 0.5f) +
+ (cloth_sim->length_constraint_tweak[v2] * 0.5f);
+
+ if (current_distance > 0.0f) {
+ mul_v3_v3fl(correction_vector, v1_to_v2, 1.0f - (constraint_distance / current_distance));
+ }
+ else {
+ copy_v3_v3(correction_vector, v1_to_v2);
+ }
+
+ mul_v3_v3fl(correction_vector_half, correction_vector, 0.5f);
+
+ const float mask_v1 = (1.0f - SCULPT_vertex_mask_get(ss, v1)) *
+ SCULPT_automasking_factor_get(ss, v1);
+ const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2)) *
+ SCULPT_automasking_factor_get(ss, v2);
+
+ const float sim_factor_v1 = cloth_brush_simulation_falloff_get(
+ brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v1]);
+ const float sim_factor_v2 = cloth_brush_simulation_falloff_get(
+ brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v2]);
+
+ madd_v3_v3fl(cloth_sim->pos[v1], correction_vector_half, 1.0f * mask_v1 * sim_factor_v1);
+ madd_v3_v3fl(cloth_sim->pos[v2], correction_vector_half, -1.0f * mask_v2 * sim_factor_v2);
+ }
+ }
+}
+
+static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
+
+ /* Update the constraints. */
+ cloth_brush_satisfy_constraints(ss, brush, cloth_sim);
+
+ /* Solve the simulation and write the final step to the mesh. */
+ SculptThreadedTaskData solve_simulation_data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .cloth_time_step = CLOTH_SIMULATION_TIME_STEP,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ BLI_task_parallel_range(
+ 0, totnode, &solve_simulation_data, do_cloth_brush_solve_simulation_task_cb_ex, &settings);
+}
+
+static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ float grab_delta[3];
+ float mat[4][4];
+ float area_no[3];
+ float area_co[3];
+ float imat[4][4];
+ float offset[3];
+
+ SculptThreadedTaskData apply_forces_data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .area_no = area_no,
+ .area_co = area_co,
+ .mat = imat,
+ };
+
+ BKE_curvemapping_initialize(brush->curve);
+
+ /* Init the grab delta. */
+ copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
+ normalize_v3(grab_delta);
+
+ apply_forces_data.grab_delta = grab_delta;
+
+ if (is_zero_v3(ss->cache->grab_delta_symmetry)) {
+ return;
+ }
+
+ /* Calcuate push offset. */
+
+ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PUSH) {
+ mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius);
+ mul_v3_v3(offset, ss->cache->scale);
+ mul_v3_fl(offset, 2.0f);
+
+ apply_forces_data.offset = offset;
+ }
+
+ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR ||
+ brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE) {
+ SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
+
+ /* Init stroke local space matrix. */
+ cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
+ mat[0][3] = 0.0f;
+ cross_v3_v3v3(mat[1], area_no, mat[0]);
+ mat[1][3] = 0.0f;
+ copy_v3_v3(mat[2], area_no);
+ mat[2][3] = 0.0f;
+ copy_v3_v3(mat[3], ss->cache->location);
+ mat[3][3] = 1.0f;
+ normalize_m4(mat);
+
+ apply_forces_data.area_co = area_co;
+ apply_forces_data.area_no = area_no;
+ apply_forces_data.mat = mat;
+
+ /* Update matrix for the cursor preview. */
+ if (ss->cache->mirror_symmetry_pass == 0) {
+ copy_m4_m4(ss->cache->stroke_local_mat, mat);
+ }
+ }
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ BLI_task_parallel_range(
+ 0, totnode, &apply_forces_data, do_cloth_brush_apply_forces_task_cb_ex, &settings);
+}
+
+/* Public functions. */
+
+/* Main Brush Function. */
+void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ const int totverts = SCULPT_vertex_count_get(ss);
+
+ /* In the first brush step of each symmetry pass, build the constraints for the vertices in all
+ * nodes inside the simulation's limits. */
+ /* Brush stroke types that restore the mesh on each brush step also need the cloth sim data to be
+ * created on each step. */
+ if (ss->cache->first_time || !ss->cache->cloth_sim) {
+
+ /* The simulation structure only needs to be created on the first symmetry pass. */
+ if (ss->cache->mirror_symmetry_pass == 0) {
+ ss->cache->cloth_sim = cloth_brush_simulation_create(ss, brush);
+ for (int i = 0; i < totverts; i++) {
+ copy_v3_v3(ss->cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
+ copy_v3_v3(ss->cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
+ }
+ }
+
+ /* Build the constraints. */
+ cloth_brush_build_nodes_constraints(sd, ob, nodes, totnode);
+
+ return;
+ }
+
+ /* Store the initial state in the simulation. */
+ for (int i = 0; i < totverts; i++) {
+ copy_v3_v3(ss->cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
+ }
+
+ /* Apply forces to the vertices. */
+ cloth_brush_apply_brush_foces(sd, ob, nodes, totnode);
+
+ /* Update and write the simulation to the nodes. */
+ cloth_brush_do_simulation_step(sd, ob, nodes, totnode);
+
+ return;
+}
+
+void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim)
+{
+ MEM_SAFE_FREE(cloth_sim->pos);
+ MEM_SAFE_FREE(cloth_sim->prev_pos);
+ MEM_SAFE_FREE(cloth_sim->acceleration);
+ MEM_SAFE_FREE(cloth_sim->length_constraints);
+ MEM_SAFE_FREE(cloth_sim->length_constraint_tweak);
+ MEM_SAFE_FREE(cloth_sim->init_pos);
+ MEM_SAFE_FREE(cloth_sim);
+}
+
+/* Cursor drawing function. */
+void SCULPT_cloth_simulation_limits_draw(const uint gpuattr,
+ const Brush *brush,
+ const float obmat[4][4],
+ const float location[3],
+ const float normal[3],
+ const float rds,
+ const float line_width,
+ const float outline_col[3],
+ const float alpha)
+{
+ float cursor_trans[4][4], cursor_rot[4][4];
+ float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f};
+ float quat[4];
+ copy_m4_m4(cursor_trans, obmat);
+ translate_m4(cursor_trans, location[0], location[1], location[2]);
+ rotation_between_vecs_to_quat(quat, z_axis, normal);
+ quat_to_mat4(cursor_rot, quat);
+ GPU_matrix_mul(cursor_trans);
+ GPU_matrix_mul(cursor_rot);
+
+ GPU_line_width(line_width);
+ immUniformColor3fvAlpha(outline_col, alpha * 0.5f);
+ imm_draw_circle_dashed_3d(
+ gpuattr, 0, 0, rds + (rds * brush->cloth_sim_limit * brush->cloth_sim_falloff), 320);
+ immUniformColor3fvAlpha(outline_col, alpha * 0.7f);
+ imm_draw_circle_wire_3d(gpuattr, 0, 0, rds + rds * brush->cloth_sim_limit, 80);
+}
+
+void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,
+ SculptSession *ss,
+ const float outline_col[3],
+ float outline_alpha)
+{
+ float local_mat_inv[4][4];
+ invert_m4_m4(local_mat_inv, ss->cache->stroke_local_mat);
+ GPU_matrix_mul(ss->cache->stroke_local_mat);
+
+ const float dist = ss->cache->radius;
+ const float arrow_x = ss->cache->radius * 0.2f;
+ const float arrow_y = ss->cache->radius * 0.1f;
+
+ immUniformColor3fvAlpha(outline_col, outline_alpha);
+ GPU_line_width(2.0f);
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3f(gpuattr, dist, 0.0f, 0.0f);
+ immVertex3f(gpuattr, -dist, 0.0f, 0.0f);
+ immEnd();
+
+ immBegin(GPU_PRIM_TRIS, 6);
+ immVertex3f(gpuattr, dist, 0.0f, 0.0f);
+ immVertex3f(gpuattr, dist - arrow_x, arrow_y, 0.0f);
+ immVertex3f(gpuattr, dist - arrow_x, -arrow_y, 0.0f);
+
+ immVertex3f(gpuattr, -dist, 0.0f, 0.0f);
+ immVertex3f(gpuattr, -dist + arrow_x, arrow_y, 0.0f);
+ immVertex3f(gpuattr, -dist + arrow_x, -arrow_y, 0.0f);
+
+ immEnd();
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c
new file mode 100644
index 00000000000..b7d1cd8c005
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_detail.c
@@ -0,0 +1,428 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_hash.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_view3d.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+typedef struct {
+ const float *ray_start;
+ bool hit;
+ float depth;
+ float edge_length;
+
+ struct IsectRayPrecalc isect_precalc;
+} SculptDetailRaycastData;
+
+static bool sculpt_and_constant_or_manual_detail_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+
+ return SCULPT_mode_poll(C) && ob->sculpt->bm &&
+ (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL));
+}
+
+static bool sculpt_and_dynamic_topology_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+
+ return SCULPT_mode_poll(C) && ob->sculpt->bm;
+}
+
+static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ float size;
+ float bb_min[3], bb_max[3], center[3], dim[3];
+ int totnodes;
+ PBVHNode **nodes;
+
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnodes);
+
+ if (!totnodes) {
+ return OPERATOR_CANCELLED;
+ }
+
+ for (int i = 0; i < totnodes; i++) {
+ BKE_pbvh_node_mark_topology_update(nodes[i]);
+ }
+ /* Get the bounding box, it's center and size. */
+ BKE_pbvh_bounding_box(ob->sculpt->pbvh, bb_min, bb_max);
+ add_v3_v3v3(center, bb_min, bb_max);
+ mul_v3_fl(center, 0.5f);
+ sub_v3_v3v3(dim, bb_max, bb_min);
+ size = max_fff(dim[0], dim[1], dim[2]);
+
+ /* Update topology size. */
+ float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat));
+ BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
+
+ SCULPT_undo_push_begin("Dynamic topology flood fill");
+ SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS);
+
+ while (BKE_pbvh_bmesh_update_topology(
+ ss->pbvh, PBVH_Collapse | PBVH_Subdivide, center, NULL, size, false, false)) {
+ for (int i = 0; i < totnodes; i++) {
+ BKE_pbvh_node_mark_topology_update(nodes[i]);
+ }
+ }
+
+ MEM_SAFE_FREE(nodes);
+ SCULPT_undo_push_end();
+
+ /* Force rebuild of pbvh for better BB placement. */
+ SCULPT_pbvh_clear(ob);
+ /* Redraw. */
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCULPT_OT_detail_flood_fill(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Detail Flood Fill";
+ ot->idname = "SCULPT_OT_detail_flood_fill";
+ ot->description = "Flood fill the mesh with the selected detail setting";
+
+ /* API callbacks. */
+ ot->exec = sculpt_detail_flood_fill_exec;
+ ot->poll = sculpt_and_constant_or_manual_detail_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+typedef enum eSculptSampleDetailModeTypes {
+ SAMPLE_DETAIL_DYNTOPO = 0,
+ SAMPLE_DETAIL_VOXEL = 1,
+} eSculptSampleDetailModeTypes;
+
+static EnumPropertyItem prop_sculpt_sample_detail_mode_types[] = {
+ {SAMPLE_DETAIL_DYNTOPO, "DYNTOPO", 0, "Dyntopo", "Sample dyntopo detail"},
+ {SAMPLE_DETAIL_VOXEL, "VOXEL", 0, "Voxel", "Sample mesh voxel size"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Object *ob = vc->obact;
+ Mesh *mesh = ob->data;
+
+ SculptSession *ss = ob->sculpt;
+ SculptCursorGeometryInfo sgi;
+ SCULPT_vertex_random_access_init(ss);
+
+ /* Update the active vertex. */
+ float mouse[2] = {mx, my};
+ SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false);
+
+ /* Average the edge length of the connected edges to the active vertex. */
+ int active_vertex = SCULPT_active_vertex_get(ss);
+ const float *active_vertex_co = SCULPT_active_vertex_co_get(ss);
+ float edge_length = 0.0f;
+ int tot = 0;
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, active_vertex, ni) {
+ edge_length += len_v3v3(active_vertex_co, SCULPT_vertex_co_get(ss, ni.index));
+ tot += 1;
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ if (tot > 0) {
+ mesh->remesh_voxel_size = edge_length / (float)tot;
+ }
+}
+
+static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
+{
+ if (BKE_pbvh_node_get_tmin(node) < *tmin) {
+ SculptDetailRaycastData *srd = data_v;
+ if (BKE_pbvh_bmesh_node_raycast_detail(
+ node, srd->ray_start, &srd->isect_precalc, &srd->depth, &srd->edge_length)) {
+ srd->hit = true;
+ *tmin = srd->depth;
+ }
+ }
+}
+
+static void sample_detail_dyntopo(bContext *C, ViewContext *vc, ARegion *region, int mx, int my)
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Object *ob = vc->obact;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ SCULPT_stroke_modifiers_check(C, ob, brush);
+
+ float mouse[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
+ float ray_start[3], ray_end[3], ray_normal[3];
+ float depth = SCULPT_raycast_init(vc, mouse, ray_start, ray_end, ray_normal, false);
+
+ SculptDetailRaycastData srd;
+ srd.hit = 0;
+ srd.ray_start = ray_start;
+ srd.depth = depth;
+ srd.edge_length = 0.0f;
+ isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
+
+ BKE_pbvh_raycast(ob->sculpt->pbvh, sculpt_raycast_detail_cb, &srd, ray_start, ray_normal, false);
+
+ if (srd.hit && srd.edge_length > 0.0f) {
+ /* Convert edge length to world space detail resolution. */
+ sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat));
+ }
+}
+
+static int sample_detail(bContext *C, int mx, int my, int mode)
+{
+ /* Find 3D view to pick from. */
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_VIEW3D, mx, my);
+ ARegion *region = (area) ? BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my) : NULL;
+ if (region == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Set context to 3D view. */
+ ScrArea *prev_area = CTX_wm_area(C);
+ ARegion *prev_region = CTX_wm_region(C);
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
+
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc, depsgraph);
+
+ Object *ob = vc.obact;
+ SculptSession *ss = ob->sculpt;
+
+ if (!ss->pbvh) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Pick sample detail. */
+ switch (mode) {
+ case SAMPLE_DETAIL_DYNTOPO:
+ if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
+ CTX_wm_area_set(C, prev_area);
+ CTX_wm_region_set(C, prev_region);
+ return OPERATOR_CANCELLED;
+ }
+ sample_detail_dyntopo(C, &vc, region, mx, my);
+ break;
+ case SAMPLE_DETAIL_VOXEL:
+ if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
+ CTX_wm_area_set(C, prev_area);
+ CTX_wm_region_set(C, prev_region);
+ return OPERATOR_CANCELLED;
+ }
+ sample_detail_voxel(C, &vc, mx, my);
+ break;
+ }
+
+ /* Restore context. */
+ CTX_wm_area_set(C, prev_area);
+ CTX_wm_region_set(C, prev_region);
+
+ return OPERATOR_FINISHED;
+}
+
+static int sculpt_sample_detail_size_exec(bContext *C, wmOperator *op)
+{
+ int ss_co[2];
+ RNA_int_get_array(op->ptr, "location", ss_co);
+ int mode = RNA_enum_get(op->ptr, "mode");
+ return sample_detail(C, ss_co[0], ss_co[1], mode);
+}
+
+static int sculpt_sample_detail_size_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e))
+{
+ ED_workspace_status_text(C, TIP_("Click on the mesh to set the detail"));
+ WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EYEDROPPER);
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sculpt_sample_detail_size_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ switch (event->type) {
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ int ss_co[2] = {event->x, event->y};
+
+ int mode = RNA_enum_get(op->ptr, "mode");
+ sample_detail(C, ss_co[0], ss_co[1], mode);
+
+ RNA_int_set_array(op->ptr, "location", ss_co);
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ ED_workspace_status_text(C, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ return OPERATOR_FINISHED;
+ }
+ break;
+
+ case RIGHTMOUSE: {
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ ED_workspace_status_text(C, NULL);
+
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Sample Detail Size";
+ ot->idname = "SCULPT_OT_sample_detail_size";
+ ot->description = "Sample the mesh detail on clicked point";
+
+ /* API callbacks. */
+ ot->invoke = sculpt_sample_detail_size_invoke;
+ ot->exec = sculpt_sample_detail_size_exec;
+ ot->modal = sculpt_sample_detail_size_modal;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int_array(ot->srna,
+ "location",
+ 2,
+ NULL,
+ 0,
+ SHRT_MAX,
+ "Location",
+ "Screen Coordinates of sampling",
+ 0,
+ SHRT_MAX);
+ RNA_def_enum(ot->srna,
+ "mode",
+ prop_sculpt_sample_detail_mode_types,
+ SAMPLE_DETAIL_DYNTOPO,
+ "Detail Mode",
+ "Target sculpting workflow that is going to use the sampled size");
+}
+
+/* Dynamic-topology detail size.
+ *
+ * This should be improved further, perhaps by showing a triangle
+ * grid rather than brush alpha. */
+static void set_brush_rc_props(PointerRNA *ptr, const char *prop)
+{
+ char *path = BLI_sprintfN("tool_settings.sculpt.brush.%s", prop);
+ RNA_string_set(ptr, "data_path_primary", path);
+ MEM_freeN(path);
+}
+
+static int sculpt_set_detail_size_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_radial_control", true);
+
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+
+ if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
+ set_brush_rc_props(&props_ptr, "constant_detail_resolution");
+ RNA_string_set(
+ &props_ptr, "data_path_primary", "tool_settings.sculpt.constant_detail_resolution");
+ }
+ else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
+ set_brush_rc_props(&props_ptr, "constant_detail_resolution");
+ RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_percent");
+ }
+ else {
+ set_brush_rc_props(&props_ptr, "detail_size");
+ RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_size");
+ }
+
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+
+ WM_operator_properties_free(&props_ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCULPT_OT_set_detail_size(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Set Detail Size";
+ ot->idname = "SCULPT_OT_set_detail_size";
+ ot->description =
+ "Set the mesh detail (either relative or constant one, depending on current dyntopo mode)";
+
+ /* API callbacks. */
+ ot->exec = sculpt_set_detail_size_exec;
+ ot->poll = sculpt_and_dynamic_topology_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
new file mode 100644
index 00000000000..eefd8529dbf
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
@@ -0,0 +1,439 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_hash.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_pbvh.h"
+#include "BKE_pointcache.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_view3d.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+void SCULPT_dynamic_topology_triangulate(BMesh *bm)
+{
+ if (bm->totloop != bm->totface * 3) {
+ BM_mesh_triangulate(
+ bm, MOD_TRIANGULATE_QUAD_BEAUTY, MOD_TRIANGULATE_NGON_EARCLIP, 4, false, NULL, NULL, NULL);
+ }
+}
+
+void SCULPT_pbvh_clear(Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+
+ /* Clear out any existing DM and PBVH. */
+ if (ss->pbvh) {
+ BKE_pbvh_free(ss->pbvh);
+ ss->pbvh = NULL;
+ }
+
+ if (ss->pmap) {
+ MEM_freeN(ss->pmap);
+ ss->pmap = NULL;
+ }
+
+ if (ss->pmap_mem) {
+ MEM_freeN(ss->pmap_mem);
+ ss->pmap_mem = NULL;
+ }
+
+ BKE_object_free_derived_caches(ob);
+
+ /* Tag to rebuild PBVH in depsgraph. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+}
+
+void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
+{
+ int cd_node_layer_index;
+
+ char layer_id[] = "_dyntopo_node_id";
+
+ cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id);
+ if (cd_node_layer_index == -1) {
+ BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_INT, layer_id);
+ cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id);
+ }
+
+ ss->cd_vert_node_offset = CustomData_get_n_offset(
+ &ss->bm->vdata,
+ CD_PROP_INT,
+ cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT));
+
+ ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
+
+ cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id);
+ if (cd_node_layer_index == -1) {
+ BM_data_layer_add_named(ss->bm, &ss->bm->pdata, CD_PROP_INT, layer_id);
+ cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id);
+ }
+
+ ss->cd_face_node_offset = CustomData_get_n_offset(
+ &ss->bm->pdata,
+ CD_PROP_INT,
+ cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT));
+
+ ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
+}
+
+void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
+
+ SCULPT_pbvh_clear(ob);
+
+ ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags & SCULPT_DYNTOPO_SMOOTH_SHADING) !=
+ 0;
+
+ /* Dynamic topology doesn't ensure selection state is valid, so remove [#36280]. */
+ BKE_mesh_mselect_clear(me);
+
+ /* Create triangles-only BMesh. */
+ ss->bm = BM_mesh_create(&allocsize,
+ &((struct BMeshCreateParams){
+ .use_toolflags = false,
+ }));
+
+ BM_mesh_bm_from_me(ss->bm,
+ me,
+ (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true,
+ .use_shapekey = true,
+ .active_shapekey = ob->shapenr,
+ }));
+ SCULPT_dynamic_topology_triangulate(ss->bm);
+ BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
+ SCULPT_dyntopo_node_layers_add(ss);
+ /* Make sure the data for existing faces are initialized. */
+ if (me->totpoly != ss->bm->totface) {
+ BM_mesh_normals_update(ss->bm);
+ }
+
+ /* Enable dynamic topology. */
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+
+ /* Enable logging for undo/redo. */
+ ss->bm_log = BM_log_create(ss->bm);
+
+ /* Update dependency graph, so modifiers that depend on dyntopo being enabled
+ * are re-evaluated and the PBVH is re-created. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+}
+
+/* Free the sculpt BMesh and BMLog
+ *
+ * If 'unode' is given, the BMesh's data is copied out to the unode
+ * before the BMesh is deleted so that it can be restored from. */
+static void SCULPT_dynamic_topology_disable_ex(
+ Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, SculptUndoNode *unode)
+{
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+
+ SCULPT_pbvh_clear(ob);
+
+ if (unode) {
+ /* Free all existing custom data. */
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
+ /* Copy over stored custom data. */
+ SculptUndoNodeGeometry *geometry = &unode->geometry_bmesh_enter;
+ me->totvert = geometry->totvert;
+ me->totloop = geometry->totloop;
+ me->totpoly = geometry->totpoly;
+ me->totedge = geometry->totedge;
+ me->totface = 0;
+ CustomData_copy(
+ &geometry->vdata, &me->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, geometry->totvert);
+ CustomData_copy(
+ &geometry->edata, &me->edata, CD_MASK_MESH.emask, CD_DUPLICATE, geometry->totedge);
+ CustomData_copy(
+ &geometry->ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop);
+ CustomData_copy(
+ &geometry->pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly);
+
+ BKE_mesh_update_customdata_pointers(me, false);
+ }
+ else {
+ BKE_sculptsession_bm_to_me(ob, true);
+
+ /* Reset Face Sets as they are no longer valid. */
+ if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) {
+ CustomData_add_layer(&me->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, me->totpoly);
+ }
+ ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
+ for (int i = 0; i < me->totpoly; i++) {
+ ss->face_sets[i] = 1;
+ }
+ me->face_sets_color_default = 1;
+
+ /* Sync the visibility to vertices manually as the pmap is still not initialized. */
+ for (int i = 0; i < me->totvert; i++) {
+ me->mvert[i].flag &= ~ME_HIDE;
+ me->mvert[i].flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+
+ /* Clear data. */
+ me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
+
+ /* Typically valid but with global-undo they can be NULL. [#36234] */
+ if (ss->bm) {
+ BM_mesh_free(ss->bm);
+ ss->bm = NULL;
+ }
+ if (ss->bm_log) {
+ BM_log_free(ss->bm_log);
+ ss->bm_log = NULL;
+ }
+
+ BKE_particlesystem_reset_all(ob);
+ BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED);
+
+ /* Update dependency graph, so modifiers that depend on dyntopo being enabled
+ * are re-evaluated and the PBVH is re-created. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+}
+
+void SCULPT_dynamic_topology_disable(bContext *C, SculptUndoNode *unode)
+{
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ SCULPT_dynamic_topology_disable_ex(bmain, depsgraph, scene, ob, unode);
+}
+
+void sculpt_dynamic_topology_disable_with_undo(Main *bmain,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ if (ss->bm) {
+ SCULPT_undo_push_begin("Dynamic topology disable");
+ SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
+ SCULPT_dynamic_topology_disable_ex(bmain, depsgraph, scene, ob, NULL);
+ SCULPT_undo_push_end();
+ }
+}
+
+static void sculpt_dynamic_topology_enable_with_undo(Main *bmain,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ if (ss->bm == NULL) {
+ SCULPT_undo_push_begin("Dynamic topology enable");
+ SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob);
+ SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ SCULPT_undo_push_end();
+ }
+}
+
+static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+
+ WM_cursor_wait(true);
+
+ if (ss->bm) {
+ sculpt_dynamic_topology_disable_with_undo(bmain, depsgraph, scene, ob);
+ }
+ else {
+ sculpt_dynamic_topology_enable_with_undo(bmain, depsgraph, scene, ob);
+ }
+
+ WM_cursor_wait(false);
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum eDynTopoWarnFlag flag)
+{
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Warning!"), ICON_ERROR);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ if (flag & (DYNTOPO_WARN_VDATA | DYNTOPO_WARN_EDATA | DYNTOPO_WARN_LDATA)) {
+ const char *msg_error = TIP_("Vertex Data Detected!");
+ const char *msg = TIP_("Dyntopo will not preserve vertex colors, UVs, or other customdata");
+ uiItemL(layout, msg_error, ICON_INFO);
+ uiItemL(layout, msg, ICON_NONE);
+ uiItemS(layout);
+ }
+
+ if (flag & DYNTOPO_WARN_MODIFIER) {
+ const char *msg_error = TIP_("Generative Modifiers Detected!");
+ const char *msg = TIP_(
+ "Keeping the modifiers will increase polycount when returning to object mode");
+
+ uiItemL(layout, msg_error, ICON_INFO);
+ uiItemL(layout, msg, ICON_NONE);
+ uiItemS(layout);
+ }
+
+ uiItemFullO_ptr(layout, ot, IFACE_("OK"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, NULL);
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+}
+
+enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob)
+{
+ Mesh *me = ob->data;
+ SculptSession *ss = ob->sculpt;
+
+ enum eDynTopoWarnFlag flag = 0;
+
+ BLI_assert(ss->bm == NULL);
+ UNUSED_VARS_NDEBUG(ss);
+
+ for (int i = 0; i < CD_NUMTYPES; i++) {
+ if (!ELEM(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX)) {
+ if (CustomData_has_layer(&me->vdata, i)) {
+ flag |= DYNTOPO_WARN_VDATA;
+ }
+ if (CustomData_has_layer(&me->edata, i)) {
+ flag |= DYNTOPO_WARN_EDATA;
+ }
+ if (CustomData_has_layer(&me->ldata, i)) {
+ flag |= DYNTOPO_WARN_LDATA;
+ }
+ }
+ }
+
+ {
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
+
+ /* Exception for shape keys because we can edit those. */
+ for (; md; md = md->next) {
+ const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
+ if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) {
+ continue;
+ }
+
+ if (mti->type == eModifierTypeType_Constructive) {
+ flag |= DYNTOPO_WARN_MODIFIER;
+ break;
+ }
+ }
+ }
+
+ return flag;
+}
+
+static int sculpt_dynamic_topology_toggle_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+
+ if (!ss->bm) {
+ Scene *scene = CTX_data_scene(C);
+ enum eDynTopoWarnFlag flag = SCULPT_dynamic_topology_check(scene, ob);
+
+ if (flag) {
+ /* The mesh has customdata that will be lost, let the user confirm this is OK. */
+ return dyntopo_warning_popup(C, op->type, flag);
+ }
+ }
+
+ return sculpt_dynamic_topology_toggle_exec(C, op);
+}
+
+void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Dynamic Topology Toggle";
+ ot->idname = "SCULPT_OT_dynamic_topology_toggle";
+ ot->description = "Dynamic topology alters the mesh topology while sculpting";
+
+ /* API callbacks. */
+ ot->invoke = sculpt_dynamic_topology_toggle_invoke;
+ ot->exec = sculpt_dynamic_topology_toggle_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
new file mode 100644
index 00000000000..f96f08e3244
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -0,0 +1,961 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_hash.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_ccg.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_multires.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_view3d.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+/* Draw Face Sets Brush. */
+
+static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float bstrength = ss->cache->bstrength;
+
+ PBVHVertexIter vd;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
+ MeshElemMap *vert_map = &ss->pmap[vd.index];
+ for (int j = 0; j < ss->pmap[vd.index].count; j++) {
+ const MPoly *p = &ss->mpoly[vert_map->indices[j]];
+
+ float poly_center[3];
+ BKE_mesh_calc_poly_center(p, &ss->mloop[p->loopstart], ss->mvert, poly_center);
+
+ if (sculpt_brush_test_sq_fn(&test, poly_center)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) {
+ ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set);
+ }
+ }
+ }
+ }
+
+ else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ if (fade > 0.05f) {
+ SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set);
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ float bstrength = ss->cache->bstrength;
+
+ PBVHVertexIter vd;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+
+ const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0);
+ /* This operations needs a stregth tweak as the relax deformation is too weak by default. */
+ if (relax_face_sets) {
+ bstrength *= 2.0f;
+ }
+
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ if (relax_face_sets != SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co);
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ BKE_curvemapping_initialize(brush->curve);
+
+ /* Threaded loop over nodes. */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ if (ss->cache->alt_smooth) {
+ for (int i = 0; i < 4; i++) {
+ BLI_task_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings);
+ }
+ }
+ else {
+ BLI_task_parallel_range(0, totnode, &data, do_draw_face_sets_brush_task_cb_ex, &settings);
+ }
+}
+
+/* Face Sets Operators */
+
+typedef enum eSculptFaceGroupsCreateModes {
+ SCULPT_FACE_SET_MASKED = 0,
+ SCULPT_FACE_SET_VISIBLE = 1,
+ SCULPT_FACE_SET_ALL = 2,
+ SCULPT_FACE_SET_SELECTION = 3,
+} eSculptFaceGroupsCreateModes;
+
+static EnumPropertyItem prop_sculpt_face_set_create_types[] = {
+ {
+ SCULPT_FACE_SET_MASKED,
+ "MASKED",
+ 0,
+ "Face Set From Masked",
+ "Create a new Face Set from the masked faces",
+ },
+ {
+ SCULPT_FACE_SET_VISIBLE,
+ "VISIBLE",
+ 0,
+ "Face Set From Visible",
+ "Create a new Face Set from the visible vertices",
+ },
+ {
+ SCULPT_FACE_SET_ALL,
+ "ALL",
+ 0,
+ "Face Set Full Mesh",
+ "Create an unique Face Set with all faces in the sculpt",
+ },
+ {
+ SCULPT_FACE_SET_SELECTION,
+ "SELECTION",
+ 0,
+ "Face Set From Edit Mode Selection",
+ "Create an Face Set corresponding to the Edit Mode face selection",
+ },
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ ARegion *region = CTX_wm_region(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+
+ const int mode = RNA_enum_get(op->ptr, "mode");
+
+ /* Dyntopo not suported. */
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, mode == SCULPT_FACE_SET_MASKED);
+
+ const int tot_vert = SCULPT_vertex_count_get(ss);
+ float threshold = 0.5f;
+
+ PBVH *pbvh = ob->sculpt->pbvh;
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+
+ if (!nodes) {
+ return OPERATOR_CANCELLED;
+ }
+
+ SCULPT_undo_push_begin("face set change");
+ SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
+
+ const int next_face_set = SCULPT_face_set_next_available_get(ss);
+
+ if (mode == SCULPT_FACE_SET_MASKED) {
+ for (int i = 0; i < tot_vert; i++) {
+ if (SCULPT_vertex_mask_get(ss, i) >= threshold && SCULPT_vertex_visible_get(ss, i)) {
+ SCULPT_vertex_face_set_set(ss, i, next_face_set);
+ }
+ }
+ }
+
+ if (mode == SCULPT_FACE_SET_VISIBLE) {
+ for (int i = 0; i < tot_vert; i++) {
+ if (SCULPT_vertex_visible_get(ss, i)) {
+ SCULPT_vertex_face_set_set(ss, i, next_face_set);
+ }
+ }
+ }
+
+ if (mode == SCULPT_FACE_SET_ALL) {
+ for (int i = 0; i < tot_vert; i++) {
+ SCULPT_vertex_face_set_set(ss, i, next_face_set);
+ }
+ }
+
+ if (mode == SCULPT_FACE_SET_SELECTION) {
+ Mesh *mesh = ob->data;
+ BMesh *bm;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
+ bm = BM_mesh_create(&allocsize,
+ &((struct BMeshCreateParams){
+ .use_toolflags = true,
+ }));
+
+ BM_mesh_bm_from_me(bm,
+ mesh,
+ (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true,
+ }));
+
+ BMIter iter;
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ ss->face_sets[BM_elem_index_get(f)] = next_face_set;
+ }
+ }
+ BM_mesh_free(bm);
+ }
+
+ for (int i = 0; i < totnode; i++) {
+ BKE_pbvh_node_mark_redraw(nodes[i]);
+ }
+
+ MEM_SAFE_FREE(nodes);
+
+ SCULPT_undo_push_end();
+
+ ED_region_tag_redraw(region);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCULPT_OT_face_sets_create(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Create Face Set";
+ ot->idname = "SCULPT_OT_face_sets_create";
+ ot->description = "Create a new Face Set";
+
+ /* api callbacks */
+ ot->exec = sculpt_face_set_create_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(
+ ot->srna, "mode", prop_sculpt_face_set_create_types, SCULPT_FACE_SET_MASKED, "Mode", "");
+}
+
+typedef enum eSculptFaceSetsInitMode {
+ SCULPT_FACE_SETS_FROM_LOOSE_PARTS = 0,
+ SCULPT_FACE_SETS_FROM_MATERIALS = 1,
+ SCULPT_FACE_SETS_FROM_NORMALS = 2,
+ SCULPT_FACE_SETS_FROM_UV_SEAMS = 3,
+ SCULPT_FACE_SETS_FROM_CREASES = 4,
+ SCULPT_FACE_SETS_FROM_SHARP_EDGES = 5,
+ SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT = 6,
+ SCULPT_FACE_SETS_FROM_FACE_MAPS = 7,
+} eSculptFaceSetsInitMode;
+
+static EnumPropertyItem prop_sculpt_face_sets_init_types[] = {
+ {
+ SCULPT_FACE_SETS_FROM_LOOSE_PARTS,
+ "LOOSE_PARTS",
+ 0,
+ "Face Sets From Loose Parts",
+ "Create a Face Set per loose part in the mesh",
+ },
+ {
+ SCULPT_FACE_SETS_FROM_MATERIALS,
+ "MATERIALS",
+ 0,
+ "Face Sets From Material Slots",
+ "Create a Face Set per Material Slot",
+ },
+ {
+ SCULPT_FACE_SETS_FROM_NORMALS,
+ "NORMALS",
+ 0,
+ "Face Sets From Mesh Normals",
+ "Create Face Sets for Faces that have similar normal",
+ },
+ {
+ SCULPT_FACE_SETS_FROM_UV_SEAMS,
+ "UV_SEAMS",
+ 0,
+ "Face Sets From UV Seams",
+ "Create Face Sets using UV Seams as boundaries",
+ },
+ {
+ SCULPT_FACE_SETS_FROM_CREASES,
+ "CREASES",
+ 0,
+ "Face Sets From Edge Creases",
+ "Create Face Sets using Edge Creases as boundaries",
+ },
+ {
+ SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT,
+ "BEVEL_WEIGHT",
+ 0,
+ "Face Sets From Bevel Weight",
+ "Create Face Sets using Bevel Weights as boundaries",
+ },
+ {
+ SCULPT_FACE_SETS_FROM_SHARP_EDGES,
+ "SHARP_EDGES",
+ 0,
+ "Face Sets From Sharp Edges",
+ "Create Face Sets using Sharp Edges as boundaries",
+ },
+ {
+ SCULPT_FACE_SETS_FROM_FACE_MAPS,
+ "FACE_MAPS",
+ 0,
+ "Face Sets From Face Maps",
+ "Create a Face Set per Face Map",
+ },
+ {0, NULL, 0, NULL, NULL},
+};
+
+typedef bool (*face_sets_flood_fill_test)(
+ BMesh *bm, BMFace *from_f, BMEdge *from_e, BMFace *to_f, const float threshold);
+
+static bool sculpt_face_sets_init_loose_parts_test(BMesh *UNUSED(bm),
+ BMFace *UNUSED(from_f),
+ BMEdge *UNUSED(from_e),
+ BMFace *UNUSED(to_f),
+ const float UNUSED(threshold))
+{
+ return true;
+}
+
+static bool sculpt_face_sets_init_normals_test(
+ BMesh *UNUSED(bm), BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float threshold)
+{
+ return fabsf(dot_v3v3(from_f->no, to_f->no)) > threshold;
+}
+
+static bool sculpt_face_sets_init_uv_seams_test(BMesh *UNUSED(bm),
+ BMFace *UNUSED(from_f),
+ BMEdge *from_e,
+ BMFace *UNUSED(to_f),
+ const float UNUSED(threshold))
+{
+ return !BM_elem_flag_test(from_e, BM_ELEM_SEAM);
+}
+
+static bool sculpt_face_sets_init_crease_test(
+ BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
+{
+ return BM_elem_float_data_get(&bm->edata, from_e, CD_CREASE) < threshold;
+}
+
+static bool sculpt_face_sets_init_bevel_weight_test(
+ BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
+{
+ return BM_elem_float_data_get(&bm->edata, from_e, CD_BWEIGHT) < threshold;
+}
+
+static bool sculpt_face_sets_init_sharp_edges_test(BMesh *UNUSED(bm),
+ BMFace *UNUSED(from_f),
+ BMEdge *from_e,
+ BMFace *UNUSED(to_f),
+ const float UNUSED(threshold))
+{
+ return BM_elem_flag_test(from_e, BM_ELEM_SMOOTH);
+}
+
+static void sculpt_face_sets_init_flood_fill(Object *ob,
+ face_sets_flood_fill_test test,
+ const float threshold)
+{
+ SculptSession *ss = ob->sculpt;
+ Mesh *mesh = ob->data;
+ BMesh *bm;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
+ bm = BM_mesh_create(&allocsize,
+ &((struct BMeshCreateParams){
+ .use_toolflags = true,
+ }));
+
+ BM_mesh_bm_from_me(bm,
+ mesh,
+ (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true,
+ }));
+
+ bool *visited_faces = MEM_callocN(sizeof(bool) * mesh->totpoly, "visited faces");
+ const int totfaces = mesh->totpoly;
+
+ int *face_sets = ss->face_sets;
+
+ BM_mesh_elem_table_init(bm, BM_FACE);
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+
+ int next_face_set = 1;
+
+ for (int i = 0; i < totfaces; i++) {
+ if (!visited_faces[i]) {
+ GSQueue *queue;
+ queue = BLI_gsqueue_new(sizeof(int));
+
+ face_sets[i] = next_face_set;
+ visited_faces[i] = true;
+ BLI_gsqueue_push(queue, &i);
+
+ while (!BLI_gsqueue_is_empty(queue)) {
+ int from_f;
+ BLI_gsqueue_pop(queue, &from_f);
+
+ BMFace *f, *f_neighbor;
+ BMEdge *ed;
+ BMIter iter_a, iter_b;
+
+ f = BM_face_at_index(bm, from_f);
+
+ BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) {
+ BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) {
+ if (f_neighbor != f) {
+ int neighbor_face_index = BM_elem_index_get(f_neighbor);
+ if (!visited_faces[neighbor_face_index]) {
+ if (test(bm, f, ed, f_neighbor, threshold)) {
+ face_sets[neighbor_face_index] = next_face_set;
+ visited_faces[neighbor_face_index] = true;
+ BLI_gsqueue_push(queue, &neighbor_face_index);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ next_face_set += 1;
+
+ BLI_gsqueue_free(queue);
+ }
+ }
+
+ MEM_SAFE_FREE(visited_faces);
+
+ BM_mesh_free(bm);
+}
+
+static void sculpt_face_sets_init_loop(Object *ob, const int mode)
+{
+ Mesh *mesh = ob->data;
+ SculptSession *ss = ob->sculpt;
+ BMesh *bm;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
+ bm = BM_mesh_create(&allocsize,
+ &((struct BMeshCreateParams){
+ .use_toolflags = true,
+ }));
+
+ BM_mesh_bm_from_me(bm,
+ mesh,
+ (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true,
+ }));
+ BMIter iter;
+ BMFace *f;
+
+ const int cd_fmaps_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) {
+ ss->face_sets[BM_elem_index_get(f)] = (int)(f->mat_nr + 1);
+ }
+ else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
+ if (cd_fmaps_offset != -1) {
+ ss->face_sets[BM_elem_index_get(f)] = BM_ELEM_CD_GET_INT(f, cd_fmaps_offset) + 2;
+ }
+ else {
+ ss->face_sets[BM_elem_index_get(f)] = 1;
+ }
+ }
+ }
+ BM_mesh_free(bm);
+}
+
+static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ ARegion *region = CTX_wm_region(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+
+ const int mode = RNA_enum_get(op->ptr, "mode");
+
+ /* Dyntopo not supported. */
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false);
+
+ PBVH *pbvh = ob->sculpt->pbvh;
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+
+ if (!nodes) {
+ return OPERATOR_CANCELLED;
+ }
+
+ SCULPT_undo_push_begin("face set change");
+ SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
+
+ const float threshold = RNA_float_get(op->ptr, "threshold");
+
+ switch (mode) {
+ case SCULPT_FACE_SETS_FROM_LOOSE_PARTS:
+ sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_loose_parts_test, threshold);
+ break;
+ case SCULPT_FACE_SETS_FROM_MATERIALS:
+ sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_MATERIALS);
+ break;
+ case SCULPT_FACE_SETS_FROM_NORMALS:
+ sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_normals_test, threshold);
+ break;
+ case SCULPT_FACE_SETS_FROM_UV_SEAMS:
+ sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_uv_seams_test, threshold);
+ break;
+ case SCULPT_FACE_SETS_FROM_CREASES:
+ sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_crease_test, threshold);
+ break;
+ case SCULPT_FACE_SETS_FROM_SHARP_EDGES:
+ sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_sharp_edges_test, threshold);
+ break;
+ case SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT:
+ sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_bevel_weight_test, threshold);
+ break;
+ case SCULPT_FACE_SETS_FROM_FACE_MAPS:
+ sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_FACE_MAPS);
+ break;
+ }
+
+ SCULPT_undo_push_end();
+
+ /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
+ SCULPT_visibility_sync_all_face_sets_to_vertices(ss);
+
+ for (int i = 0; i < totnode; i++) {
+ BKE_pbvh_node_mark_update_visibility(nodes[i]);
+ }
+
+ BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
+
+ MEM_SAFE_FREE(nodes);
+
+ if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
+ BKE_mesh_flush_hidden_from_verts(ob->data);
+ }
+
+ ED_region_tag_redraw(region);
+ DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
+
+ View3D *v3d = CTX_wm_view3d(C);
+ if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void SCULPT_OT_face_sets_init(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Init Face Sets";
+ ot->idname = "SCULPT_OT_face_sets_init";
+ ot->description = "Initializes all Face Sets in the mesh";
+
+ /* api callbacks */
+ ot->exec = sculpt_face_set_init_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(
+ ot->srna, "mode", prop_sculpt_face_sets_init_types, SCULPT_FACE_SET_MASKED, "Mode", "");
+ RNA_def_float(
+ ot->srna,
+ "threshold",
+ 0.5f,
+ 0.0f,
+ 1.0f,
+ "Threshold",
+ "Minimum value to consider a certain attribute a boundary when creating the Face Sets",
+ 0.0f,
+ 1.0f);
+}
+
+typedef enum eSculptFaceGroupVisibilityModes {
+ SCULPT_FACE_SET_VISIBILITY_TOGGLE = 0,
+ SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE = 1,
+ SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE = 2,
+ SCULPT_FACE_SET_VISIBILITY_INVERT = 3,
+ SCULPT_FACE_SET_VISIBILITY_SHOW_ALL = 4,
+} eSculptFaceGroupVisibilityModes;
+
+static EnumPropertyItem prop_sculpt_face_sets_change_visibility_types[] = {
+ {
+ SCULPT_FACE_SET_VISIBILITY_TOGGLE,
+ "TOGGLE",
+ 0,
+ "Toggle Visibility",
+ "Hide all Face Sets except for the active one",
+ },
+ {
+ SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE,
+ "SHOW_ACTIVE",
+ 0,
+ "Show Active Face Set",
+ "Show Active Face Set",
+ },
+ {
+ SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE,
+ "HIDE_ACTIVE",
+ 0,
+ "Hide Active Face Sets",
+ "Hide Active Face Sets",
+ },
+ {
+ SCULPT_FACE_SET_VISIBILITY_INVERT,
+ "INVERT",
+ 0,
+ "Invert Face Set Visibility",
+ "Invert Face Set Visibility",
+ },
+ {
+ SCULPT_FACE_SET_VISIBILITY_SHOW_ALL,
+ "SHOW_ALL",
+ 0,
+ "Show All Face Sets",
+ "Show All Face Sets",
+ },
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ ARegion *region = CTX_wm_region(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+
+ /* Dyntopo not supported. */
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
+
+ const int tot_vert = SCULPT_vertex_count_get(ss);
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ const int active_face_set = SCULPT_active_face_set_get(ss);
+
+ SCULPT_undo_push_begin("Hide area");
+
+ PBVH *pbvh = ob->sculpt->pbvh;
+ PBVHNode **nodes;
+ int totnode;
+
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+
+ if (totnode == 0) {
+ MEM_SAFE_FREE(nodes);
+ return OPERATOR_CANCELLED;
+ }
+
+ SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
+
+ if (mode == SCULPT_FACE_SET_VISIBILITY_TOGGLE) {
+ bool hidden_vertex = false;
+
+ /* This can fail with regular meshes with non-manifold geometry as the visibility state can't
+ * be synced from face sets to non-manifold vertices. */
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
+ for (int i = 0; i < tot_vert; i++) {
+ if (!SCULPT_vertex_visible_get(ss, i)) {
+ hidden_vertex = true;
+ break;
+ }
+ }
+ }
+
+ for (int i = 0; i < ss->totfaces; i++) {
+ if (ss->face_sets[i] <= 0) {
+ hidden_vertex = true;
+ break;
+ }
+ }
+
+ if (hidden_vertex) {
+ SCULPT_face_sets_visibility_all_set(ss, true);
+ }
+ else {
+ SCULPT_face_sets_visibility_all_set(ss, false);
+ SCULPT_face_set_visibility_set(ss, active_face_set, true);
+ }
+ }
+
+ if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ALL) {
+ SCULPT_face_sets_visibility_all_set(ss, true);
+ }
+
+ if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE) {
+ SCULPT_face_sets_visibility_all_set(ss, false);
+ SCULPT_face_set_visibility_set(ss, active_face_set, true);
+ for (int i = 0; i < tot_vert; i++) {
+ SCULPT_vertex_visible_set(ss,
+ i,
+ SCULPT_vertex_visible_get(ss, i) &&
+ SCULPT_vertex_has_face_set(ss, i, active_face_set));
+ }
+ }
+
+ if (mode == SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE) {
+ SCULPT_face_set_visibility_set(ss, active_face_set, false);
+ }
+
+ if (mode == SCULPT_FACE_SET_VISIBILITY_INVERT) {
+ SCULPT_face_sets_visibility_invert(ss);
+ }
+
+ /* For modes that use the cursor active vertex, update the rotation origin for viewport
+ * navigation. */
+ if (ELEM(mode, SCULPT_FACE_SET_VISIBILITY_TOGGLE, SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE)) {
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+ float location[3];
+ copy_v3_v3(location, SCULPT_active_vertex_co_get(ss));
+ mul_m4_v3(ob->obmat, location);
+ copy_v3_v3(ups->average_stroke_accum, location);
+ ups->average_stroke_counter = 1;
+ ups->last_stroke_valid = true;
+ }
+
+ /* Sync face sets visibility and vertex visibility. */
+ SCULPT_visibility_sync_all_face_sets_to_vertices(ss);
+
+ SCULPT_undo_push_end();
+
+ for (int i = 0; i < totnode; i++) {
+ BKE_pbvh_node_mark_update_visibility(nodes[i]);
+ }
+
+ BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
+
+ MEM_SAFE_FREE(nodes);
+
+ if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
+ BKE_mesh_flush_hidden_from_verts(ob->data);
+ }
+
+ ED_region_tag_redraw(region);
+ DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
+
+ View3D *v3d = CTX_wm_view3d(C);
+ if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void SCULPT_OT_face_sets_change_visibility(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Face Sets Visibility";
+ ot->idname = "SCULPT_OT_face_set_change_visibility";
+ ot->description = "Change the visibility of the Face Sets of the sculpt";
+
+ /* Api callbacks. */
+ ot->exec = sculpt_face_sets_change_visibility_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna,
+ "mode",
+ prop_sculpt_face_sets_change_visibility_types,
+ SCULPT_FACE_SET_VISIBILITY_TOGGLE,
+ "Mode",
+ "");
+}
+
+static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSED(op))
+{
+
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ ARegion *region = CTX_wm_region(C);
+
+ /* Dyntopo not supported. */
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ return OPERATOR_CANCELLED;
+ }
+
+ PBVH *pbvh = ob->sculpt->pbvh;
+ PBVHNode **nodes;
+ int totnode;
+ Mesh *mesh = ob->data;
+
+ mesh->face_sets_color_seed += 1;
+ if (ss->face_sets) {
+ const int random_index = clamp_i(ss->totfaces * BLI_hash_int_01(mesh->face_sets_color_seed),
+ 0,
+ max_ii(0, ss->totfaces - 1));
+ mesh->face_sets_color_default = ss->face_sets[random_index];
+ }
+ BKE_pbvh_face_sets_color_set(pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default);
+
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ for (int i = 0; i < totnode; i++) {
+ BKE_pbvh_node_mark_redraw(nodes[i]);
+ }
+
+ MEM_SAFE_FREE(nodes);
+
+ View3D *v3d = CTX_wm_view3d(C);
+ if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
+ }
+
+ ED_region_tag_redraw(region);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCULPT_OT_face_sets_randomize_colors(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Randomize Face Sets Colors";
+ ot->idname = "SCULPT_OT_face_sets_randomize_colors";
+ ot->description = "Generates a new set of random colors to render the Face Sets in the viewport";
+
+ /* Api callbacks. */
+ ot->exec = sculpt_face_sets_randomize_colors_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
new file mode 100644
index 00000000000..d2a683461a7
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
@@ -0,0 +1,502 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_hash.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+typedef enum eSculptMaskFilterTypes {
+ MASK_FILTER_SMOOTH = 0,
+ MASK_FILTER_SHARPEN = 1,
+ MASK_FILTER_GROW = 2,
+ MASK_FILTER_SHRINK = 3,
+ MASK_FILTER_CONTRAST_INCREASE = 5,
+ MASK_FILTER_CONTRAST_DECREASE = 6,
+} eSculptMaskFilterTypes;
+
+static EnumPropertyItem prop_mask_filter_types[] = {
+ {MASK_FILTER_SMOOTH, "SMOOTH", 0, "Smooth Mask", "Smooth mask"},
+ {MASK_FILTER_SHARPEN, "SHARPEN", 0, "Sharpen Mask", "Sharpen mask"},
+ {MASK_FILTER_GROW, "GROW", 0, "Grow Mask", "Grow mask"},
+ {MASK_FILTER_SHRINK, "SHRINK", 0, "Shrink Mask", "Shrink mask"},
+ {MASK_FILTER_CONTRAST_INCREASE,
+ "CONTRAST_INCREASE",
+ 0,
+ "Increase contrast",
+ "Increase the contrast of the paint mask"},
+ {MASK_FILTER_CONTRAST_DECREASE,
+ "CONTRAST_DECREASE",
+ 0,
+ "Decrease contrast",
+ "Decrease the contrast of the paint mask"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static void mask_filter_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+ bool update = false;
+
+ const int mode = data->filter_type;
+ float contrast = 0.0f;
+
+ PBVHVertexIter vd;
+
+ if (mode == MASK_FILTER_CONTRAST_INCREASE) {
+ contrast = 0.1f;
+ }
+
+ if (mode == MASK_FILTER_CONTRAST_DECREASE) {
+ contrast = -0.1f;
+ }
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ float delta, gain, offset, max, min;
+ float prev_val = *vd.mask;
+ SculptVertexNeighborIter ni;
+ switch (mode) {
+ case MASK_FILTER_SMOOTH:
+ case MASK_FILTER_SHARPEN: {
+ float val = SCULPT_neighbor_mask_average(ss, vd.index);
+
+ val -= *vd.mask;
+
+ if (mode == MASK_FILTER_SMOOTH) {
+ *vd.mask += val;
+ }
+ else if (mode == MASK_FILTER_SHARPEN) {
+ if (*vd.mask > 0.5f) {
+ *vd.mask += 0.05f;
+ }
+ else {
+ *vd.mask -= 0.05f;
+ }
+ *vd.mask += val / 2.0f;
+ }
+ break;
+ }
+ case MASK_FILTER_GROW:
+ max = 0.0f;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ float vmask_f = data->prev_mask[ni.index];
+ if (vmask_f > max) {
+ max = vmask_f;
+ }
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ *vd.mask = max;
+ break;
+ case MASK_FILTER_SHRINK:
+ min = 1.0f;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ float vmask_f = data->prev_mask[ni.index];
+ if (vmask_f < min) {
+ min = vmask_f;
+ }
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ *vd.mask = min;
+ break;
+ case MASK_FILTER_CONTRAST_INCREASE:
+ case MASK_FILTER_CONTRAST_DECREASE:
+ delta = contrast / 2.0f;
+ gain = 1.0f - delta * 2.0f;
+ if (contrast > 0) {
+ gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON);
+ offset = gain * (-delta);
+ }
+ else {
+ delta *= -1.0f;
+ offset = gain * (delta);
+ }
+ *vd.mask = gain * (*vd.mask) + offset;
+ break;
+ }
+ CLAMP(*vd.mask, 0.0f, 1.0f);
+ if (*vd.mask != prev_val) {
+ update = true;
+ }
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ if (update) {
+ BKE_pbvh_node_mark_update_mask(node);
+ }
+}
+
+static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
+{
+ ARegion *region = CTX_wm_region(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ PBVH *pbvh = ob->sculpt->pbvh;
+ PBVHNode **nodes;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ int totnode;
+ int filter_type = RNA_enum_get(op->ptr, "filter_type");
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
+
+ SCULPT_vertex_random_access_init(ss);
+
+ if (!ob->sculpt->pmap) {
+ return OPERATOR_CANCELLED;
+ }
+
+ int num_verts = SCULPT_vertex_count_get(ss);
+
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ SCULPT_undo_push_begin("Mask filter");
+
+ for (int i = 0; i < totnode; i++) {
+ SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
+ }
+
+ float *prev_mask = NULL;
+ int iterations = RNA_int_get(op->ptr, "iterations");
+
+ /* Auto iteration count calculates the number of iteration based on the vertices of the mesh to
+ * avoid adding an unnecessary amount of undo steps when using the operator from a shortcut.
+ * One iteration per 50000 vertices in the mesh should be fine in most cases.
+ * Maybe we want this to be configurable. */
+ if (RNA_boolean_get(op->ptr, "auto_iteration_count")) {
+ iterations = (int)(num_verts / 50000.0f) + 1;
+ }
+
+ for (int i = 0; i < iterations; i++) {
+ if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) {
+ prev_mask = MEM_mallocN(num_verts * sizeof(float), "prevmask");
+ for (int j = 0; j < num_verts; j++) {
+ prev_mask[j] = SCULPT_vertex_mask_get(ss, j);
+ }
+ }
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = nodes,
+ .filter_type = filter_type,
+ .prev_mask = prev_mask,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings);
+
+ if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) {
+ MEM_freeN(prev_mask);
+ }
+ }
+
+ MEM_SAFE_FREE(nodes);
+
+ SCULPT_undo_push_end();
+
+ ED_region_tag_redraw(region);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ return OPERATOR_FINISHED;
+}
+
+void SCULPT_mask_filter_smooth_apply(
+ Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, const int smooth_iterations)
+{
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = nodes,
+ .filter_type = MASK_FILTER_SMOOTH,
+ };
+
+ for (int i = 0; i < smooth_iterations; i++) {
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings);
+ }
+}
+
+void SCULPT_OT_mask_filter(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Mask Filter";
+ ot->idname = "SCULPT_OT_mask_filter";
+ ot->description = "Applies a filter to modify the current mask";
+
+ /* API callbacks. */
+ ot->exec = sculpt_mask_filter_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER;
+
+ /* RNA. */
+ RNA_def_enum(ot->srna,
+ "filter_type",
+ prop_mask_filter_types,
+ MASK_FILTER_SMOOTH,
+ "Type",
+ "Filter that is going to be applied to the mask");
+ RNA_def_int(ot->srna,
+ "iterations",
+ 1,
+ 1,
+ 100,
+ "Iterations",
+ "Number of times that the filter is going to be applied",
+ 1,
+ 100);
+ RNA_def_boolean(
+ ot->srna,
+ "auto_iteration_count",
+ false,
+ "Auto Iteration Count",
+ "Use a automatic number of iterations based on the number of vertices of the sculpt");
+}
+
+static float neighbor_dirty_mask(SculptSession *ss, PBVHVertexIter *vd)
+{
+ int total = 0;
+ float avg[3];
+ zero_v3(avg);
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->index, ni) {
+ float normalized[3];
+ sub_v3_v3v3(normalized, SCULPT_vertex_co_get(ss, ni.index), vd->co);
+ normalize_v3(normalized);
+ add_v3_v3(avg, normalized);
+ total++;
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ float normal[3];
+ if (vd->no) {
+ normal_short_to_float_v3(normal, vd->no);
+ }
+ else {
+ copy_v3_v3(normal, vd->fno);
+ }
+ float dot = dot_v3v3(avg, normal);
+ float angle = max_ff(saacosf(dot), 0.0f);
+ return angle;
+ }
+ return 0.0f;
+}
+
+typedef struct DirtyMaskRangeData {
+ float min, max;
+} DirtyMaskRangeData;
+
+static void dirty_mask_compute_range_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+ DirtyMaskRangeData *range = tls->userdata_chunk;
+ PBVHVertexIter vd;
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ float dirty_mask = neighbor_dirty_mask(ss, &vd);
+ range->min = min_ff(dirty_mask, range->min);
+ range->max = max_ff(dirty_mask, range->max);
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void dirty_mask_compute_range_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
+{
+ DirtyMaskRangeData *join = chunk_join;
+ DirtyMaskRangeData *range = chunk;
+ join->min = min_ff(range->min, join->min);
+ join->max = max_ff(range->max, join->max);
+}
+
+static void dirty_mask_apply_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+ PBVHVertexIter vd;
+
+ const bool dirty_only = data->dirty_mask_dirty_only;
+ const float min = data->dirty_mask_min;
+ const float max = data->dirty_mask_max;
+
+ float range = max - min;
+ if (range < 0.0001f) {
+ range = 0.0f;
+ }
+ else {
+ range = 1.0f / range;
+ }
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ float dirty_mask = neighbor_dirty_mask(ss, &vd);
+ float mask = *vd.mask + (1.0f - ((dirty_mask - min) * range));
+ if (dirty_only) {
+ mask = fminf(mask, 0.5f) * 2.0f;
+ }
+ *vd.mask = CLAMPIS(mask, 0.0f, 1.0f);
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ BKE_pbvh_node_mark_update_mask(node);
+}
+
+static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
+{
+ ARegion *region = CTX_wm_region(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ PBVH *pbvh = ob->sculpt->pbvh;
+ PBVHNode **nodes;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ int totnode;
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
+
+ SCULPT_vertex_random_access_init(ss);
+
+ if (!ob->sculpt->pmap) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ SCULPT_undo_push_begin("Dirty Mask");
+
+ for (int i = 0; i < totnode; i++) {
+ SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
+ }
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = nodes,
+ .dirty_mask_dirty_only = RNA_boolean_get(op->ptr, "dirty_only"),
+ };
+ DirtyMaskRangeData range = {
+ .min = FLT_MAX,
+ .max = -FLT_MAX,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+
+ settings.func_reduce = dirty_mask_compute_range_reduce;
+ settings.userdata_chunk = &range;
+ settings.userdata_chunk_size = sizeof(DirtyMaskRangeData);
+
+ BLI_task_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings);
+ data.dirty_mask_min = range.min;
+ data.dirty_mask_max = range.max;
+ BLI_task_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings);
+
+ MEM_SAFE_FREE(nodes);
+
+ BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask);
+
+ SCULPT_undo_push_end();
+
+ ED_region_tag_redraw(region);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCULPT_OT_dirty_mask(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Dirty Mask";
+ ot->idname = "SCULPT_OT_dirty_mask";
+ ot->description = "Generates a mask based on the geometry cavity and pointiness";
+
+ /* API callbacks. */
+ ot->exec = sculpt_dirty_mask_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER;
+
+ /* RNA. */
+ RNA_def_boolean(
+ ot->srna, "dirty_only", false, "Dirty Only", "Don't calculate cleans for convex areas");
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
new file mode 100644
index 00000000000..7c438e9245b
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -0,0 +1,673 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_hash.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+static void filter_cache_init_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ PBVHNode *node = data->nodes[i];
+
+ SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
+}
+
+void SCULPT_filter_cache_init(Object *ob, Sculpt *sd)
+{
+ SculptSession *ss = ob->sculpt;
+ PBVH *pbvh = ob->sculpt->pbvh;
+
+ ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
+
+ ss->filter_cache->random_seed = rand();
+
+ float center[3] = {0.0f};
+ SculptSearchSphereData search_data = {
+ .original = true,
+ .center = center,
+ .radius_squared = FLT_MAX,
+ .ignore_fully_masked = true,
+
+ };
+ BKE_pbvh_search_gather(pbvh,
+ SCULPT_search_sphere_cb,
+ &search_data,
+ &ss->filter_cache->nodes,
+ &ss->filter_cache->totnode);
+
+ for (int i = 0; i < ss->filter_cache->totnode; i++) {
+ BKE_pbvh_node_mark_normals_update(ss->filter_cache->nodes[i]);
+ }
+
+ /* mesh->runtime.subdiv_ccg is not available. Updating of the normals is done during drawing.
+ * Filters can't use normals in multires. */
+ if (BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) {
+ BKE_pbvh_update_normals(ss->pbvh, NULL);
+ }
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = ss->filter_cache->nodes,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(
+ &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
+ BLI_task_parallel_range(
+ 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
+}
+
+void SCULPT_filter_cache_free(SculptSession *ss)
+{
+ MEM_SAFE_FREE(ss->filter_cache->nodes);
+ MEM_SAFE_FREE(ss->filter_cache->mask_update_it);
+ MEM_SAFE_FREE(ss->filter_cache->prev_mask);
+ MEM_SAFE_FREE(ss->filter_cache->normal_factor);
+ MEM_SAFE_FREE(ss->filter_cache->prev_face_set);
+ MEM_SAFE_FREE(ss->filter_cache->automask);
+ MEM_SAFE_FREE(ss->filter_cache->surface_smooth_laplacian_disp);
+ MEM_SAFE_FREE(ss->filter_cache->sharpen_factor);
+ MEM_SAFE_FREE(ss->filter_cache->accum_disp);
+ MEM_SAFE_FREE(ss->filter_cache);
+}
+
+typedef enum eSculptMeshFilterTypes {
+ MESH_FILTER_SMOOTH = 0,
+ MESH_FILTER_SCALE = 1,
+ MESH_FILTER_INFLATE = 2,
+ MESH_FILTER_SPHERE = 3,
+ MESH_FILTER_RANDOM = 4,
+ MESH_FILTER_RELAX = 5,
+ MESH_FILTER_RELAX_FACE_SETS = 6,
+ MESH_FILTER_SURFACE_SMOOTH = 7,
+ MESH_FILTER_SHARPEN = 8,
+} eSculptMeshFilterTypes;
+
+static EnumPropertyItem prop_mesh_filter_types[] = {
+ {MESH_FILTER_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth mesh"},
+ {MESH_FILTER_SCALE, "SCALE", 0, "Scale", "Scale mesh"},
+ {MESH_FILTER_INFLATE, "INFLATE", 0, "Inflate", "Inflate mesh"},
+ {MESH_FILTER_SPHERE, "SPHERE", 0, "Sphere", "Morph into sphere"},
+ {MESH_FILTER_RANDOM, "RANDOM", 0, "Random", "Randomize vertex positions"},
+ {MESH_FILTER_RELAX, "RELAX", 0, "Relax", "Relax mesh"},
+ {MESH_FILTER_RELAX_FACE_SETS,
+ "RELAX_FACE_SETS",
+ 0,
+ "Relax Face Sets",
+ "Smooth the edges of all the Face Sets"},
+ {MESH_FILTER_SURFACE_SMOOTH,
+ "SURFACE_SMOOTH",
+ 0,
+ "Surface Smooth",
+ "Smooth the surface of the mesh, preserving the volume"},
+ {MESH_FILTER_SHARPEN, "SHARPEN", 0, "Sharpen", "Sharpen the cavities of the mesh"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+typedef enum eMeshFilterDeformAxis {
+ MESH_FILTER_DEFORM_X = 1 << 0,
+ MESH_FILTER_DEFORM_Y = 1 << 1,
+ MESH_FILTER_DEFORM_Z = 1 << 2,
+} eMeshFilterDeformAxis;
+
+static EnumPropertyItem prop_mesh_filter_deform_axis_items[] = {
+ {MESH_FILTER_DEFORM_X, "X", 0, "X", "Deform in the X axis"},
+ {MESH_FILTER_DEFORM_Y, "Y", 0, "Y", "Deform in the Y axis"},
+ {MESH_FILTER_DEFORM_Z, "Z", 0, "Z", "Deform in the Z axis"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static bool sculpt_mesh_filter_needs_pmap(int filter_type, bool use_face_sets)
+{
+ return use_face_sets || ELEM(filter_type,
+ MESH_FILTER_SMOOTH,
+ MESH_FILTER_RELAX,
+ MESH_FILTER_RELAX_FACE_SETS,
+ MESH_FILTER_SURFACE_SMOOTH,
+ MESH_FILTER_SHARPEN);
+}
+
+static void mesh_filter_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+
+ const int filter_type = data->filter_type;
+
+ SculptOrigVertData orig_data;
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i]);
+
+ /* When using the relax face sets meshes filter,
+ * each 3 iterations, do a whole mesh relax to smooth the contents of the Face Set. */
+ /* This produces better results as the relax operation is no completely focused on the
+ * boundaries. */
+ const bool relax_face_sets = !(ss->filter_cache->iteration_count % 3 == 0);
+
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
+ float orig_co[3], val[3], avg[3], normal[3], disp[3], disp2[3], transform[3][3], final_pos[3];
+ float fade = vd.mask ? *vd.mask : 0.0f;
+ fade = 1.0f - fade;
+ fade *= data->filter_strength;
+
+ if (fade == 0.0f) {
+ continue;
+ }
+
+ if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) {
+ if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) {
+ /* Surface Smooth can't skip the loop for this vertex as it needs to calculate its
+ * laplacian_disp. This value is accessed from the vertex neighbors when deforming the
+ * vertices, so it is needed for all vertices even if they are not going to be displaced.
+ */
+ if (filter_type == MESH_FILTER_SURFACE_SMOOTH) {
+ fade = 0.0f;
+ }
+ else {
+ continue;
+ }
+ }
+ /* Skip the edges of the face set when relaxing or smoothing.
+ * There is a relax face set option to relax the boundaries independently. */
+ if (filter_type == MESH_FILTER_RELAX) {
+ if (!SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
+ continue;
+ }
+ }
+ }
+
+ if (ELEM(filter_type, MESH_FILTER_RELAX, MESH_FILTER_RELAX_FACE_SETS)) {
+ copy_v3_v3(orig_co, vd.co);
+ }
+ else {
+ copy_v3_v3(orig_co, orig_data.co);
+ }
+
+ if (filter_type == MESH_FILTER_RELAX_FACE_SETS) {
+ if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
+ continue;
+ }
+ }
+
+ switch (filter_type) {
+ case MESH_FILTER_SMOOTH:
+ CLAMP(fade, -1.0f, 1.0f);
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ SCULPT_neighbor_average(ss, avg, vd.index);
+ break;
+ case PBVH_BMESH:
+ SCULPT_bmesh_neighbor_average(avg, vd.bm_vert);
+ break;
+ case PBVH_GRIDS:
+ SCULPT_neighbor_coords_average(ss, avg, vd.index);
+ break;
+ }
+ sub_v3_v3v3(val, avg, orig_co);
+ madd_v3_v3v3fl(val, orig_co, val, fade);
+ sub_v3_v3v3(disp, val, orig_co);
+ break;
+ case MESH_FILTER_INFLATE:
+ normal_short_to_float_v3(normal, orig_data.no);
+ mul_v3_v3fl(disp, normal, fade);
+ break;
+ case MESH_FILTER_SCALE:
+ unit_m3(transform);
+ scale_m3_fl(transform, 1.0f + fade);
+ copy_v3_v3(val, orig_co);
+ mul_m3_v3(transform, val);
+ sub_v3_v3v3(disp, val, orig_co);
+ break;
+ case MESH_FILTER_SPHERE:
+ normalize_v3_v3(disp, orig_co);
+ if (fade > 0.0f) {
+ mul_v3_v3fl(disp, disp, fade);
+ }
+ else {
+ mul_v3_v3fl(disp, disp, -fade);
+ }
+
+ unit_m3(transform);
+ if (fade > 0.0f) {
+ scale_m3_fl(transform, 1.0f - fade);
+ }
+ else {
+ scale_m3_fl(transform, 1.0f + fade);
+ }
+ copy_v3_v3(val, orig_co);
+ mul_m3_v3(transform, val);
+ sub_v3_v3v3(disp2, val, orig_co);
+
+ mid_v3_v3v3(disp, disp, disp2);
+ break;
+ case MESH_FILTER_RANDOM: {
+ normal_short_to_float_v3(normal, orig_data.no);
+ /* Index is not unique for multires, so hash by vertex coordinates. */
+ const uint *hash_co = (const uint *)orig_co;
+ const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^
+ BLI_hash_int_2d(hash_co[2], ss->filter_cache->random_seed);
+ mul_v3_fl(normal, hash * (1.0f / (float)0xFFFFFFFF) - 0.5f);
+ mul_v3_v3fl(disp, normal, fade);
+ break;
+ }
+ case MESH_FILTER_RELAX: {
+ SCULPT_relax_vertex(
+ ss, &vd, clamp_f(fade * ss->filter_cache->automask[vd.index], 0.0f, 1.0f), false, val);
+ sub_v3_v3v3(disp, val, vd.co);
+ break;
+ }
+ case MESH_FILTER_RELAX_FACE_SETS: {
+ SCULPT_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), relax_face_sets, val);
+ sub_v3_v3v3(disp, val, vd.co);
+ break;
+ }
+ case MESH_FILTER_SURFACE_SMOOTH: {
+ SCULPT_surface_smooth_laplacian_step(ss,
+ disp,
+ vd.co,
+ ss->filter_cache->surface_smooth_laplacian_disp,
+ vd.index,
+ orig_data.co,
+ ss->filter_cache->surface_smooth_shape_preservation);
+ break;
+ }
+ case MESH_FILTER_SHARPEN: {
+ const float smooth_ratio = ss->filter_cache->sharpen_smooth_ratio;
+
+ /* This filter can't work at full strength as it needs multiple iterations to reach a
+ * stable state. */
+ fade = clamp_f(fade, 0.0f, 0.5f);
+
+ float disp_sharpen[3];
+ copy_v3_v3(disp_sharpen, ss->filter_cache->accum_disp[vd.index]);
+ mul_v3_fl(disp_sharpen, 1.0f - ss->filter_cache->sharpen_factor[vd.index]);
+
+ float disp_avg[3];
+ float avg_co[3];
+ SCULPT_neighbor_coords_average(ss, avg_co, vd.index);
+ sub_v3_v3v3(disp_avg, avg_co, vd.co);
+ mul_v3_v3fl(
+ disp_avg, disp_avg, smooth_ratio * pow2f(ss->filter_cache->sharpen_factor[vd.index]));
+ add_v3_v3v3(disp, disp_avg, disp_sharpen);
+ break;
+ }
+ }
+
+ for (int it = 0; it < 3; it++) {
+ if (!ss->filter_cache->enabled_axis[it]) {
+ disp[it] = 0.0f;
+ }
+ }
+
+ if (ELEM(filter_type, MESH_FILTER_SURFACE_SMOOTH, MESH_FILTER_SHARPEN)) {
+ madd_v3_v3v3fl(final_pos, vd.co, disp, clamp_f(fade, 0.0f, 1.0f));
+ }
+ else {
+ add_v3_v3v3(final_pos, orig_co, disp);
+ }
+ copy_v3_v3(vd.co, final_pos);
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ BKE_pbvh_node_mark_update(node);
+}
+
+static void mesh_filter_sharpen_init_factors(SculptSession *ss)
+{
+ const int totvert = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totvert; i++) {
+ float avg[3];
+ SCULPT_neighbor_coords_average(ss, avg, i);
+ ss->filter_cache->sharpen_factor[i] = len_v3v3(avg, SCULPT_vertex_co_get(ss, i));
+ }
+ float max_factor = 0.0f;
+ for (int i = 0; i < totvert; i++) {
+ if (ss->filter_cache->sharpen_factor[i] > max_factor) {
+ max_factor = ss->filter_cache->sharpen_factor[i];
+ }
+ }
+
+ max_factor = 1.0f / max_factor;
+ for (int i = 0; i < totvert; i++) {
+ ss->filter_cache->sharpen_factor[i] *= max_factor;
+ ss->filter_cache->sharpen_factor[i] = 1.0f - pow2f(1.0f - ss->filter_cache->sharpen_factor[i]);
+ }
+}
+
+static void mesh_filter_sharpen_accumulate_displacement(SculptSession *ss)
+{
+ const int totvert = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totvert; i++) {
+ zero_v3(ss->filter_cache->accum_disp[i]);
+ }
+ for (int i = 0; i < totvert; i++) {
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+ float disp_n[3];
+ sub_v3_v3v3(disp_n, SCULPT_vertex_co_get(ss, i), SCULPT_vertex_co_get(ss, ni.index));
+ mul_v3_fl(disp_n, ss->filter_cache->sharpen_factor[i]);
+ add_v3_v3(ss->filter_cache->accum_disp[ni.index], disp_n);
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ }
+}
+
+static void mesh_filter_surface_smooth_displace_task_cb(
+ void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+ PBVHVertexIter vd;
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ float fade = vd.mask ? *vd.mask : 0.0f;
+ fade = 1.0f - fade;
+ fade *= data->filter_strength;
+ if (fade == 0.0f) {
+ continue;
+ }
+
+ if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) {
+ if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) {
+ continue;
+ }
+ }
+
+ SCULPT_surface_smooth_displace_step(ss,
+ vd.co,
+ ss->filter_cache->surface_smooth_laplacian_disp,
+ vd.index,
+ ss->filter_cache->surface_smooth_current_vertex,
+ clamp_f(fade, 0.0f, 1.0f));
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ int filter_type = RNA_enum_get(op->ptr, "type");
+ float filter_strength = RNA_float_get(op->ptr, "strength");
+ const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
+
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ SCULPT_filter_cache_free(ss);
+ SCULPT_undo_push_end();
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
+ return OPERATOR_FINISHED;
+ }
+
+ if (event->type != MOUSEMOVE) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ float len = event->prevclickx - event->mval[0];
+ filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
+
+ SCULPT_vertex_random_access_init(ss);
+
+ bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets);
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false);
+
+ if (filter_type == MESH_FILTER_SHARPEN) {
+ mesh_filter_sharpen_accumulate_displacement(ss);
+ }
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = ss->filter_cache->nodes,
+ .filter_type = filter_type,
+ .filter_strength = filter_strength,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(
+ &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
+ BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings);
+
+ if (filter_type == MESH_FILTER_SURFACE_SMOOTH) {
+ BLI_task_parallel_range(0,
+ ss->filter_cache->totnode,
+ &data,
+ mesh_filter_surface_smooth_displace_task_cb,
+ &settings);
+ }
+
+ ss->filter_cache->iteration_count++;
+
+ if (ss->deform_modifiers_active || ss->shapekey_active) {
+ SCULPT_flush_stroke_deform(sd, ob, true);
+ }
+
+ /* The relax mesh filter needs the updated normals of the modified mesh after each iteration. */
+ if (ELEM(MESH_FILTER_RELAX, MESH_FILTER_RELAX_FACE_SETS)) {
+ BKE_pbvh_update_normals(ss->pbvh, ss->subdiv_ccg);
+ }
+
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ int filter_type = RNA_enum_get(op->ptr, "type");
+ SculptSession *ss = ob->sculpt;
+ PBVH *pbvh = ob->sculpt->pbvh;
+
+ int deform_axis = RNA_enum_get(op->ptr, "deform_axis");
+ if (deform_axis == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (RNA_boolean_get(op->ptr, "use_face_sets")) {
+ /* Update the active vertex */
+ float mouse[2];
+ SculptCursorGeometryInfo sgi;
+ mouse[0] = event->mval[0];
+ mouse[1] = event->mval[1];
+ SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
+ }
+
+ const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
+
+ SCULPT_vertex_random_access_init(ss);
+
+ bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets);
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false);
+
+ const int totvert = SCULPT_vertex_count_get(ss);
+ if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_pmap && !ob->sculpt->pmap) {
+ return OPERATOR_CANCELLED;
+ }
+
+ SCULPT_undo_push_begin("Mesh filter");
+
+ SCULPT_filter_cache_init(ob, sd);
+
+ if (use_face_sets) {
+ ss->filter_cache->active_face_set = SCULPT_vertex_face_set_get(ss,
+ SCULPT_active_vertex_get(ss));
+ }
+ else {
+ ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
+ }
+
+ if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_SURFACE_SMOOTH) {
+ ss->filter_cache->surface_smooth_laplacian_disp = MEM_mallocN(3 * sizeof(float) * totvert,
+ "surface smooth disp");
+ ss->filter_cache->surface_smooth_shape_preservation = RNA_float_get(
+ op->ptr, "surface_smooth_shape_preservation");
+ ss->filter_cache->surface_smooth_current_vertex = RNA_float_get(
+ op->ptr, "surface_smooth_current_vertex");
+ }
+
+ if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_SHARPEN) {
+ ss->filter_cache->sharpen_smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio");
+ ss->filter_cache->sharpen_factor = MEM_mallocN(sizeof(float) * totvert, "sharpen factor");
+ ss->filter_cache->accum_disp = MEM_mallocN(3 * sizeof(float) * totvert, "orco");
+
+ mesh_filter_sharpen_init_factors(ss);
+ }
+
+ ss->filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
+ ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
+ ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
+
+ if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_RELAX) {
+ ss->filter_cache->automask = MEM_mallocN(totvert * sizeof(float),
+ "Relax filter edge automask");
+ for (int i = 0; i < totvert; i++) {
+ ss->filter_cache->automask[i] = 1.0f;
+ }
+ SCULPT_boundary_automasking_init(
+ ob, AUTOMASK_INIT_BOUNDARY_EDGES, 1, ss->filter_cache->automask);
+ }
+
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Filter mesh";
+ ot->idname = "SCULPT_OT_mesh_filter";
+ ot->description = "Applies a filter to modify the current mesh";
+
+ /* API callbacks. */
+ ot->invoke = sculpt_mesh_filter_invoke;
+ ot->modal = sculpt_mesh_filter_modal;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* RNA. */
+ RNA_def_enum(ot->srna,
+ "type",
+ prop_mesh_filter_types,
+ MESH_FILTER_INFLATE,
+ "Filter type",
+ "Operation that is going to be applied to the mesh");
+ RNA_def_float(
+ ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f);
+ RNA_def_enum_flag(ot->srna,
+ "deform_axis",
+ prop_mesh_filter_deform_axis_items,
+ MESH_FILTER_DEFORM_X | MESH_FILTER_DEFORM_Y | MESH_FILTER_DEFORM_Z,
+ "Deform axis",
+ "Apply the deformation in the selected axis");
+ ot->prop = RNA_def_boolean(ot->srna,
+ "use_face_sets",
+ false,
+ "Use Face Sets",
+ "Apply the filter only to the Face Mask under the cursor");
+
+ /* Surface Smooth Mesh Filter properties. */
+ RNA_def_float(ot->srna,
+ "surface_smooth_shape_preservation",
+ 0.5f,
+ 0.0f,
+ 1.0f,
+ "Shape Preservation",
+ "How much of the original shape is preserved when smoothing",
+ 0.0f,
+ 1.0f);
+ RNA_def_float(ot->srna,
+ "surface_smooth_current_vertex",
+ 0.5f,
+ 0.0f,
+ 1.0f,
+ "Per Vertex Displacement",
+ "How much the position of each individual vertex influences the final result",
+ 0.0f,
+ 1.0f);
+ RNA_def_float(ot->srna,
+ "sharpen_smooth_ratio",
+ 0.35f,
+ 0.0f,
+ 1.0f,
+ "Smooth Ratio",
+ "How much smoothing is applied to polished surfaces",
+ 0.0f,
+ 1.0f);
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 5d92b202997..9b13f6e6c24 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2006 by Nicholas Bishop
@@ -24,34 +24,44 @@
#ifndef __SCULPT_INTERN_H__
#define __SCULPT_INTERN_H__
+#include "DNA_brush_types.h"
+#include "DNA_key_types.h"
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
-#include "DNA_key_types.h"
#include "BLI_bitmap.h"
+#include "BLI_gsqueue.h"
#include "BLI_threads.h"
+#include "BKE_paint.h"
#include "BKE_pbvh.h"
struct KeyBlock;
struct Object;
+struct SculptPoseIKChainSegment;
struct SculptUndoNode;
struct bContext;
-struct SculptPoseIKChainSegment;
-bool sculpt_mode_poll(struct bContext *C);
-bool sculpt_mode_poll_view3d(struct bContext *C);
+enum ePaintSymmetryFlags;
+
+bool SCULPT_mode_poll(struct bContext *C);
+bool SCULPT_mode_poll_view3d(struct bContext *C);
/* checks for a brush, not just sculpt mode */
-bool sculpt_poll(struct bContext *C);
-bool sculpt_poll_view3d(struct bContext *C);
+bool SCULPT_poll(struct bContext *C);
+bool SCULPT_poll_view3d(struct bContext *C);
/* Updates */
typedef enum SculptUpdateType {
SCULPT_UPDATE_COORDS = 1 << 0,
SCULPT_UPDATE_MASK = 1 << 1,
+ SCULPT_UPDATE_VISIBILITY = 1 << 2,
} SculptUpdateType;
+void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags);
+void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags);
+void SCULPT_flush_stroke_deform(struct Sculpt *sd, Object *ob, bool is_proxy_used);
+
/* Stroke */
typedef struct SculptCursorGeometryInfo {
@@ -60,13 +70,275 @@ typedef struct SculptCursorGeometryInfo {
float active_vertex_co[3];
} SculptCursorGeometryInfo;
-bool sculpt_stroke_get_location(struct bContext *C, float out[3], const float mouse[2]);
-bool sculpt_cursor_geometry_info_update(bContext *C,
+bool SCULPT_stroke_get_location(struct bContext *C, float out[3], const float mouse[2]);
+bool SCULPT_cursor_geometry_info_update(bContext *C,
SculptCursorGeometryInfo *out,
const float mouse[2],
bool use_sampled_normal);
-void sculpt_geometry_preview_lines_update(bContext *C, struct SculptSession *ss, float radius);
-void sculpt_pose_calc_pose_data(struct Sculpt *sd,
+void SCULPT_geometry_preview_lines_update(bContext *C, struct SculptSession *ss, float radius);
+
+void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush);
+float SCULPT_raycast_init(struct ViewContext *vc,
+ const float mouse[2],
+ float ray_start[3],
+ float ray_end[3],
+ float ray_normal[3],
+ bool original);
+
+/* Sculpt PBVH abstraction API */
+void SCULPT_vertex_random_access_init(struct SculptSession *ss);
+
+int SCULPT_vertex_count_get(struct SculptSession *ss);
+const float *SCULPT_vertex_co_get(struct SculptSession *ss, int index);
+void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3]);
+float SCULPT_vertex_mask_get(struct SculptSession *ss, int index);
+
+#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
+typedef struct SculptVertexNeighborIter {
+ /* Storage */
+ int *neighbors;
+ int size;
+ int capacity;
+ int neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
+
+ /* Internal iterator. */
+ int num_duplicates;
+ int i;
+
+ /* Public */
+ int index;
+ bool is_duplicate;
+} SculptVertexNeighborIter;
+
+void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
+ const int index,
+ const bool include_duplicates,
+ SculptVertexNeighborIter *iter);
+
+/* Iterator over neighboring vertices. */
+#define SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator) \
+ SCULPT_vertex_neighbors_get(ss, v_index, false, &neighbor_iterator); \
+ for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \
+ neighbor_iterator.i++) { \
+ neighbor_iterator.index = ni.neighbors[ni.i];
+
+/* Iterate over neighboring and duplicate vertices (for PBVH_GRIDS). Duplicates come
+ * first since they are nearest for floodfill. */
+#define SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator) \
+ SCULPT_vertex_neighbors_get(ss, v_index, true, &neighbor_iterator); \
+ for (neighbor_iterator.i = neighbor_iterator.size - 1; neighbor_iterator.i >= 0; \
+ neighbor_iterator.i--) { \
+ neighbor_iterator.index = ni.neighbors[ni.i]; \
+ neighbor_iterator.is_duplicate = (ni.i >= \
+ neighbor_iterator.size - neighbor_iterator.num_duplicates);
+
+#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator) \
+ } \
+ if (neighbor_iterator.neighbors != neighbor_iterator.neighbors_fixed) { \
+ MEM_freeN(neighbor_iterator.neighbors); \
+ } \
+ ((void)0)
+
+int SCULPT_active_vertex_get(SculptSession *ss);
+const float *SCULPT_active_vertex_co_get(SculptSession *ss);
+void SCULPT_active_vertex_normal_get(SculptSession *ss, float normal[3]);
+
+bool SCULPT_vertex_is_boundary(SculptSession *ss, const int index);
+
+/* Sculpt Visibility API */
+
+void SCULPT_vertex_visible_set(SculptSession *ss, int index, bool visible);
+bool SCULPT_vertex_visible_get(SculptSession *ss, int index);
+
+void SCULPT_visibility_sync_all_face_sets_to_vertices(struct SculptSession *ss);
+void SCULPT_visibility_sync_all_vertex_to_face_sets(struct SculptSession *ss);
+
+/* Face Sets API */
+
+int SCULPT_active_face_set_get(SculptSession *ss);
+int SCULPT_vertex_face_set_get(SculptSession *ss, int index);
+void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_set);
+
+bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set);
+bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index);
+
+int SCULPT_face_set_next_available_get(SculptSession *ss);
+
+void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible);
+bool SCULPT_vertex_all_face_sets_visible_get(SculptSession *ss, int index);
+bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, int index);
+
+void SCULPT_face_sets_visibility_invert(SculptSession *ss);
+void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible);
+
+/* Sculpt Original Data */
+typedef struct {
+ struct BMLog *bm_log;
+
+ struct SculptUndoNode *unode;
+ float (*coords)[3];
+ short (*normals)[3];
+ const float *vmasks;
+
+ /* Original coordinate, normal, and mask. */
+ const float *co;
+ const short *no;
+ float mask;
+} SculptOrigVertData;
+
+void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node);
+void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter);
+
+/* Utils. */
+void SCULPT_calc_brush_plane(struct Sculpt *sd,
+ struct Object *ob,
+ struct PBVHNode **nodes,
+ int totnode,
+ float r_area_no[3],
+ float r_area_co[3]);
+
+void SCULPT_calc_area_normal(
+ Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3]);
+
+int SCULPT_nearest_vertex_get(struct Sculpt *sd,
+ struct Object *ob,
+ const float co[3],
+ float max_distance,
+ bool use_original);
+
+int SCULPT_plane_point_side(const float co[3], const float plane[4]);
+int SCULPT_plane_trim(const struct StrokeCache *cache,
+ const struct Brush *brush,
+ const float val[3]);
+void SCULPT_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3]);
+
+float SCULPT_brush_plane_offset_get(Sculpt *sd, SculptSession *ss);
+
+ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3]);
+bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm);
+bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3],
+ const float br_co[3],
+ float radius,
+ char symm);
+bool SCULPT_is_symmetry_iteration_valid(char i, char symm);
+void SCULPT_flip_v3_by_symm_area(float v[3],
+ const ePaintSymmetryFlags symm,
+ const ePaintSymmetryAreas symmarea,
+ const float pivot[3]);
+void SCULPT_flip_quat_by_symm_area(float quat[3],
+ const ePaintSymmetryFlags symm,
+ const ePaintSymmetryAreas symmarea,
+ const float pivot[3]);
+
+/* Flood Fill. */
+typedef struct {
+ GSQueue *queue;
+ char *visited_vertices;
+} SculptFloodFill;
+
+void SCULPT_floodfill_init(struct SculptSession *ss, SculptFloodFill *flood);
+void SCULPT_floodfill_add_active(struct Sculpt *sd,
+ struct Object *ob,
+ struct SculptSession *ss,
+ SculptFloodFill *flood,
+ float radius);
+void SCULPT_floodfill_add_initial_with_symmetry(struct Sculpt *sd,
+ struct Object *ob,
+ struct SculptSession *ss,
+ SculptFloodFill *flood,
+ int index,
+ float radius);
+void SCULPT_floodfill_add_initial(SculptFloodFill *flood, int index);
+void SCULPT_floodfill_execute(
+ struct SculptSession *ss,
+ SculptFloodFill *flood,
+ bool (*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata),
+ void *userdata);
+void SCULPT_floodfill_free(SculptFloodFill *flood);
+
+/* Dynamic topology */
+
+enum eDynTopoWarnFlag {
+ DYNTOPO_WARN_VDATA = (1 << 0),
+ DYNTOPO_WARN_EDATA = (1 << 1),
+ DYNTOPO_WARN_LDATA = (1 << 2),
+ DYNTOPO_WARN_MODIFIER = (1 << 3),
+};
+
+void SCULPT_dynamic_topology_enable_ex(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob);
+void SCULPT_dynamic_topology_disable(bContext *C, struct SculptUndoNode *unode);
+void sculpt_dynamic_topology_disable_with_undo(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob);
+
+bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush);
+
+void SCULPT_dynamic_topology_triangulate(struct BMesh *bm);
+void SCULPT_dyntopo_node_layers_add(struct SculptSession *ss);
+
+enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob);
+
+void SCULPT_pbvh_clear(Object *ob);
+
+/* Automasking. */
+float SCULPT_automasking_factor_get(SculptSession *ss, int vert);
+
+void SCULPT_automasking_init(Sculpt *sd, Object *ob);
+void SCULPT_automasking_end(Object *ob);
+
+bool SCULPT_is_automasking_mode_enabled(const Sculpt *sd,
+ const Brush *br,
+ const eAutomasking_flag mode);
+bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, const Brush *br);
+
+typedef enum eBoundaryAutomaskMode {
+ AUTOMASK_INIT_BOUNDARY_EDGES = 1,
+ AUTOMASK_INIT_BOUNDARY_FACE_SETS = 2,
+} eBoundaryAutomaskMode;
+float *SCULPT_boundary_automasking_init(Object *ob,
+ eBoundaryAutomaskMode mode,
+ int propagation_steps,
+ float *automask_factor);
+
+/* Filters. */
+void SCULPT_filter_cache_init(Object *ob, Sculpt *sd);
+void SCULPT_filter_cache_free(SculptSession *ss);
+
+void SCULPT_mask_filter_smooth_apply(
+ Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, const int smooth_iterations);
+
+/* Brushes. */
+
+/* Cloth Brush. */
+void SCULPT_do_cloth_brush(struct Sculpt *sd,
+ struct Object *ob,
+ struct PBVHNode **nodes,
+ int totnode);
+void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim);
+
+void SCULPT_cloth_simulation_limits_draw(const uint gpuattr,
+ const struct Brush *brush,
+ const float obmat[4][4],
+ const float location[3],
+ const float normal[3],
+ const float rds,
+ const float line_width,
+ const float outline_col[3],
+ const float alpha);
+void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,
+ struct SculptSession *ss,
+ const float outline_col[3],
+ float outline_alpha);
+/* Pose Brush. */
+void SCULPT_do_pose_brush(struct Sculpt *sd,
+ struct Object *ob,
+ struct PBVHNode **nodes,
+ int totnode);
+void SCULPT_pose_calc_pose_data(struct Sculpt *sd,
struct Object *ob,
struct SculptSession *ss,
float initial_location[3],
@@ -74,23 +346,68 @@ void sculpt_pose_calc_pose_data(struct Sculpt *sd,
float pose_offset,
float *r_pose_origin,
float *r_pose_factor);
-
-struct SculptPoseIKChain *sculpt_pose_ik_chain_init(struct Sculpt *sd,
+void SCULPT_pose_brush_init(struct Sculpt *sd,
+ struct Object *ob,
+ struct SculptSession *ss,
+ struct Brush *br);
+struct SculptPoseIKChain *SCULPT_pose_ik_chain_init(struct Sculpt *sd,
struct Object *ob,
struct SculptSession *ss,
struct Brush *br,
const float initial_location[3],
const float radius);
-
-void sculpt_pose_ik_chain_free(struct SculptPoseIKChain *ik_chain);
-
-/* Sculpt PBVH abstraction API */
-const float *sculpt_vertex_co_get(struct SculptSession *ss, int index);
-
-/* Dynamic topology */
-void sculpt_pbvh_clear(Object *ob);
-void sculpt_dyntopo_node_layers_add(struct SculptSession *ss);
-void sculpt_dynamic_topology_disable(bContext *C, struct SculptUndoNode *unode);
+void SCULPT_pose_ik_chain_free(struct SculptPoseIKChain *ik_chain);
+
+/* Multiplane Scrape Brush. */
+void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
+void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr,
+ SculptSession *ss,
+ const float outline_col[3],
+ const float outline_alpha);
+/* Draw Face Sets Brush. */
+void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
+
+/* Smooth Brush. */
+
+void SCULPT_neighbor_average(SculptSession *ss, float avg[3], uint vert);
+void SCULPT_bmesh_neighbor_average(float avg[3], struct BMVert *v);
+
+void SCULPT_bmesh_four_neighbor_average(float avg[3], float direction[3], struct BMVert *v);
+
+void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int index);
+float SCULPT_neighbor_mask_average(SculptSession *ss, int index);
+
+void SCULPT_smooth(Sculpt *sd,
+ Object *ob,
+ PBVHNode **nodes,
+ const int totnode,
+ float bstrength,
+ const bool smooth_mask);
+void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
+
+/* Surface Smooth Brush. */
+
+void SCULPT_surface_smooth_laplacian_step(SculptSession *ss,
+ float *disp,
+ const float co[3],
+ float (*laplacian_disp)[3],
+ const int v_index,
+ const float origco[3],
+ const float alpha);
+void SCULPT_surface_smooth_displace_step(SculptSession *ss,
+ float *co,
+ float (*laplacian_disp)[3],
+ const int v_index,
+ const float beta,
+ const float fade);
+void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
+
+/* Slide/Relax */
+void SCULPT_relax_vertex(struct SculptSession *ss,
+ struct PBVHVertexIter *vd,
+ float factor,
+ bool filter_boundary_face_sets,
+ float *r_final_pos);
/* Undo */
@@ -102,8 +419,26 @@ typedef enum {
SCULPT_UNDO_DYNTOPO_END,
SCULPT_UNDO_DYNTOPO_SYMMETRIZE,
SCULPT_UNDO_GEOMETRY,
+ SCULPT_UNDO_FACE_SETS,
} SculptUndoType;
+/* Storage of geometry for the undo node.
+ * Is used as a storage for either original or modified geometry. */
+typedef struct SculptUndoNodeGeometry {
+ /* Is used for sanity check, helping with ensuring that two and only two
+ * geometry pushes happened in the undo stack. */
+ bool is_initialized;
+
+ CustomData vdata;
+ CustomData edata;
+ CustomData ldata;
+ CustomData pdata;
+ int totvert;
+ int totedge;
+ int totloop;
+ int totpoly;
+} SculptUndoNodeGeometry;
+
typedef struct SculptUndoNode {
struct SculptUndoNode *next, *prev;
@@ -137,20 +472,26 @@ typedef struct SculptUndoNode {
/* shape keys */
char shapeName[sizeof(((KeyBlock *)0))->name];
- /* geometry modification operations and bmesh enter data */
- CustomData geom_vdata;
- CustomData geom_edata;
- CustomData geom_ldata;
- CustomData geom_pdata;
- int geom_totvert;
- int geom_totedge;
- int geom_totloop;
- int geom_totpoly;
+ /* Geometry modification operations.
+ *
+ * Original geometry is stored before some modification is run and is used to restore state of
+ * the object when undoing the operation
+ *
+ * Modified geometry is stored after the modification and is used to redo the modification. */
+ bool geometry_clear_pbvh;
+ SculptUndoNodeGeometry geometry_original;
+ SculptUndoNodeGeometry geometry_modified;
+
+ /* Geometry at the bmesh enter moment. */
+ SculptUndoNodeGeometry geometry_bmesh_enter;
/* pivot */
float pivot_pos[3];
float pivot_rot[4];
+ /* Sculpt Face Sets */
+ int *face_sets;
+
size_t undo_size;
} SculptUndoNode;
@@ -202,11 +543,22 @@ typedef struct SculptThreadedTaskData {
float (*mat)[4];
float (*vertCos)[3];
+ /* X and Z vectors aligned to the stroke direction for operations where perpendicular vectors to
+ * the stroke direction are needed. */
+ float (*stroke_xz)[3];
+
int filter_type;
float filter_strength;
bool use_area_cos;
bool use_area_nos;
+
+ /* 0=towards view, 1=flipped */
+ float (*area_cos)[3];
+ float (*area_nos)[3];
+ int *count_no;
+ int *count_co;
+
bool any_vertex_sampled;
float *prev_mask;
@@ -221,17 +573,25 @@ typedef struct SculptThreadedTaskData {
float max_distance_squared;
float nearest_vertex_search_co[3];
+ /* Stabilized strength for the Clay Thumb brush. */
+ float clay_strength;
+
int mask_expand_update_it;
bool mask_expand_invert_mask;
bool mask_expand_use_normals;
bool mask_expand_keep_prev_mask;
+ bool mask_expand_create_face_set;
float transform_mats[8][4][4];
+ float cloth_time_step;
+
float dirty_mask_min;
float dirty_mask_max;
bool dirty_mask_dirty_only;
+ int face_set;
+
ThreadMutex mutex;
} SculptThreadedTaskData;
@@ -239,6 +599,7 @@ typedef struct SculptThreadedTaskData {
/*************** Brush testing declarations ****************/
typedef struct SculptBrushTest {
float radius_squared;
+ float radius;
float location[3];
float dist;
int mirror_symmetry_pass;
@@ -273,33 +634,36 @@ typedef struct {
struct DistRayAABB_Precalc *dist_ray_to_aabb_precalc;
} SculptSearchCircleData;
-void sculpt_brush_test_init(struct SculptSession *ss, SculptBrushTest *test);
-bool sculpt_brush_test_sphere(SculptBrushTest *test, const float co[3]);
-bool sculpt_brush_test_sphere_sq(SculptBrushTest *test, const float co[3]);
-bool sculpt_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3]);
-bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float local[4][4]);
-bool sculpt_brush_test_circle_sq(SculptBrushTest *test, const float co[3]);
-bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v);
-bool sculpt_search_circle_cb(PBVHNode *node, void *data_v);
-
-SculptBrushTestFn sculpt_brush_test_init_with_falloff_shape(SculptSession *ss,
+void SCULPT_brush_test_init(struct SculptSession *ss, SculptBrushTest *test);
+bool SCULPT_brush_test_sphere(SculptBrushTest *test, const float co[3]);
+bool SCULPT_brush_test_sphere_sq(SculptBrushTest *test, const float co[3]);
+bool SCULPT_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3]);
+bool SCULPT_brush_test_cube(SculptBrushTest *test,
+ const float co[3],
+ const float local[4][4],
+ const float roundness);
+bool SCULPT_brush_test_circle_sq(SculptBrushTest *test, const float co[3]);
+bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v);
+bool SCULPT_search_circle_cb(PBVHNode *node, void *data_v);
+
+SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss,
SculptBrushTest *test,
char falloff_shape);
-const float *sculpt_brush_frontface_normal_from_falloff_shape(SculptSession *ss,
+const float *SCULPT_brush_frontface_normal_from_falloff_shape(SculptSession *ss,
char falloff_shape);
-float tex_strength(struct SculptSession *ss,
- const struct Brush *br,
- const float point[3],
- const float len,
- const short vno[3],
- const float fno[3],
- const float mask,
- const int vertex_index,
- const int thread_id);
+float SCULPT_brush_strength_factor(struct SculptSession *ss,
+ const struct Brush *br,
+ const float point[3],
+ const float len,
+ const short vno[3],
+ const float fno[3],
+ const float mask,
+ const int vertex_index,
+ const int thread_id);
/* just for vertex paint. */
-bool sculpt_pbvh_calc_area_normal(const struct Brush *brush,
+bool SCULPT_pbvh_calc_area_normal(const struct Brush *brush,
Object *ob,
PBVHNode **nodes,
int totnode,
@@ -312,6 +676,8 @@ bool sculpt_pbvh_calc_area_normal(const struct Brush *brush,
* For descriptions of these settings, check the operator properties.
*/
+#define SCULPT_CLAY_STABILIZER_LEN 10
+
typedef struct StrokeCache {
/* Invariants */
float initial_radius;
@@ -328,6 +694,10 @@ typedef struct StrokeCache {
float location[3];
float last_location[3];
+ /* Used for alternating between deformation in brushes that need to apply different ones to
+ * achieve certain effects. */
+ int iteration_count;
+
/* Original pixel radius with the pressure curve applied for dyntopo detail size */
float dyntopo_pixel_radius;
@@ -360,6 +730,9 @@ typedef struct StrokeCache {
bool is_rake_rotation_valid;
struct SculptRakeData rake_data;
+ /* Face Sets */
+ int paint_face_set;
+
/* Symmetry index between 0 and 7 bit combo 0 is Brush only;
* 1 is X mirror; 2 is Y mirror; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
int symmetry;
@@ -390,6 +763,27 @@ typedef struct StrokeCache {
/* Pose brush */
struct SculptPoseIKChain *pose_ik_chain;
+ /* Clay Thumb brush */
+ /* Angle of the front tilting plane of the brush to simulate clay accumulation. */
+ float clay_thumb_front_angle;
+ /* Stores pressure samples to get an stabilized strength and radius variation. */
+ float clay_pressure_stabilizer[SCULPT_CLAY_STABILIZER_LEN];
+ int clay_pressure_stabilizer_index;
+
+ /* Cloth brush */
+ struct SculptClothSimulation *cloth_sim;
+ float initial_location[3];
+ float true_initial_location[3];
+ float initial_normal[3];
+ float true_initial_normal[3];
+
+ /* Surface Smooth Brush */
+ /* Stores the displacement produced by the laplacian step of HC smooth. */
+ float (*surface_smooth_laplacian_disp)[3];
+
+ /* Layer brush */
+ float *layer_displacement_factor;
+
float vertex_rotation; /* amount to rotate the vertices when using rotate brush */
struct Dial *dial;
@@ -407,7 +801,7 @@ typedef struct StrokeCache {
float *automask;
float stroke_local_mat[4][4];
- float multiplane_scrape_sampled_angle;
+ float multiplane_scrape_angle;
rcti previous_r; /* previous redraw rectangle */
rcti current_r; /* current redraw rectangle */
@@ -418,6 +812,20 @@ typedef struct FilterCache {
bool enabled_axis[3];
int random_seed;
+ /* Used for alternating between filter operations in filters that need to apply different ones to
+ * achieve certain effects. */
+ int iteration_count;
+
+ /* Stores the displacement produced by the laplacian step of HC smooth. */
+ float (*surface_smooth_laplacian_disp)[3];
+ float surface_smooth_shape_preservation;
+ float surface_smooth_current_vertex;
+
+ /* Sharpen mesh filter. */
+ float sharpen_smooth_ratio;
+ float *sharpen_factor;
+ float (*accum_disp)[3];
+
/* unmasked nodes */
PBVHNode **nodes;
int totnode;
@@ -430,23 +838,65 @@ typedef struct FilterCache {
float *edge_factor;
float *prev_mask;
float mask_expand_initial_co[3];
+
+ /* Used to prevent undesired results on certain mesh filters. */
+ float *automask;
+
+ int new_face_set;
+ int *prev_face_set;
+
+ int active_face_set;
} FilterCache;
-void sculpt_cache_calc_brushdata_symm(StrokeCache *cache,
+void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
const char symm,
const char axis,
const float angle);
-void sculpt_cache_free(StrokeCache *cache);
+void SCULPT_cache_free(StrokeCache *cache);
+
+SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type);
+SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node);
+SculptUndoNode *SCULPT_undo_get_first_node(void);
+void SCULPT_undo_push_begin(const char *name);
+void SCULPT_undo_push_end(void);
+void SCULPT_undo_push_end_ex(const bool use_nested_undo);
+
+void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]);
+
+void SCULPT_update_object_bounding_box(struct Object *ob);
+
+bool SCULPT_get_redraw_rect(struct ARegion *region,
+ struct RegionView3D *rv3d,
+ Object *ob,
+ rcti *rect);
+
+/* Operators. */
+
+/* Face Sets. */
+void SCULPT_OT_face_sets_randomize_colors(struct wmOperatorType *ot);
+void SCULPT_OT_face_sets_change_visibility(struct wmOperatorType *ot);
+void SCULPT_OT_face_sets_init(struct wmOperatorType *ot);
+void SCULPT_OT_face_sets_create(struct wmOperatorType *ot);
+
+/* Transform. */
+void SCULPT_OT_set_pivot_position(struct wmOperatorType *ot);
+
+/* Mesh Filter. */
+void SCULPT_OT_mesh_filter(struct wmOperatorType *ot);
-SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type);
-SculptUndoNode *sculpt_undo_get_node(PBVHNode *node);
-void sculpt_undo_push_begin(const char *name);
-void sculpt_undo_push_end(void);
+/* Mask filter and Dirty Mask. */
+void SCULPT_OT_mask_filter(struct wmOperatorType *ot);
+void SCULPT_OT_dirty_mask(struct wmOperatorType *ot);
-void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]);
+/* Mask and Face Sets Expand. */
+void SCULPT_OT_mask_expand(struct wmOperatorType *ot);
-void sculpt_update_object_bounding_box(struct Object *ob);
+/* Detail size. */
+void SCULPT_OT_detail_flood_fill(struct wmOperatorType *ot);
+void SCULPT_OT_sample_detail_size(struct wmOperatorType *ot);
+void SCULPT_OT_set_detail_size(struct wmOperatorType *ot);
-bool sculpt_get_redraw_rect(struct ARegion *ar, struct RegionView3D *rv3d, Object *ob, rcti *rect);
+/* Dyntopo. */
+void SCULPT_OT_dynamic_topology_toggle(struct wmOperatorType *ot);
#endif
diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
new file mode 100644
index 00000000000..cbb198e14a3
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
@@ -0,0 +1,526 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_ccg.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_multires.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_view3d.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
+
+ MEM_freeN(op->customdata);
+
+ for (int n = 0; n < ss->filter_cache->totnode; n++) {
+ PBVHNode *node = ss->filter_cache->nodes[n];
+ if (create_face_set) {
+ for (int i = 0; i < ss->totfaces; i++) {
+ ss->face_sets[i] = ss->filter_cache->prev_face_set[i];
+ }
+ }
+ else {
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ *vd.mask = ss->filter_cache->prev_mask[vd.index];
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+
+ BKE_pbvh_node_mark_redraw(node);
+ }
+
+ if (!create_face_set) {
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
+ }
+ SCULPT_filter_cache_free(ss);
+ SCULPT_undo_push_end();
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
+ ED_workspace_status_text(C, NULL);
+}
+
+static void sculpt_expand_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+ PBVHVertexIter vd;
+ int update_it = data->mask_expand_update_it;
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
+ {
+ int vi = vd.index;
+ float final_mask = *vd.mask;
+ if (data->mask_expand_use_normals) {
+ if (ss->filter_cache->normal_factor[SCULPT_active_vertex_get(ss)] <
+ ss->filter_cache->normal_factor[vd.index]) {
+ final_mask = 1.0f;
+ }
+ else {
+ final_mask = 0.0f;
+ }
+ }
+ else {
+ if (ss->filter_cache->mask_update_it[vi] <= update_it &&
+ ss->filter_cache->mask_update_it[vi] != 0) {
+ final_mask = 1.0f;
+ }
+ else {
+ final_mask = 0.0f;
+ }
+ }
+
+ if (data->mask_expand_create_face_set) {
+ if (final_mask == 1.0f) {
+ SCULPT_vertex_face_set_set(ss, vd.index, ss->filter_cache->new_face_set);
+ }
+ BKE_pbvh_node_mark_redraw(node);
+ }
+ else {
+
+ if (data->mask_expand_keep_prev_mask) {
+ final_mask = MAX2(ss->filter_cache->prev_mask[vd.index], final_mask);
+ }
+
+ if (data->mask_expand_invert_mask) {
+ final_mask = 1.0f - final_mask;
+ }
+
+ if (*vd.mask != final_mask) {
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ *vd.mask = final_mask;
+ BKE_pbvh_node_mark_update_mask(node);
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ ARegion *region = CTX_wm_region(C);
+ float prevclick_f[2];
+ copy_v2_v2(prevclick_f, op->customdata);
+ int prevclick[2] = {(int)prevclick_f[0], (int)prevclick_f[1]};
+ int len = (int)len_v2v2_int(prevclick, event->mval);
+ len = abs(len);
+ int mask_speed = RNA_int_get(op->ptr, "mask_speed");
+ int mask_expand_update_it = len / mask_speed;
+ mask_expand_update_it = mask_expand_update_it + 1;
+
+ const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
+
+ if (RNA_boolean_get(op->ptr, "use_cursor")) {
+ SculptCursorGeometryInfo sgi;
+ float mouse[2];
+ mouse[0] = event->mval[0];
+ mouse[1] = event->mval[1];
+ SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
+ mask_expand_update_it = ss->filter_cache->mask_update_it[(int)SCULPT_active_vertex_get(ss)];
+ }
+
+ if ((event->type == EVT_ESCKEY && event->val == KM_PRESS) ||
+ (event->type == RIGHTMOUSE && event->val == KM_PRESS)) {
+ /* Returning OPERATOR_CANCELLED will leak memory due to not finishing
+ * undo. Better solution could be to make paint_mesh_restore_co work
+ * for this case. */
+ sculpt_mask_expand_cancel(C, op);
+ return OPERATOR_FINISHED;
+ }
+
+ if ((event->type == LEFTMOUSE && event->val == KM_RELEASE) ||
+ (event->type == EVT_RETKEY && event->val == KM_PRESS) ||
+ (event->type == EVT_PADENTER && event->val == KM_PRESS)) {
+
+ /* Smooth iterations. */
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false);
+ const int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations");
+ SCULPT_mask_filter_smooth_apply(
+ sd, ob, ss->filter_cache->nodes, ss->filter_cache->totnode, smooth_iterations);
+
+ /* Pivot position. */
+ if (RNA_boolean_get(op->ptr, "update_pivot")) {
+ const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ const float threshold = 0.2f;
+ float avg[3];
+ int total = 0;
+ zero_v3(avg);
+
+ for (int n = 0; n < ss->filter_cache->totnode; n++) {
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, ss->filter_cache->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ const float mask = (vd.mask) ? *vd.mask : 0.0f;
+ if (mask < (0.5f + threshold) && mask > (0.5f - threshold)) {
+ if (SCULPT_check_vertex_pivot_symmetry(
+ vd.co, ss->filter_cache->mask_expand_initial_co, symm)) {
+ add_v3_v3(avg, vd.co);
+ total++;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ copy_v3_v3(ss->pivot_pos, avg);
+ }
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ }
+
+ MEM_freeN(op->customdata);
+
+ for (int i = 0; i < ss->filter_cache->totnode; i++) {
+ BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]);
+ }
+
+ SCULPT_filter_cache_free(ss);
+
+ SCULPT_undo_push_end();
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
+ ED_workspace_status_text(C, NULL);
+ return OPERATOR_FINISHED;
+ }
+
+ /* When pressing Ctrl, expand directly to the max number of iterations. This allows to flood fill
+ * mask and face sets by connectivity directly. */
+ if (event->ctrl) {
+ mask_expand_update_it = ss->filter_cache->mask_update_last_it - 1;
+ }
+
+ if (!ELEM(event->type, MOUSEMOVE, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ if (mask_expand_update_it == ss->filter_cache->mask_update_current_it) {
+ ED_region_tag_redraw(region);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ if (mask_expand_update_it < ss->filter_cache->mask_update_last_it) {
+
+ if (create_face_set) {
+ for (int i = 0; i < ss->totfaces; i++) {
+ ss->face_sets[i] = ss->filter_cache->prev_face_set[i];
+ }
+ }
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = ss->filter_cache->nodes,
+ .mask_expand_update_it = mask_expand_update_it,
+ .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"),
+ .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
+ .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
+ .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"),
+ };
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(
+ &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
+ BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
+ ss->filter_cache->mask_update_current_it = mask_expand_update_it;
+ }
+
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+typedef struct MaskExpandFloodFillData {
+ float original_normal[3];
+ float edge_sensitivity;
+ bool use_normals;
+} MaskExpandFloodFillData;
+
+static bool mask_expand_floodfill_cb(
+ SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
+{
+ MaskExpandFloodFillData *data = userdata;
+
+ if (!is_duplicate) {
+ int to_it = ss->filter_cache->mask_update_it[from_v] + 1;
+ ss->filter_cache->mask_update_it[to_v] = to_it;
+ if (to_it > ss->filter_cache->mask_update_last_it) {
+ ss->filter_cache->mask_update_last_it = to_it;
+ }
+
+ if (data->use_normals) {
+ float current_normal[3], prev_normal[3];
+ SCULPT_vertex_normal_get(ss, to_v, current_normal);
+ SCULPT_vertex_normal_get(ss, from_v, prev_normal);
+ const float from_edge_factor = ss->filter_cache->edge_factor[from_v];
+ ss->filter_cache->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) *
+ from_edge_factor;
+ ss->filter_cache->normal_factor[to_v] = dot_v3v3(data->original_normal, current_normal) *
+ powf(from_edge_factor, data->edge_sensitivity);
+ CLAMP(ss->filter_cache->normal_factor[to_v], 0.0f, 1.0f);
+ }
+ }
+ else {
+ /* PBVH_GRIDS duplicate handling. */
+ ss->filter_cache->mask_update_it[to_v] = ss->filter_cache->mask_update_it[from_v];
+ if (data->use_normals) {
+ ss->filter_cache->edge_factor[to_v] = ss->filter_cache->edge_factor[from_v];
+ ss->filter_cache->normal_factor[to_v] = ss->filter_cache->normal_factor[from_v];
+ }
+ }
+
+ return true;
+}
+
+static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ PBVH *pbvh = ob->sculpt->pbvh;
+
+ const bool use_normals = RNA_boolean_get(op->ptr, "use_normals");
+ const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
+
+ SculptCursorGeometryInfo sgi;
+ float mouse[2];
+ mouse[0] = event->mval[0];
+ mouse[1] = event->mval[1];
+
+ SCULPT_vertex_random_access_init(ss);
+
+ op->customdata = MEM_mallocN(2 * sizeof(float), "initial mouse position");
+ copy_v2_v2(op->customdata, mouse);
+
+ SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
+
+ int vertex_count = SCULPT_vertex_count_get(ss);
+
+ ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
+
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &ss->filter_cache->nodes, &ss->filter_cache->totnode);
+
+ SCULPT_undo_push_begin("Mask Expand");
+
+ if (create_face_set) {
+ SCULPT_undo_push_node(ob, ss->filter_cache->nodes[0], SCULPT_UNDO_FACE_SETS);
+ for (int i = 0; i < ss->filter_cache->totnode; i++) {
+ BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]);
+ }
+ }
+ else {
+ for (int i = 0; i < ss->filter_cache->totnode; i++) {
+ SCULPT_undo_push_node(ob, ss->filter_cache->nodes[i], SCULPT_UNDO_MASK);
+ BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]);
+ }
+ }
+
+ ss->filter_cache->mask_update_it = MEM_callocN(sizeof(int) * vertex_count,
+ "mask update iteration");
+ if (use_normals) {
+ ss->filter_cache->normal_factor = MEM_callocN(sizeof(float) * vertex_count,
+ "mask update normal factor");
+ ss->filter_cache->edge_factor = MEM_callocN(sizeof(float) * vertex_count,
+ "mask update normal factor");
+ for (int i = 0; i < vertex_count; i++) {
+ ss->filter_cache->edge_factor[i] = 1.0f;
+ }
+ }
+
+ if (create_face_set) {
+ ss->filter_cache->prev_face_set = MEM_callocN(sizeof(float) * ss->totfaces, "prev face mask");
+ for (int i = 0; i < ss->totfaces; i++) {
+ ss->filter_cache->prev_face_set[i] = ss->face_sets[i];
+ }
+ ss->filter_cache->new_face_set = SCULPT_face_set_next_available_get(ss);
+ }
+ else {
+ ss->filter_cache->prev_mask = MEM_callocN(sizeof(float) * vertex_count, "prev mask");
+ for (int i = 0; i < vertex_count; i++) {
+ ss->filter_cache->prev_mask[i] = SCULPT_vertex_mask_get(ss, i);
+ }
+ }
+
+ ss->filter_cache->mask_update_last_it = 1;
+ ss->filter_cache->mask_update_current_it = 1;
+ ss->filter_cache->mask_update_it[SCULPT_active_vertex_get(ss)] = 0;
+
+ copy_v3_v3(ss->filter_cache->mask_expand_initial_co, SCULPT_active_vertex_co_get(ss));
+
+ SculptFloodFill flood;
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_active(sd, ob, ss, &flood, FLT_MAX);
+
+ MaskExpandFloodFillData fdata = {
+ .use_normals = use_normals,
+ .edge_sensitivity = RNA_int_get(op->ptr, "edge_sensitivity"),
+ };
+ SCULPT_active_vertex_normal_get(ss, fdata.original_normal);
+ SCULPT_floodfill_execute(ss, &flood, mask_expand_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ if (use_normals) {
+ for (int repeat = 0; repeat < 2; repeat++) {
+ for (int i = 0; i < vertex_count; i++) {
+ float avg = 0.0f;
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+ avg += ss->filter_cache->normal_factor[ni.index];
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ ss->filter_cache->normal_factor[i] = avg / ni.size;
+ }
+ }
+
+ MEM_SAFE_FREE(ss->filter_cache->edge_factor);
+ }
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = ss->filter_cache->nodes,
+ .mask_expand_update_it = 0,
+ .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"),
+ .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
+ .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
+ .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"),
+ };
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(
+ &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
+ BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
+
+ const char *status_str = TIP_(
+ "Move the mouse to expand the mask from the active vertex. LMB: confirm mask, ESC/RMB: "
+ "cancel");
+ ED_workspace_status_text(C, status_str);
+
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void SCULPT_OT_mask_expand(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Mask Expand";
+ ot->idname = "SCULPT_OT_mask_expand";
+ ot->description = "Expands a mask from the initial active vertex under the cursor";
+
+ /* API callbacks. */
+ ot->invoke = sculpt_mask_expand_invoke;
+ ot->modal = sculpt_mask_expand_modal;
+ ot->cancel = sculpt_mask_expand_cancel;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->prop = RNA_def_boolean(ot->srna, "invert", true, "Invert", "Invert the new mask");
+ ot->prop = RNA_def_boolean(
+ ot->srna, "use_cursor", true, "Use Cursor", "Expand the mask to the cursor position");
+ ot->prop = RNA_def_boolean(ot->srna,
+ "update_pivot",
+ true,
+ "Update Pivot Position",
+ "Set the pivot position to the mask border after creating the mask");
+ ot->prop = RNA_def_int(ot->srna, "smooth_iterations", 2, 0, 10, "Smooth iterations", "", 0, 10);
+ ot->prop = RNA_def_int(ot->srna, "mask_speed", 5, 1, 10, "Mask speed", "", 1, 10);
+
+ ot->prop = RNA_def_boolean(ot->srna,
+ "use_normals",
+ true,
+ "Use Normals",
+ "Generate the mask using the normals and curvature of the model");
+ ot->prop = RNA_def_boolean(ot->srna,
+ "keep_previous_mask",
+ false,
+ "Keep Previous Mask",
+ "Generate the new mask on top of the current one");
+ ot->prop = RNA_def_int(ot->srna,
+ "edge_sensitivity",
+ 300,
+ 0,
+ 2000,
+ "Edge Detection Sensitivity",
+ "Sensitivity for expanding the mask across sculpted sharp edges when "
+ "using normals to generate the mask",
+ 0,
+ 2000);
+ ot->prop = RNA_def_boolean(ot->srna,
+ "create_face_set",
+ false,
+ "Expand Face Mask",
+ "Expand a new Face Mask instead of the sculpt mask");
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
new file mode 100644
index 00000000000..f3327706102
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
@@ -0,0 +1,464 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_ccg.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_multires.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+typedef struct MultiplaneScrapeSampleData {
+ float area_cos[2][3];
+ float area_nos[2][3];
+ int area_count[2];
+} MultiplaneScrapeSampleData;
+
+static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ MultiplaneScrapeSampleData *mssd = tls->userdata_chunk;
+ float(*mat)[4] = data->mat;
+
+ PBVHVertexIter vd;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ /* Apply the brush normal radius to the test before sampling. */
+ float test_radius = sqrtf(test.radius_squared);
+ test_radius *= brush->normal_radius_factor;
+ test.radius_squared = test_radius * test_radius;
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ float local_co[3];
+ float normal[3];
+ if (vd.no) {
+ normal_short_to_float_v3(normal, vd.no);
+ }
+ else {
+ copy_v3_v3(normal, vd.fno);
+ }
+ mul_v3_m4v3(local_co, mat, vd.co);
+ /* Use the brush falloff to weight the sampled normals. */
+ const float fade = SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ /* Sample the normal and area of the +X and -X axis individually. */
+ if (local_co[0] > 0.0f) {
+ madd_v3_v3fl(mssd->area_nos[0], normal, fade);
+ add_v3_v3(mssd->area_cos[0], vd.co);
+ mssd->area_count[0]++;
+ }
+ else {
+ madd_v3_v3fl(mssd->area_nos[1], normal, fade);
+ add_v3_v3(mssd->area_cos[1], vd.co);
+ mssd->area_count[1]++;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+}
+
+static void calc_multiplane_scrape_surface_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
+{
+ MultiplaneScrapeSampleData *join = chunk_join;
+ MultiplaneScrapeSampleData *mssd = chunk;
+
+ add_v3_v3(join->area_cos[0], mssd->area_cos[0]);
+ add_v3_v3(join->area_cos[1], mssd->area_cos[1]);
+
+ add_v3_v3(join->area_nos[0], mssd->area_nos[0]);
+ add_v3_v3(join->area_nos[1], mssd->area_nos[1]);
+
+ join->area_count[0] += mssd->area_count[0];
+ join->area_count[1] += mssd->area_count[1];
+}
+
+static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ float(*mat)[4] = data->mat;
+ float(*scrape_planes)[4] = data->multiplane_scrape_planes;
+
+ float angle = data->multiplane_scrape_angle;
+
+ PBVHVertexIter vd;
+ float(*proxy)[3];
+ const float bstrength = fabsf(ss->cache->bstrength);
+
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ float local_co[3];
+ bool deform = false;
+
+ mul_v3_m4v3(local_co, mat, vd.co);
+
+ if (local_co[0] > 0.0f) {
+ deform = !SCULPT_plane_point_side(vd.co, scrape_planes[0]);
+ }
+ else {
+ deform = !SCULPT_plane_point_side(vd.co, scrape_planes[1]);
+ }
+
+ if (angle < 0.0f) {
+ deform = true;
+ }
+
+ if (deform) {
+ float intr[3];
+ float val[3];
+
+ if (local_co[0] > 0.0f) {
+ closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co);
+ }
+ else {
+ closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co);
+ }
+
+ sub_v3_v3v3(val, intr, vd.co);
+ if (SCULPT_plane_trim(ss->cache, brush, val)) {
+ /* Deform the local space along the Y axis to avoid artifacts on curved strokes. */
+ /* This produces a not round brush tip. */
+ local_co[1] *= 2.0f;
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ len_v3(local_co),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ mul_v3_v3fl(proxy[vd.i], val, fade);
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+/* Public functions. */
+
+/* Main Brush Function. */
+void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ const bool flip = (ss->cache->bstrength < 0.0f);
+ const float radius = flip ? -ss->cache->radius : ss->cache->radius;
+ const float offset = SCULPT_brush_plane_offset_get(sd, ss);
+ const float displace = -radius * offset;
+
+ /* The sculpt-plane normal (whatever its set to) */
+ float area_no_sp[3];
+
+ /* Geometry normal. */
+ float area_no[3];
+ float area_co[3];
+
+ float temp[3];
+ float mat[4][4];
+
+ SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
+
+ if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
+ SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no);
+ }
+ else {
+ copy_v3_v3(area_no, area_no_sp);
+ }
+
+ /* Delay the first daub because grab delta is not setup. */
+ if (ss->cache->first_time) {
+ ss->cache->multiplane_scrape_angle = 0.0f;
+ return;
+ }
+
+ if (is_zero_v3(ss->cache->grab_delta_symmetry)) {
+ return;
+ }
+
+ mul_v3_v3v3(temp, area_no_sp, ss->cache->scale);
+ mul_v3_fl(temp, displace);
+ add_v3_v3(area_co, temp);
+
+ /* Init brush local space matrix. */
+ cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
+ mat[0][3] = 0.0f;
+ cross_v3_v3v3(mat[1], area_no, mat[0]);
+ mat[1][3] = 0.0f;
+ copy_v3_v3(mat[2], area_no);
+ mat[2][3] = 0.0f;
+ copy_v3_v3(mat[3], ss->cache->location);
+ mat[3][3] = 1.0f;
+ normalize_m4(mat);
+ invert_m4(mat);
+
+ /* Update matrix for the cursor preview. */
+ if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0) {
+ copy_m4_m4(ss->cache->stroke_local_mat, mat);
+ }
+
+ /* Dynamic mode. */
+
+ if (brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_DYNAMIC) {
+ /* Sample the individual normal and area center of the two areas at both sides of the cursor.
+ */
+ SculptThreadedTaskData sample_data = {
+ .sd = NULL,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .totnode = totnode,
+ .mat = mat,
+ };
+
+ MultiplaneScrapeSampleData mssd = {{{0}}};
+
+ TaskParallelSettings sample_settings;
+ BKE_pbvh_parallel_range_settings(&sample_settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ sample_settings.func_reduce = calc_multiplane_scrape_surface_reduce;
+ sample_settings.userdata_chunk = &mssd;
+ sample_settings.userdata_chunk_size = sizeof(MultiplaneScrapeSampleData);
+
+ BLI_task_parallel_range(
+ 0, totnode, &sample_data, calc_multiplane_scrape_surface_task_cb, &sample_settings);
+
+ float sampled_plane_normals[2][3];
+ float sampled_plane_co[2][3];
+ float sampled_cv[2][3];
+ float mid_co[3];
+
+ /* Use the area center of both planes to detect if we are sculpting along a concave or convex
+ * edge. */
+ mul_v3_v3fl(sampled_plane_co[0], mssd.area_cos[0], 1.0f / (float)mssd.area_count[0]);
+ mul_v3_v3fl(sampled_plane_co[1], mssd.area_cos[1], 1.0f / (float)mssd.area_count[1]);
+ mid_v3_v3v3(mid_co, sampled_plane_co[0], sampled_plane_co[1]);
+
+ /* Calculate the scrape planes angle based on the sampled normals. */
+ mul_v3_v3fl(sampled_plane_normals[0], mssd.area_nos[0], 1.0f / (float)mssd.area_count[0]);
+ mul_v3_v3fl(sampled_plane_normals[1], mssd.area_nos[1], 1.0f / (float)mssd.area_count[1]);
+ normalize_v3(sampled_plane_normals[0]);
+ normalize_v3(sampled_plane_normals[1]);
+
+ float sampled_angle = angle_v3v3(sampled_plane_normals[0], sampled_plane_normals[1]);
+ copy_v3_v3(sampled_cv[0], area_no);
+ sub_v3_v3v3(sampled_cv[1], ss->cache->location, mid_co);
+
+ sampled_angle += DEG2RADF(brush->multiplane_scrape_angle) * ss->cache->pressure;
+
+ /* Invert the angle if we are sculpting along a concave edge. */
+ if (dot_v3v3(sampled_cv[0], sampled_cv[1]) < 0.0f) {
+ sampled_angle = -sampled_angle;
+ }
+
+ /* In dynamic mode, set the angle to 0 when inverting the brush, so you can trim plane
+ * surfaces without changing the brush. */
+ if (flip) {
+ sampled_angle = 0.0f;
+ }
+ else {
+ copy_v3_v3(area_co, ss->cache->location);
+ }
+
+ /* Interpolate between the previous and new sampled angles to avoid artifacts when if angle
+ * difference between two samples is too big. */
+ ss->cache->multiplane_scrape_angle = interpf(
+ RAD2DEGF(sampled_angle), ss->cache->multiplane_scrape_angle, 0.2f);
+ }
+ else {
+
+ /* Standard mode: Scrape with the brush property fixed angle. */
+ copy_v3_v3(area_co, ss->cache->location);
+ ss->cache->multiplane_scrape_angle = brush->multiplane_scrape_angle;
+ if (flip) {
+ ss->cache->multiplane_scrape_angle *= -1.0f;
+ }
+ }
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .mat = mat,
+ .multiplane_scrape_angle = ss->cache->multiplane_scrape_angle,
+ };
+
+ /* Calculate the final left and right scrape planes. */
+ float plane_no[3];
+ float plane_no_rot[3];
+ float y_axis[3] = {0.0f, 1.0f, 0.0f};
+ float mat_inv[4][4];
+ invert_m4_m4(mat_inv, mat);
+
+ mul_v3_mat3_m4v3(plane_no, mat, area_no);
+ rotate_v3_v3v3fl(
+ plane_no_rot, plane_no, y_axis, DEG2RADF(-ss->cache->multiplane_scrape_angle * 0.5f));
+ mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot);
+ normalize_v3(plane_no);
+ plane_from_point_normal_v3(data.multiplane_scrape_planes[1], area_co, plane_no);
+
+ mul_v3_mat3_m4v3(plane_no, mat, area_no);
+ rotate_v3_v3v3fl(
+ plane_no_rot, plane_no, y_axis, DEG2RADF(ss->cache->multiplane_scrape_angle * 0.5f));
+ mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot);
+ normalize_v3(plane_no);
+ plane_from_point_normal_v3(data.multiplane_scrape_planes[0], area_co, plane_no);
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ BLI_task_parallel_range(0, totnode, &data, do_multiplane_scrape_brush_task_cb_ex, &settings);
+}
+
+void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr,
+ SculptSession *ss,
+ const float outline_col[3],
+ const float outline_alpha)
+{
+ float local_mat_inv[4][4];
+ invert_m4_m4(local_mat_inv, ss->cache->stroke_local_mat);
+ GPU_matrix_mul(local_mat_inv);
+ float angle = ss->cache->multiplane_scrape_angle;
+ if (ss->cache->pen_flip || ss->cache->invert) {
+ angle = -angle;
+ }
+
+ float offset = ss->cache->radius * 0.25f;
+
+ float p[3] = {0.0f, 0.0f, ss->cache->radius};
+ float y_axis[3] = {0.0f, 1.0f, 0.0f};
+ float p_l[3];
+ float p_r[3];
+ float area_center[3] = {0.0f, 0.0f, 0.0f};
+ rotate_v3_v3v3fl(p_r, p, y_axis, DEG2RADF((angle + 180) * 0.5f));
+ rotate_v3_v3v3fl(p_l, p, y_axis, DEG2RADF(-(angle + 180) * 0.5f));
+
+ immBegin(GPU_PRIM_LINES, 14);
+ immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+ immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
+ immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+ immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
+
+ immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+ immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
+ immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+ immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
+
+ immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+ immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+
+ immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
+ immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
+
+ immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
+ immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
+
+ immEnd();
+
+ immUniformColor3fvAlpha(outline_col, outline_alpha * 0.1f);
+ immBegin(GPU_PRIM_TRIS, 12);
+ immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+ immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
+ immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
+ immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+ immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+ immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
+
+ immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+ immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
+ immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
+ immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+ immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+ immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
+
+ immEnd();
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
new file mode 100644
index 00000000000..c7511dfc80f
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -0,0 +1,900 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_ccg.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_multires.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+static void pose_solve_ik_chain(SculptPoseIKChain *ik_chain,
+ const float initial_target[3],
+ const bool use_anchor)
+{
+ SculptPoseIKChainSegment *segments = ik_chain->segments;
+ int tot_segments = ik_chain->tot_segments;
+
+ float target[3];
+
+ /* Set the initial target. */
+ copy_v3_v3(target, initial_target);
+
+ /* Solve the positions and rotations of all segments in the chain. */
+ for (int i = 0; i < tot_segments; i++) {
+ float initial_orientation[3];
+ float current_orientation[3];
+ float current_head_position[3];
+ float current_origin_position[3];
+
+ /* Calculate the rotation to orientate the segment to the target from its initial state. */
+ sub_v3_v3v3(current_orientation, target, segments[i].orig);
+ normalize_v3(current_orientation);
+ sub_v3_v3v3(initial_orientation, segments[i].initial_head, segments[i].initial_orig);
+ normalize_v3(initial_orientation);
+ rotation_between_vecs_to_quat(segments[i].rot, initial_orientation, current_orientation);
+
+ /* Rotate the segment by calculating a new head position. */
+ madd_v3_v3v3fl(current_head_position, segments[i].orig, current_orientation, segments[i].len);
+
+ /* Move the origin of the segment towards the target. */
+ sub_v3_v3v3(current_origin_position, target, current_head_position);
+
+ /* Store the new head and origin positions to the segment. */
+ copy_v3_v3(segments[i].head, current_head_position);
+ add_v3_v3(segments[i].orig, current_origin_position);
+
+ /* Use the origin of this segment as target for the next segment in the chain. */
+ copy_v3_v3(target, segments[i].orig);
+ }
+
+ /* Move back the whole chain to preserve the anchor point. */
+ if (use_anchor) {
+ float anchor_diff[3];
+ sub_v3_v3v3(
+ anchor_diff, segments[tot_segments - 1].initial_orig, segments[tot_segments - 1].orig);
+
+ for (int i = 0; i < tot_segments; i++) {
+ add_v3_v3(segments[i].orig, anchor_diff);
+ add_v3_v3(segments[i].head, anchor_diff);
+ }
+ }
+}
+
+static void pose_solve_roll_chain(SculptPoseIKChain *ik_chain,
+ const Brush *brush,
+ const float roll)
+{
+ SculptPoseIKChainSegment *segments = ik_chain->segments;
+ int tot_segments = ik_chain->tot_segments;
+
+ for (int i = 0; i < tot_segments; i++) {
+ float initial_orientation[3];
+ float initial_rotation[4];
+ float current_rotation[4];
+
+ sub_v3_v3v3(initial_orientation, segments[i].initial_head, segments[i].initial_orig);
+ normalize_v3(initial_orientation);
+
+ /* Calculate the current roll angle using the brush curve. */
+ float current_roll = roll * BKE_brush_curve_strength(brush, i, tot_segments);
+
+ axis_angle_normalized_to_quat(initial_rotation, initial_orientation, 0.0f);
+ axis_angle_normalized_to_quat(current_rotation, initial_orientation, current_roll);
+
+ /* Store the difference of the rotations in the segment rotation. */
+ rotation_between_quats_to_quat(segments[i].rot, current_rotation, initial_rotation);
+ }
+}
+
+static void do_pose_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
+ SculptPoseIKChainSegment *segments = ik_chain->segments;
+
+ PBVHVertexIter vd;
+ float disp[3], new_co[3];
+ float final_pos[3];
+
+ SculptOrigVertData orig_data;
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
+
+ float total_disp[3];
+ zero_v3(total_disp);
+
+ ePaintSymmetryAreas symm_area = SCULPT_get_vertex_symm_area(orig_data.co);
+
+ /* Calculate the displacement of each vertex for all the segments in the chain. */
+ for (int ik = 0; ik < ik_chain->tot_segments; ik++) {
+ copy_v3_v3(new_co, orig_data.co);
+
+ /* Get the transform matrix for the vertex symmetry area to calculate a displacement in the
+ * vertex. */
+ mul_m4_v3(segments[ik].pivot_mat_inv[(int)symm_area], new_co);
+ mul_m4_v3(segments[ik].trans_mat[(int)symm_area], new_co);
+ mul_m4_v3(segments[ik].pivot_mat[(int)symm_area], new_co);
+
+ /* Apply the segment weight of the vertex to the displacement. */
+ sub_v3_v3v3(disp, new_co, orig_data.co);
+ mul_v3_fl(disp, segments[ik].weights[vd.index]);
+
+ /* Apply the vertex mask to the displacement. */
+ float mask = vd.mask ? *vd.mask : 0.0f;
+ mul_v3_fl(disp, 1.0f - mask);
+
+ /* Accumulate the displacement. */
+ add_v3_v3(total_disp, disp);
+ }
+
+ /* Apply the accumulated displacement to the vertex. */
+ add_v3_v3v3(final_pos, orig_data.co, total_disp);
+ copy_v3_v3(vd.co, final_pos);
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+typedef struct PoseGrowFactorTLSData {
+ float pos_avg[3];
+ int pos_count;
+} PoseGrowFactorTLSData;
+
+static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ PoseGrowFactorTLSData *gftd = tls->userdata_chunk;
+ SculptSession *ss = data->ob->sculpt;
+ const char symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ SculptVertexNeighborIter ni;
+ float max = 0.0f;
+
+ /* Grow the factor. */
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ float vmask_f = data->prev_mask[ni.index];
+ max = MAX2(vmask_f, max);
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ /* Keep the count of the vertices that where added to the factors in this grow iteration. */
+ if (max > data->prev_mask[vd.index]) {
+ data->pose_factor[vd.index] = max;
+ if (SCULPT_check_vertex_pivot_symmetry(vd.co, data->pose_initial_co, symm)) {
+ add_v3_v3(gftd->pos_avg, vd.co);
+ gftd->pos_count++;
+ }
+ }
+ }
+
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void pose_brush_grow_factor_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
+{
+ PoseGrowFactorTLSData *join = chunk_join;
+ PoseGrowFactorTLSData *gftd = chunk;
+ add_v3_v3(join->pos_avg, gftd->pos_avg);
+ join->pos_count += gftd->pos_count;
+}
+
+/* Grow the factor until its boundary is near to the offset pose origin or outside the target
+ * distance. */
+static void sculpt_pose_grow_pose_factor(Sculpt *sd,
+ Object *ob,
+ SculptSession *ss,
+ float pose_origin[3],
+ float pose_target[3],
+ float max_len,
+ float *r_pose_origin,
+ float *pose_factor)
+{
+ PBVHNode **nodes;
+ PBVH *pbvh = ob->sculpt->pbvh;
+ int totnode;
+
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = nodes,
+ .totnode = totnode,
+ .pose_factor = pose_factor,
+ };
+
+ data.pose_initial_co = pose_target;
+ TaskParallelSettings settings;
+ PoseGrowFactorTLSData gftd;
+ gftd.pos_count = 0;
+ zero_v3(gftd.pos_avg);
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ settings.func_reduce = pose_brush_grow_factor_reduce;
+ settings.userdata_chunk = &gftd;
+ settings.userdata_chunk_size = sizeof(PoseGrowFactorTLSData);
+
+ bool grow_next_iteration = true;
+ float prev_len = FLT_MAX;
+ data.prev_mask = MEM_mallocN(SCULPT_vertex_count_get(ss) * sizeof(float), "prev mask");
+ while (grow_next_iteration) {
+ zero_v3(gftd.pos_avg);
+ gftd.pos_count = 0;
+ memcpy(data.prev_mask, pose_factor, SCULPT_vertex_count_get(ss) * sizeof(float));
+ BLI_task_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings);
+
+ if (gftd.pos_count != 0) {
+ mul_v3_fl(gftd.pos_avg, 1.0f / (float)gftd.pos_count);
+ if (pose_origin) {
+ /* Test with pose origin. Used when growing the factors to compensate the Origin Offset. */
+ /* Stop when the factor's avg_pos starts moving away from the origin instead of getting
+ * closer to it. */
+ float len = len_v3v3(gftd.pos_avg, pose_origin);
+ if (len < prev_len) {
+ prev_len = len;
+ grow_next_iteration = true;
+ }
+ else {
+ grow_next_iteration = false;
+ memcpy(pose_factor, data.prev_mask, SCULPT_vertex_count_get(ss) * sizeof(float));
+ }
+ }
+ else {
+ /* Test with length. Used to calculate the origin positions of the IK chain. */
+ /* Stops when the factors have grown enough to generate a new segment origin. */
+ float len = len_v3v3(gftd.pos_avg, pose_target);
+ if (len < max_len) {
+ prev_len = len;
+ grow_next_iteration = true;
+ }
+ else {
+ grow_next_iteration = false;
+ if (r_pose_origin) {
+ copy_v3_v3(r_pose_origin, gftd.pos_avg);
+ }
+ memcpy(pose_factor, data.prev_mask, SCULPT_vertex_count_get(ss) * sizeof(float));
+ }
+ }
+ }
+ else {
+ if (r_pose_origin) {
+ copy_v3_v3(r_pose_origin, pose_target);
+ }
+ grow_next_iteration = false;
+ }
+ }
+ MEM_freeN(data.prev_mask);
+
+ MEM_SAFE_FREE(nodes);
+}
+
+static bool sculpt_pose_brush_is_vertex_inside_brush_radius(const float vertex[3],
+ const float br_co[3],
+ float radius,
+ char symm)
+{
+ for (char i = 0; i <= symm; ++i) {
+ if (SCULPT_is_symmetry_iteration_valid(i, symm)) {
+ float location[3];
+ flip_v3_v3(location, br_co, (char)i);
+ if (len_v3v3(location, vertex) < radius) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+typedef struct PoseFloodFillData {
+ float pose_initial_co[3];
+ float radius;
+ int symm;
+
+ float *pose_factor;
+ float pose_origin[3];
+ int tot_co;
+
+ int current_face_set;
+ int next_face_set;
+ int prev_face_set;
+ int next_vertex;
+
+ bool next_face_set_found;
+
+ /* Store the visited face sets to avoid going back when calculating the chain. */
+ GSet *visited_face_sets;
+
+ /* In face sets origin mode, each vertex can only be assigned to one face set. */
+ bool *is_weighted;
+
+ bool is_first_iteration;
+
+ /* Fallback origin. If we can't find any face set to continue, use the position of all vertices
+ * that have the current face set. */
+ float fallback_origin[3];
+ int fallback_count;
+} PoseFloodFillData;
+
+static bool pose_topology_floodfill_cb(
+ SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
+{
+ PoseFloodFillData *data = userdata;
+
+ if (data->pose_factor) {
+ data->pose_factor[to_v] = 1.0f;
+ }
+
+ const float *co = SCULPT_vertex_co_get(ss, to_v);
+ if (sculpt_pose_brush_is_vertex_inside_brush_radius(
+ co, data->pose_initial_co, data->radius, data->symm)) {
+ return true;
+ }
+ else if (SCULPT_check_vertex_pivot_symmetry(co, data->pose_initial_co, data->symm)) {
+ if (!is_duplicate) {
+ add_v3_v3(data->pose_origin, co);
+ data->tot_co++;
+ }
+ }
+
+ return false;
+}
+
+static bool pose_face_sets_floodfill_cb(
+ SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
+{
+ PoseFloodFillData *data = userdata;
+
+ const int index = to_v;
+ bool visit_next = false;
+
+ const float *co = SCULPT_vertex_co_get(ss, index);
+ const bool symmetry_check = SCULPT_check_vertex_pivot_symmetry(
+ co, data->pose_initial_co, data->symm) &&
+ !is_duplicate;
+
+ /* First iteration. Continue expanding using topology until a vertex is outside the brush radius
+ * to determine the first face set. */
+ if (data->current_face_set == SCULPT_FACE_SET_NONE) {
+
+ data->pose_factor[index] = 1.0f;
+ data->is_weighted[index] = true;
+
+ if (sculpt_pose_brush_is_vertex_inside_brush_radius(
+ co, data->pose_initial_co, data->radius, data->symm)) {
+ const int visited_face_set = SCULPT_vertex_face_set_get(ss, index);
+ BLI_gset_add(data->visited_face_sets, POINTER_FROM_INT(visited_face_set));
+ }
+ else if (symmetry_check) {
+ data->current_face_set = SCULPT_vertex_face_set_get(ss, index);
+ BLI_gset_add(data->visited_face_sets, POINTER_FROM_INT(data->current_face_set));
+ }
+ return true;
+ }
+
+ /* We already have a current face set, so we can start checking the face sets of the vertices. */
+ /* In the first iteration we need to check all face sets we already visited as the flood fill may
+ * still not be finished in some of them. */
+ bool is_vertex_valid = false;
+ if (data->is_first_iteration) {
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, data->visited_face_sets) {
+ const int visited_face_set = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
+ is_vertex_valid |= SCULPT_vertex_has_face_set(ss, index, visited_face_set);
+ }
+ }
+ else {
+ is_vertex_valid = SCULPT_vertex_has_face_set(ss, index, data->current_face_set);
+ }
+
+ if (is_vertex_valid) {
+
+ if (!data->is_weighted[index]) {
+ data->pose_factor[index] = 1.0f;
+ data->is_weighted[index] = true;
+ visit_next = true;
+ }
+
+ /* Fallback origin accumulation. */
+ if (symmetry_check) {
+ add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, index));
+ data->fallback_count++;
+ }
+
+ if (symmetry_check && !SCULPT_vertex_has_unique_face_set(ss, index)) {
+
+ /* We only add coordinates for calculating the origin when it is possible to go from this
+ * vertex to another vertex in a valid face set for the next iteration. */
+ bool count_as_boundary = false;
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
+ int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.index);
+
+ /* Check if we can get a valid face set for the next iteration from this neighbor. */
+ if (SCULPT_vertex_has_unique_face_set(ss, ni.index) &&
+ !BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(next_face_set_candidate))) {
+ if (!data->next_face_set_found) {
+ data->next_face_set = next_face_set_candidate;
+ data->next_vertex = ni.index;
+ data->next_face_set_found = true;
+ }
+ count_as_boundary = true;
+ }
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ /* Origin accumulation. */
+ if (count_as_boundary) {
+ add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, index));
+ data->tot_co++;
+ }
+ }
+ }
+ return visit_next;
+}
+
+/* Public functions. */
+
+/* Calculate the pose origin and (Optionaly the pose factor) that is used when using the pose brush
+ *
+ * r_pose_origin must be a valid pointer. the r_pose_factor is optional. When set to NULL it won't
+ * be calculated. */
+void SCULPT_pose_calc_pose_data(Sculpt *sd,
+ Object *ob,
+ SculptSession *ss,
+ float initial_location[3],
+ float radius,
+ float pose_offset,
+ float *r_pose_origin,
+ float *r_pose_factor)
+{
+ SCULPT_vertex_random_access_init(ss);
+
+ /* Calculate the pose rotation point based on the boundaries of the brush factor. */
+ SculptFloodFill flood;
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_active(sd, ob, ss, &flood, (r_pose_factor) ? radius : 0.0f);
+
+ PoseFloodFillData fdata = {
+ .radius = radius,
+ .symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL,
+ .pose_factor = r_pose_factor,
+ .tot_co = 0,
+ };
+ zero_v3(fdata.pose_origin);
+ copy_v3_v3(fdata.pose_initial_co, initial_location);
+ SCULPT_floodfill_execute(ss, &flood, pose_topology_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ if (fdata.tot_co > 0) {
+ mul_v3_fl(fdata.pose_origin, 1.0f / (float)fdata.tot_co);
+ }
+
+ /* Offset the pose origin. */
+ float pose_d[3];
+ sub_v3_v3v3(pose_d, fdata.pose_origin, fdata.pose_initial_co);
+ normalize_v3(pose_d);
+ madd_v3_v3fl(fdata.pose_origin, pose_d, radius * pose_offset);
+ copy_v3_v3(r_pose_origin, fdata.pose_origin);
+
+ /* Do the initial grow of the factors to get the first segment of the chain with Origin Offset.
+ */
+ if (pose_offset != 0.0f && r_pose_factor) {
+ sculpt_pose_grow_pose_factor(
+ sd, ob, ss, fdata.pose_origin, fdata.pose_origin, 0, NULL, r_pose_factor);
+ }
+}
+
+static void pose_brush_init_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ SculptVertexNeighborIter ni;
+ float avg = 0.0f;
+ int total = 0;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ avg += data->pose_factor[ni.index];
+ total++;
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ if (total > 0) {
+ data->pose_factor[vd.index] = avg / total;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+/* Init the IK chain with empty weights. */
+static SculptPoseIKChain *pose_ik_chain_new(const int totsegments, const int totverts)
+{
+ SculptPoseIKChain *ik_chain = MEM_callocN(sizeof(SculptPoseIKChain), "Pose IK Chain");
+ ik_chain->tot_segments = totsegments;
+ ik_chain->segments = MEM_callocN(totsegments * sizeof(SculptPoseIKChainSegment),
+ "Pose IK Chain Segments");
+ for (int i = 0; i < totsegments; i++) {
+ ik_chain->segments[i].weights = MEM_callocN(totverts * sizeof(float), "Pose IK weights");
+ }
+ return ik_chain;
+}
+
+/* Init the origin/head pairs of all the segments from the calculated origins. */
+static void pose_ik_chain_origin_heads_init(SculptPoseIKChain *ik_chain,
+ const float initial_location[3])
+{
+ float origin[3];
+ float head[3];
+ for (int i = 0; i < ik_chain->tot_segments; i++) {
+ if (i == 0) {
+ copy_v3_v3(head, initial_location);
+ copy_v3_v3(origin, ik_chain->segments[i].orig);
+ }
+ else {
+ copy_v3_v3(head, ik_chain->segments[i - 1].orig);
+ copy_v3_v3(origin, ik_chain->segments[i].orig);
+ }
+ copy_v3_v3(ik_chain->segments[i].orig, origin);
+ copy_v3_v3(ik_chain->segments[i].initial_orig, origin);
+ copy_v3_v3(ik_chain->segments[i].initial_head, head);
+ ik_chain->segments[i].len = len_v3v3(head, origin);
+ }
+}
+
+static SculptPoseIKChain *pose_ik_chain_init_topology(Sculpt *sd,
+ Object *ob,
+ SculptSession *ss,
+ Brush *br,
+ const float initial_location[3],
+ const float radius)
+{
+
+ const float chain_segment_len = radius * (1.0f + br->pose_offset);
+ float next_chain_segment_target[3];
+
+ int totvert = SCULPT_vertex_count_get(ss);
+ int nearest_vertex_index = SCULPT_nearest_vertex_get(sd, ob, initial_location, FLT_MAX, true);
+
+ /* Init the buffers used to keep track of the changes in the pose factors as more segments are
+ * added to the IK chain. */
+
+ /* This stores the whole pose factors values as they grow through the mesh. */
+ float *pose_factor_grow = MEM_callocN(totvert * sizeof(float), "Pose Factor Grow");
+
+ /* This stores the previous status of the factors when growing a new iteration. */
+ float *pose_factor_grow_prev = MEM_callocN(totvert * sizeof(float),
+ "Pose Factor Grow Prev Iteration");
+
+ pose_factor_grow[nearest_vertex_index] = 1.0f;
+
+ SculptPoseIKChain *ik_chain = pose_ik_chain_new(br->pose_ik_segments, totvert);
+
+ /* Calculate the first segment in the chain using the brush radius and the pose origin offset. */
+ copy_v3_v3(next_chain_segment_target, initial_location);
+ SCULPT_pose_calc_pose_data(sd,
+ ob,
+ ss,
+ next_chain_segment_target,
+ radius,
+ br->pose_offset,
+ ik_chain->segments[0].orig,
+ pose_factor_grow);
+
+ copy_v3_v3(next_chain_segment_target, ik_chain->segments[0].orig);
+
+ /* Init the weights of this segment and store the status of the pose factors to start calculating
+ * new segment origins. */
+ for (int j = 0; j < totvert; j++) {
+ ik_chain->segments[0].weights[j] = pose_factor_grow[j];
+ pose_factor_grow_prev[j] = pose_factor_grow[j];
+ }
+
+ /* Calculate the next segments in the chain growing the pose factors. */
+ for (int i = 1; i < ik_chain->tot_segments; i++) {
+
+ /* Grow the factors to get the new segment origin. */
+ sculpt_pose_grow_pose_factor(sd,
+ ob,
+ ss,
+ NULL,
+ next_chain_segment_target,
+ chain_segment_len,
+ ik_chain->segments[i].orig,
+ pose_factor_grow);
+ copy_v3_v3(next_chain_segment_target, ik_chain->segments[i].orig);
+
+ /* Create the weights for this segment from the difference between the previous grow factor
+ * iteration an the current iteration. */
+ for (int j = 0; j < totvert; j++) {
+ ik_chain->segments[i].weights[j] = pose_factor_grow[j] - pose_factor_grow_prev[j];
+ /* Store the current grow factor status for the next interation. */
+ pose_factor_grow_prev[j] = pose_factor_grow[j];
+ }
+ }
+
+ pose_ik_chain_origin_heads_init(ik_chain, initial_location);
+
+ MEM_freeN(pose_factor_grow);
+ MEM_freeN(pose_factor_grow_prev);
+
+ return ik_chain;
+}
+
+static SculptPoseIKChain *pose_ik_chain_init_face_sets(
+ Sculpt *sd, Object *ob, SculptSession *ss, Brush *br, const float radius)
+{
+
+ int totvert = SCULPT_vertex_count_get(ss);
+
+ SculptPoseIKChain *ik_chain = pose_ik_chain_new(br->pose_ik_segments, totvert);
+
+ GSet *visited_face_sets = BLI_gset_int_new_ex("visited_face_sets", ik_chain->tot_segments);
+
+ bool *is_weighted = MEM_callocN(sizeof(bool) * totvert, "weighted");
+
+ int current_face_set = SCULPT_FACE_SET_NONE;
+ int prev_face_set = SCULPT_FACE_SET_NONE;
+
+ int current_vertex = SCULPT_active_vertex_get(ss);
+
+ for (int s = 0; s < ik_chain->tot_segments; s++) {
+
+ SculptFloodFill flood;
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, current_vertex, FLT_MAX);
+
+ BLI_gset_add(visited_face_sets, POINTER_FROM_INT(current_face_set));
+
+ PoseFloodFillData fdata = {
+ .radius = radius,
+ .symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL,
+ .pose_factor = ik_chain->segments[s].weights,
+ .tot_co = 0,
+ .fallback_count = 0,
+ .current_face_set = current_face_set,
+ .prev_face_set = prev_face_set,
+ .visited_face_sets = visited_face_sets,
+ .is_weighted = is_weighted,
+ .next_face_set_found = false,
+ .is_first_iteration = s == 0,
+ };
+ zero_v3(fdata.pose_origin);
+ zero_v3(fdata.fallback_origin);
+ copy_v3_v3(fdata.pose_initial_co, SCULPT_vertex_co_get(ss, current_vertex));
+ SCULPT_floodfill_execute(ss, &flood, pose_face_sets_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ if (fdata.tot_co > 0) {
+ mul_v3_fl(fdata.pose_origin, 1.0f / (float)fdata.tot_co);
+ copy_v3_v3(ik_chain->segments[s].orig, fdata.pose_origin);
+ }
+ else if (fdata.fallback_count > 0) {
+ mul_v3_fl(fdata.fallback_origin, 1.0f / (float)fdata.fallback_count);
+ copy_v3_v3(ik_chain->segments[s].orig, fdata.fallback_origin);
+ }
+ else {
+ zero_v3(ik_chain->segments[s].orig);
+ }
+
+ prev_face_set = fdata.current_face_set;
+ current_face_set = fdata.next_face_set;
+ current_vertex = fdata.next_vertex;
+ }
+
+ BLI_gset_free(visited_face_sets, NULL);
+
+ pose_ik_chain_origin_heads_init(ik_chain, SCULPT_active_vertex_co_get(ss));
+
+ MEM_SAFE_FREE(is_weighted);
+
+ return ik_chain;
+}
+
+SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd,
+ Object *ob,
+ SculptSession *ss,
+ Brush *br,
+ const float initial_location[3],
+ const float radius)
+{
+ switch (br->pose_origin_type) {
+ case BRUSH_POSE_ORIGIN_TOPOLOGY:
+ return pose_ik_chain_init_topology(sd, ob, ss, br, initial_location, radius);
+ break;
+ case BRUSH_POSE_ORIGIN_FACE_SETS:
+ return pose_ik_chain_init_face_sets(sd, ob, ss, br, radius);
+ break;
+ }
+ return NULL;
+}
+
+void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br)
+{
+ PBVHNode **nodes;
+ PBVH *pbvh = ob->sculpt->pbvh;
+ int totnode;
+
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = br,
+ .nodes = nodes,
+ };
+
+ /* Init the IK chain that is going to be used to deform the vertices. */
+ ss->cache->pose_ik_chain = SCULPT_pose_ik_chain_init(
+ sd, ob, ss, br, ss->cache->true_location, ss->cache->radius);
+
+ /* Smooth the weights of each segment for cleaner deformation. */
+ for (int ik = 0; ik < ss->cache->pose_ik_chain->tot_segments; ik++) {
+ data.pose_factor = ss->cache->pose_ik_chain->segments[ik].weights;
+ for (int i = 0; i < br->pose_smooth_iterations; i++) {
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ BLI_task_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings);
+ }
+ }
+
+ MEM_SAFE_FREE(nodes);
+}
+
+/* Main Brush Function. */
+void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ float grab_delta[3];
+ float ik_target[3];
+ const ePaintSymmetryFlags symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+
+ /* The pose brush applies all enabled symmetry axis in a single iteration, so the rest can be
+ * ignored. */
+ if (ss->cache->mirror_symmetry_pass != 0) {
+ return;
+ }
+
+ SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
+
+ /* Solve the positions and rotations of the IK chain. */
+ if (ss->cache->invert) {
+ /* Roll Mode. */
+ /* Calculate the maximum roll. 0.02 radians per pixel works fine. */
+ float roll = (ss->cache->initial_mouse[0] - ss->cache->mouse[0]) * ss->cache->bstrength *
+ 0.02f;
+ BKE_curvemapping_initialize(brush->curve);
+ pose_solve_roll_chain(ik_chain, brush, roll);
+ }
+ else {
+ /* IK follow target mode. */
+ /* Calculate the IK target. */
+
+ copy_v3_v3(grab_delta, ss->cache->grab_delta);
+ copy_v3_v3(ik_target, ss->cache->true_location);
+ add_v3_v3(ik_target, ss->cache->grab_delta);
+
+ /* Solve the IK positions. */
+ pose_solve_ik_chain(ik_chain, ik_target, brush->flag2 & BRUSH_POSE_IK_ANCHORED);
+ }
+
+ /* Flip the segment chain in all symmetry axis and calculate the transform matrices for each
+ * possible combination. */
+ /* This can be optimized by skipping the calculation of matrices where the symmetry is not
+ * enabled. */
+ for (int symm_it = 0; symm_it < PAINT_SYMM_AREAS; symm_it++) {
+ for (int i = 0; i < brush->pose_ik_segments; i++) {
+ float symm_rot[4];
+ float symm_orig[3];
+ float symm_initial_orig[3];
+
+ ePaintSymmetryAreas symm_area = symm_it;
+
+ copy_qt_qt(symm_rot, ik_chain->segments[i].rot);
+ copy_v3_v3(symm_orig, ik_chain->segments[i].orig);
+ copy_v3_v3(symm_initial_orig, ik_chain->segments[i].initial_orig);
+
+ /* Flip the origins and rotation quats of each segment. */
+ SCULPT_flip_quat_by_symm_area(symm_rot, symm, symm_area, ss->cache->orig_grab_location);
+ SCULPT_flip_v3_by_symm_area(symm_orig, symm, symm_area, ss->cache->orig_grab_location);
+ SCULPT_flip_v3_by_symm_area(
+ symm_initial_orig, symm, symm_area, ss->cache->orig_grab_location);
+
+ /* Create the transform matrix and store it in the segment. */
+ unit_m4(ik_chain->segments[i].pivot_mat[symm_it]);
+ quat_to_mat4(ik_chain->segments[i].trans_mat[symm_it], symm_rot);
+
+ translate_m4(ik_chain->segments[i].trans_mat[symm_it],
+ symm_orig[0] - symm_initial_orig[0],
+ symm_orig[1] - symm_initial_orig[1],
+ symm_orig[2] - symm_initial_orig[2]);
+ translate_m4(
+ ik_chain->segments[i].pivot_mat[symm_it], symm_orig[0], symm_orig[1], symm_orig[2]);
+ invert_m4_m4(ik_chain->segments[i].pivot_mat_inv[symm_it],
+ ik_chain->segments[i].pivot_mat[symm_it]);
+ }
+ }
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .grab_delta = grab_delta,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings);
+}
+
+void SCULPT_pose_ik_chain_free(SculptPoseIKChain *ik_chain)
+{
+ for (int i = 0; i < ik_chain->tot_segments; i++) {
+ MEM_SAFE_FREE(ik_chain->segments[i].weights);
+ }
+ MEM_SAFE_FREE(ik_chain->segments);
+ MEM_SAFE_FREE(ik_chain);
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c
new file mode 100644
index 00000000000..17451cb40ae
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c
@@ -0,0 +1,608 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_hash.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+/* For the smooth brush, uses the neighboring vertices around vert to calculate
+ * a smoothed location for vert. Skips corner vertices (used by only one
+ * polygon). */
+void SCULPT_neighbor_average(SculptSession *ss, float avg[3], uint vert)
+{
+ const MeshElemMap *vert_map = &ss->pmap[vert];
+ const MVert *mvert = ss->mvert;
+ float(*deform_co)[3] = ss->deform_cos;
+
+ /* Don't modify corner vertices. */
+ if (vert_map->count > 1) {
+ int total = 0;
+
+ zero_v3(avg);
+
+ for (int i = 0; i < vert_map->count; i++) {
+ const MPoly *p = &ss->mpoly[vert_map->indices[i]];
+ uint f_adj_v[2];
+
+ if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) {
+ for (int j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
+ if (vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2) {
+ add_v3_v3(avg, deform_co ? deform_co[f_adj_v[j]] : mvert[f_adj_v[j]].co);
+
+ total++;
+ }
+ }
+ }
+ }
+
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ return;
+ }
+ }
+
+ copy_v3_v3(avg, deform_co ? deform_co[vert] : mvert[vert].co);
+}
+
+/* Same logic as neighbor_average(), but for bmesh rather than mesh. */
+void SCULPT_bmesh_neighbor_average(float avg[3], BMVert *v)
+{
+ /* logic for 3 or more is identical. */
+ const int vfcount = BM_vert_face_count_at_most(v, 3);
+
+ /* Don't modify corner vertices. */
+ if (vfcount > 1) {
+ BMIter liter;
+ BMLoop *l;
+ int total = 0;
+
+ zero_v3(avg);
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ const BMVert *adj_v[2] = {l->prev->v, l->next->v};
+
+ for (int i = 0; i < ARRAY_SIZE(adj_v); i++) {
+ const BMVert *v_other = adj_v[i];
+ if (vfcount != 2 || BM_vert_face_count_at_most(v_other, 2) <= 2) {
+ add_v3_v3(avg, v_other->co);
+ total++;
+ }
+ }
+ }
+
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ return;
+ }
+ }
+
+ copy_v3_v3(avg, v->co);
+}
+
+/* For bmesh: Average surrounding verts based on an orthogonality measure.
+ * Naturally converges to a quad-like structure. */
+void SCULPT_bmesh_four_neighbor_average(float avg[3], float direction[3], BMVert *v)
+{
+
+ float avg_co[3] = {0.0f, 0.0f, 0.0f};
+ float tot_co = 0.0f;
+
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(e)) {
+ copy_v3_v3(avg, v->co);
+ return;
+ }
+ BMVert *v_other = (e->v1 == v) ? e->v2 : e->v1;
+ float vec[3];
+ sub_v3_v3v3(vec, v_other->co, v->co);
+ madd_v3_v3fl(vec, v->no, -dot_v3v3(vec, v->no));
+ normalize_v3(vec);
+
+ /* fac is a measure of how orthogonal or parallel the edge is
+ * relative to the direction. */
+ float fac = dot_v3v3(vec, direction);
+ fac = fac * fac - 0.5f;
+ fac *= fac;
+ madd_v3_v3fl(avg_co, v_other->co, fac);
+ tot_co += fac;
+ }
+
+ /* In case vert has no Edge s. */
+ if (tot_co > 0.0f) {
+ mul_v3_v3fl(avg, avg_co, 1.0f / tot_co);
+
+ /* Preserve volume. */
+ float vec[3];
+ sub_v3_v3(avg, v->co);
+ mul_v3_v3fl(vec, v->no, dot_v3v3(avg, v->no));
+ sub_v3_v3(avg, vec);
+ add_v3_v3(avg, v->co);
+ }
+ else {
+ zero_v3(avg);
+ }
+}
+
+/* Generic functions for laplacian smoothing. These functions do not take boundary vertices into
+ * account. */
+
+void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int index)
+{
+ float avg[3] = {0.0f, 0.0f, 0.0f};
+ int total = 0;
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
+ add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.index));
+ total++;
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ if (total > 0) {
+ mul_v3_v3fl(result, avg, 1.0f / (float)total);
+ }
+ else {
+ copy_v3_v3(result, SCULPT_vertex_co_get(ss, index));
+ }
+}
+
+float SCULPT_neighbor_mask_average(SculptSession *ss, int index)
+{
+ float avg = 0.0f;
+ int total = 0;
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
+ avg += SCULPT_vertex_mask_get(ss, ni.index);
+ total++;
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ if (total > 0) {
+ return avg / (float)total;
+ }
+ else {
+ return SCULPT_vertex_mask_get(ss, index);
+ }
+}
+
+static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ Sculpt *sd = data->sd;
+ const Brush *brush = data->brush;
+ const bool smooth_mask = data->smooth_mask;
+ float bstrength = data->strength;
+
+ PBVHVertexIter vd;
+
+ CLAMP(bstrength, 0.0f, 1.0f);
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(
+ ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
+ vd.index,
+ thread_id);
+ if (smooth_mask) {
+ float val = SCULPT_neighbor_mask_average(ss, vd.vert_indices[vd.i]) - *vd.mask;
+ val *= fade * bstrength;
+ *vd.mask += val;
+ CLAMP(*vd.mask, 0.0f, 1.0f);
+ }
+ else {
+ float avg[3], val[3];
+
+ SCULPT_neighbor_average(ss, avg, vd.vert_indices[vd.i]);
+ sub_v3_v3v3(val, avg, vd.co);
+
+ madd_v3_v3v3fl(val, vd.co, val, fade);
+
+ SCULPT_clip(sd, ss, vd.co, val);
+ }
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_smooth_brush_bmesh_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ Sculpt *sd = data->sd;
+ const Brush *brush = data->brush;
+ const bool smooth_mask = data->smooth_mask;
+ float bstrength = data->strength;
+
+ PBVHVertexIter vd;
+
+ CLAMP(bstrength, 0.0f, 1.0f);
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ smooth_mask ? 0.0f : *vd.mask,
+ vd.index,
+ thread_id);
+ if (smooth_mask) {
+ float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask;
+ val *= fade * bstrength;
+ *vd.mask += val;
+ CLAMP(*vd.mask, 0.0f, 1.0f);
+ }
+ else {
+ float avg[3], val[3];
+
+ SCULPT_bmesh_neighbor_average(avg, vd.bm_vert);
+ sub_v3_v3v3(val, avg, vd.co);
+
+ madd_v3_v3v3fl(val, vd.co, val, fade);
+
+ SCULPT_clip(sd, ss, vd.co, val);
+ }
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ Sculpt *sd = data->sd;
+ const Brush *brush = data->brush;
+ const bool smooth_mask = data->smooth_mask;
+ float bstrength = data->strength;
+
+ PBVHVertexIter vd;
+
+ CLAMP(bstrength, 0.0f, 1.0f);
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(
+ ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
+ vd.index,
+ thread_id);
+ if (smooth_mask) {
+ float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask;
+ val *= fade * bstrength;
+ *vd.mask += val;
+ CLAMP(*vd.mask, 0.0f, 1.0f);
+ }
+ else {
+ float avg[3], val[3];
+ SCULPT_neighbor_coords_average(ss, avg, vd.index);
+ sub_v3_v3v3(val, avg, vd.co);
+ madd_v3_v3v3fl(val, vd.co, val, fade);
+ SCULPT_clip(sd, ss, vd.co, val);
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+void SCULPT_smooth(Sculpt *sd,
+ Object *ob,
+ PBVHNode **nodes,
+ const int totnode,
+ float bstrength,
+ const bool smooth_mask)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ const int max_iterations = 4;
+ const float fract = 1.0f / max_iterations;
+ PBVHType type = BKE_pbvh_type(ss->pbvh);
+ int iteration, count;
+ float last;
+
+ CLAMP(bstrength, 0.0f, 1.0f);
+
+ count = (int)(bstrength * max_iterations);
+ last = max_iterations * (bstrength - count * fract);
+
+ if (type == PBVH_FACES && !ss->pmap) {
+ BLI_assert(!"sculpt smooth: pmap missing");
+ return;
+ }
+
+ for (iteration = 0; iteration <= count; iteration++) {
+ const float strength = (iteration != count) ? 1.0f : last;
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .smooth_mask = smooth_mask,
+ .strength = strength,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+
+ switch (type) {
+ case PBVH_GRIDS:
+ BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings);
+ break;
+ case PBVH_FACES:
+ BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings);
+ break;
+ case PBVH_BMESH:
+ BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings);
+ break;
+ }
+ }
+}
+
+void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false);
+}
+
+/* HC Smooth Algorithm. */
+/* From: Improved Laplacian Smoothing of Noisy Surface Meshes */
+
+void SCULPT_surface_smooth_laplacian_step(SculptSession *ss,
+ float *disp,
+ const float co[3],
+ float (*laplacian_disp)[3],
+ const int v_index,
+ const float origco[3],
+ const float alpha)
+{
+ float laplacian_smooth_co[3];
+ float weigthed_o[3], weigthed_q[3], d[3];
+ SCULPT_neighbor_coords_average(ss, laplacian_smooth_co, v_index);
+
+ mul_v3_v3fl(weigthed_o, origco, alpha);
+ mul_v3_v3fl(weigthed_q, co, 1.0f - alpha);
+ add_v3_v3v3(d, weigthed_o, weigthed_q);
+ sub_v3_v3v3(laplacian_disp[v_index], laplacian_smooth_co, d);
+
+ sub_v3_v3v3(disp, laplacian_smooth_co, co);
+}
+
+void SCULPT_surface_smooth_displace_step(SculptSession *ss,
+ float *co,
+ float (*laplacian_disp)[3],
+ const int v_index,
+ const float beta,
+ const float fade)
+{
+ float b_avg[3] = {0.0f, 0.0f, 0.0f};
+ float b_current_vertex[3];
+ int total = 0;
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v_index, ni) {
+ add_v3_v3(b_avg, laplacian_disp[ni.index]);
+ total++;
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ if (total > 0) {
+ mul_v3_v3fl(b_current_vertex, b_avg, (1.0f - beta) / (float)total);
+ madd_v3_v3fl(b_current_vertex, laplacian_disp[v_index], beta);
+ mul_v3_fl(b_current_vertex, clamp_f(fade, 0.0f, 1.0f));
+ sub_v3_v3(co, b_current_vertex);
+ }
+}
+
+static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
+ void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float bstrength = ss->cache->bstrength;
+ float alpha = brush->surface_smooth_shape_preservation;
+
+ PBVHVertexIter vd;
+ SculptOrigVertData orig_data;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade =
+ bstrength *
+ SCULPT_brush_strength_factor(
+ ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id);
+
+ float disp[3];
+ SCULPT_surface_smooth_laplacian_step(ss,
+ disp,
+ vd.co,
+ ss->cache->surface_smooth_laplacian_disp,
+ vd.index,
+ orig_data.co,
+ alpha);
+ madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f));
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+}
+
+static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex(
+ void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float bstrength = ss->cache->bstrength;
+ const float beta = brush->surface_smooth_current_vertex;
+
+ PBVHVertexIter vd;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade =
+ bstrength *
+ SCULPT_brush_strength_factor(
+ ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id);
+ SCULPT_surface_smooth_displace_step(
+ ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade);
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
+
+ if (ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0 &&
+ ss->cache->radial_symmetry_pass == 0) {
+ BLI_assert(ss->cache->surface_smooth_laplacian_disp == NULL);
+ ss->cache->surface_smooth_laplacian_disp = MEM_callocN(
+ SCULPT_vertex_count_get(ss) * 3 * sizeof(float), "HC smooth laplacian b");
+ }
+
+ /* Threaded loop over nodes. */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
+ for (int i = 0; i < brush->surface_smooth_iterations; i++) {
+ BLI_task_parallel_range(
+ 0, totnode, &data, SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex, &settings);
+ BLI_task_parallel_range(
+ 0, totnode, &data, SCULPT_do_surface_smooth_brush_displace_task_cb_ex, &settings);
+ }
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c
new file mode 100644
index 00000000000..2eb1191b950
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_transform.c
@@ -0,0 +1,381 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+void ED_sculpt_init_transform(struct bContext *C)
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+
+ copy_v3_v3(ss->init_pivot_pos, ss->pivot_pos);
+ copy_v4_v4(ss->init_pivot_rot, ss->pivot_rot);
+
+ SCULPT_undo_push_begin("Transform");
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false);
+
+ ss->pivot_rot[3] = 1.0f;
+
+ SCULPT_vertex_random_access_init(ss);
+ SCULPT_filter_cache_init(ob, sd);
+}
+
+static void sculpt_transform_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+
+ SculptOrigVertData orig_data;
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i]);
+
+ PBVHVertexIter vd;
+
+ SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
+ float transformed_co[3], orig_co[3], disp[3];
+ float fade = vd.mask ? *vd.mask : 0.0f;
+ copy_v3_v3(orig_co, orig_data.co);
+ char symm_area = SCULPT_get_vertex_symm_area(orig_co);
+
+ copy_v3_v3(transformed_co, orig_co);
+ mul_m4_v3(data->transform_mats[(int)symm_area], transformed_co);
+ sub_v3_v3v3(disp, transformed_co, orig_co);
+ mul_v3_fl(disp, 1.0f - fade);
+
+ add_v3_v3v3(vd.co, orig_co, disp);
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ BKE_pbvh_node_mark_update(node);
+}
+
+void ED_sculpt_update_modal_transform(struct bContext *C)
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+
+ SCULPT_vertex_random_access_init(ss);
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false);
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = ss->filter_cache->nodes,
+ };
+
+ float final_pivot_pos[3], d_t[3], d_r[4];
+ float t_mat[4][4], r_mat[4][4], s_mat[4][4], pivot_mat[4][4], pivot_imat[4][4],
+ transform_mat[4][4];
+
+ copy_v3_v3(final_pivot_pos, ss->pivot_pos);
+ for (int i = 0; i < PAINT_SYMM_AREAS; i++) {
+ ePaintSymmetryAreas v_symm = i;
+
+ copy_v3_v3(final_pivot_pos, ss->pivot_pos);
+
+ unit_m4(pivot_mat);
+
+ unit_m4(t_mat);
+ unit_m4(r_mat);
+ unit_m4(s_mat);
+
+ /* Translation matrix. */
+ sub_v3_v3v3(d_t, ss->pivot_pos, ss->init_pivot_pos);
+ SCULPT_flip_v3_by_symm_area(d_t, symm, v_symm, ss->init_pivot_pos);
+ translate_m4(t_mat, d_t[0], d_t[1], d_t[2]);
+
+ /* Rotation matrix. */
+ sub_qt_qtqt(d_r, ss->pivot_rot, ss->init_pivot_rot);
+ normalize_qt(d_r);
+ SCULPT_flip_quat_by_symm_area(d_r, symm, v_symm, ss->init_pivot_pos);
+ quat_to_mat4(r_mat, d_r);
+
+ /* Scale matrix. */
+ size_to_mat4(s_mat, ss->pivot_scale);
+
+ /* Pivot matrix. */
+ SCULPT_flip_v3_by_symm_area(final_pivot_pos, symm, v_symm, ss->init_pivot_pos);
+ translate_m4(pivot_mat, final_pivot_pos[0], final_pivot_pos[1], final_pivot_pos[2]);
+ invert_m4_m4(pivot_imat, pivot_mat);
+
+ /* Final transform matrix. */
+ mul_m4_m4m4(transform_mat, r_mat, t_mat);
+ mul_m4_m4m4(transform_mat, transform_mat, s_mat);
+ mul_m4_m4m4(data.transform_mats[i], transform_mat, pivot_imat);
+ mul_m4_m4m4(data.transform_mats[i], pivot_mat, data.transform_mats[i]);
+ }
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(
+ &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
+ BLI_task_parallel_range(
+ 0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings);
+
+ if (ss->deform_modifiers_active || ss->shapekey_active) {
+ SCULPT_flush_stroke_deform(sd, ob, true);
+ }
+
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
+}
+
+void ED_sculpt_end_transform(struct bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ if (ss->filter_cache) {
+ SCULPT_filter_cache_free(ss);
+ }
+ /* Force undo push to happen even inside transform operator, since the sculpt
+ * undo system works separate from regular undo and this is require to properly
+ * finish an undo step also when cancelling. */
+ const bool use_nested_undo = true;
+ SCULPT_undo_push_end_ex(use_nested_undo);
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
+}
+
+typedef enum eSculptPivotPositionModes {
+ SCULPT_PIVOT_POSITION_ORIGIN = 0,
+ SCULPT_PIVOT_POSITION_UNMASKED = 1,
+ SCULPT_PIVOT_POSITION_MASK_BORDER = 2,
+ SCULPT_PIVOT_POSITION_ACTIVE_VERTEX = 3,
+ SCULPT_PIVOT_POSITION_CURSOR_SURFACE = 4,
+} eSculptPivotPositionModes;
+
+static EnumPropertyItem prop_sculpt_pivot_position_types[] = {
+ {SCULPT_PIVOT_POSITION_ORIGIN,
+ "ORIGIN",
+ 0,
+ "Origin",
+ "Sets the pivot to the origin of the sculpt"},
+ {SCULPT_PIVOT_POSITION_UNMASKED,
+ "UNMASKED",
+ 0,
+ "Unmasked",
+ "Sets the pivot position to the average position of the unmasked vertices"},
+ {SCULPT_PIVOT_POSITION_MASK_BORDER,
+ "BORDER",
+ 0,
+ "Mask border",
+ "Sets the pivot position to the center of the border of the mask"},
+ {SCULPT_PIVOT_POSITION_ACTIVE_VERTEX,
+ "ACTIVE",
+ 0,
+ "Active vertex",
+ "Sets the pivot position to the active vertex position"},
+ {SCULPT_PIVOT_POSITION_CURSOR_SURFACE,
+ "SURFACE",
+ 0,
+ "Surface",
+ "Sets the pivot position to the surface under the cursor"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int sculpt_set_pivot_position_exec(bContext *C, wmOperator *op)
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ ARegion *region = CTX_wm_region(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+
+ int mode = RNA_enum_get(op->ptr, "mode");
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true);
+
+ /* Pivot to center. */
+ if (mode == SCULPT_PIVOT_POSITION_ORIGIN) {
+ zero_v3(ss->pivot_pos);
+ }
+ /* Pivot to active vertex. */
+ else if (mode == SCULPT_PIVOT_POSITION_ACTIVE_VERTEX) {
+ copy_v3_v3(ss->pivot_pos, SCULPT_active_vertex_co_get(ss));
+ }
+ /* Pivot to raycast surface. */
+ else if (mode == SCULPT_PIVOT_POSITION_CURSOR_SURFACE) {
+ float stroke_location[3];
+ float mouse[2];
+ mouse[0] = RNA_float_get(op->ptr, "mouse_x");
+ mouse[1] = RNA_float_get(op->ptr, "mouse_y");
+ if (SCULPT_stroke_get_location(C, stroke_location, mouse)) {
+ copy_v3_v3(ss->pivot_pos, stroke_location);
+ }
+ }
+ else {
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+
+ float avg[3];
+ int total = 0;
+ zero_v3(avg);
+
+ /* Pivot to unmasked. */
+ if (mode == SCULPT_PIVOT_POSITION_UNMASKED) {
+ for (int n = 0; n < totnode; n++) {
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ const float mask = (vd.mask) ? *vd.mask : 0.0f;
+ if (mask < 1.0f) {
+ if (SCULPT_check_vertex_pivot_symmetry(vd.co, ss->pivot_pos, symm)) {
+ add_v3_v3(avg, vd.co);
+ total++;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+ }
+ /* Pivot to mask border. */
+ else if (mode == SCULPT_PIVOT_POSITION_MASK_BORDER) {
+ const float threshold = 0.2f;
+
+ for (int n = 0; n < totnode; n++) {
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ const float mask = (vd.mask) ? *vd.mask : 0.0f;
+ if (mask < (0.5f + threshold) && mask > (0.5f - threshold)) {
+ if (SCULPT_check_vertex_pivot_symmetry(vd.co, ss->pivot_pos, symm)) {
+ add_v3_v3(avg, vd.co);
+ total++;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+ }
+
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ copy_v3_v3(ss->pivot_pos, avg);
+ }
+
+ MEM_SAFE_FREE(nodes);
+ }
+
+ ED_region_tag_redraw(region);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+
+ return OPERATOR_FINISHED;
+}
+
+static int sculpt_set_pivot_position_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ RNA_float_set(op->ptr, "mouse_x", event->mval[0]);
+ RNA_float_set(op->ptr, "mouse_y", event->mval[1]);
+ return sculpt_set_pivot_position_exec(C, op);
+}
+
+void SCULPT_OT_set_pivot_position(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Set Pivot Position";
+ ot->idname = "SCULPT_OT_set_pivot_position";
+ ot->description = "Sets the sculpt transform pivot position";
+
+ /* API callbacks. */
+ ot->invoke = sculpt_set_pivot_position_invoke;
+ ot->exec = sculpt_set_pivot_position_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_enum(ot->srna,
+ "mode",
+ prop_sculpt_pivot_position_types,
+ SCULPT_PIVOT_POSITION_UNMASKED,
+ "Mode",
+ "");
+
+ RNA_def_float(ot->srna,
+ "mouse_x",
+ 0.0f,
+ 0.0f,
+ FLT_MAX,
+ "Mouse Position X",
+ "Position of the mouse used for \"Surface\" mode",
+ 0.0f,
+ 10000.0f);
+ RNA_def_float(ot->srna,
+ "mouse_y",
+ 0.0f,
+ 0.0f,
+ FLT_MAX,
+ "Mouse Position Y",
+ "Position of the mouse used for \"Surface\" mode",
+ 0.0f,
+ 10000.0f);
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 366eeae219c..912a6e1aaf6 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2006 by Nicholas Bishop
@@ -26,33 +26,37 @@
#include "MEM_guardedalloc.h"
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_string.h"
-#include "BLI_listbase.h"
-#include "BLI_ghash.h"
#include "BLI_task.h"
#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_screen_types.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_multires.h"
-#include "BKE_paint.h"
+#include "BKE_global.h"
#include "BKE_key.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_multires.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
#include "BKE_scene.h"
-#include "BKE_subsurf.h"
#include "BKE_subdiv_ccg.h"
+#include "BKE_subsurf.h"
#include "BKE_undo_system.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
+
+// XXX: Ideally should be no direct call to such low level things.
+#include "BKE_subdiv_eval.h"
#include "DEG_depsgraph.h"
@@ -66,6 +70,45 @@
#include "bmesh.h"
#include "sculpt_intern.h"
+/* Implementation of undo system for objects in sculpt mode.
+ *
+ * Each undo step in sculpt mode consists of list of nodes, each node contains:
+ * - Node type
+ * - Data for this type.
+ *
+ * Node type used for undo depends on specific operation and active sculpt mode
+ * ("regular" or dynamic topology).
+ *
+ * Regular sculpt brushes will use COORDS, HIDDEN or MASK nodes. These nodes are
+ * created for every BVH node which is affected by the brush. The undo push for
+ * the node happens BEFORE modifications. This makes the operation undo to work
+ * in the following way: for every node in the undo step swap happens between
+ * node in the undo stack and the corresponding value in the BVH. This is how
+ * redo is possible after undo.
+ *
+ * The COORDS, HIDDEN or MASK type of nodes contains arrays of the corresponding
+ * values.
+ *
+ * Operations like Symmetrize are using GEOMETRY type of nodes which pushes the
+ * entire state of the mesh to the undo stack. This node contains all CustomData
+ * layers.
+ *
+ * The tricky aspect of this undo node type is that it stores mesh before and
+ * after modification. This allows the undo system to both undo and redo the
+ * symmetrize operation within the pre-modified-push of other node type
+ * behavior, but it uses more memory that it seems it should be.
+ *
+ * The dynamic topology undo nodes are handled somewhat separately from all
+ * other ones and the idea there is to store log of operations: which vertices
+ * and faces have been added or removed.
+ *
+ * Begin of dynamic topology sculpting mode have own node type. It contains an
+ * entire copy of mesh since just enabling the dynamic topology mode already
+ * does modifications on it.
+ *
+ * End of dynamic topology and symmetrize in this mode are handled in a special
+ * manner as well. */
+
typedef struct UndoSculpt {
ListBase nodes;
@@ -79,7 +122,7 @@ static void update_cb(PBVHNode *node, void *rebuild)
BKE_pbvh_node_mark_update(node);
BKE_pbvh_node_mark_update_mask(node);
if (*((bool *)rebuild)) {
- BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_mark_update_visibility(node);
}
BKE_pbvh_node_fully_hidden_set(node, 0);
}
@@ -119,7 +162,7 @@ static void update_cb_partial(PBVHNode *node, void *userdata)
static bool test_swap_v3_v3(float a[3], float b[3])
{
- /* no need for float comparison here (memory is exactly equal or not) */
+ /* No need for float comparison here (memory is exactly equal or not). */
if (memcmp(a, b, sizeof(float[3])) != 0) {
swap_v3_v3(a, b);
return true;
@@ -151,10 +194,10 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
int *index;
if (unode->maxvert) {
- /* regular mesh restore */
+ /* Regular mesh restore. */
if (ss->shapekey_active && !STREQ(ss->shapekey_active->name, unode->shapeName)) {
- /* shape key has been changed before calling undo operator */
+ /* Shape key has been changed before calling undo operator. */
Key *key = BKE_key_from_object(ob);
KeyBlock *kb = key ? BKE_keyblock_find_name(key, unode->shapeName) : NULL;
@@ -166,12 +209,12 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
}
else {
- /* key has been removed -- skip this undo node */
- return 0;
+ /* Key has been removed -- skip this undo node. */
+ return false;
}
}
- /* no need for float comparison here (memory is exactly equal or not) */
+ /* No need for float comparison here (memory is exactly equal or not). */
index = unode->index;
mvert = ss->mvert;
@@ -197,11 +240,11 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
}
}
- /* propagate new coords to keyblock */
- sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos);
+ /* Propagate new coords to keyblock. */
+ SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos);
- /* pbvh uses it's own mvert array, so coords should be */
- /* propagated to pbvh here */
+ /* PBVH uses it's own mvert array, so coords should be */
+ /* propagated to PBVH here. */
BKE_pbvh_vert_coords_apply(ss->pbvh, vertCos, ss->shapekey_active->totelem);
MEM_freeN(vertCos);
@@ -230,7 +273,7 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
}
}
else if (unode->maxgrid && subdiv_ccg != NULL) {
- /* multires restore */
+ /* Multires restore. */
CCGElem **grids, *grid;
CCGKey key;
float(*co)[3];
@@ -250,7 +293,7 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
}
}
- return 1;
+ return true;
}
static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode)
@@ -259,12 +302,11 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode)
Object *ob = OBACT(view_layer);
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
- int i;
if (unode->maxvert) {
MVert *mvert = ss->mvert;
- for (i = 0; i < unode->totvert; i++) {
+ for (int i = 0; i < unode->totvert; i++) {
MVert *v = &mvert[unode->index[i]];
if ((BLI_BITMAP_TEST(unode->vert_hidden, i) != 0) != ((v->flag & ME_HIDE) != 0)) {
BLI_BITMAP_FLIP(unode->vert_hidden, i);
@@ -276,12 +318,12 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode)
else if (unode->maxgrid && subdiv_ccg != NULL) {
BLI_bitmap **grid_hidden = subdiv_ccg->grid_hidden;
- for (i = 0; i < unode->totgrid; i++) {
+ for (int i = 0; i < unode->totgrid; i++) {
SWAP(BLI_bitmap *, unode->grid_hidden[i], grid_hidden[unode->grids[i]]);
}
}
- return 1;
+ return true;
}
static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode)
@@ -292,16 +334,16 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode)
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
MVert *mvert;
float *vmask;
- int *index, i, j;
+ int *index;
if (unode->maxvert) {
- /* regular mesh restore */
+ /* Regular mesh restore. */
index = unode->index;
mvert = ss->mvert;
vmask = ss->vmask;
- for (i = 0; i < unode->totvert; i++) {
+ for (int i = 0; i < unode->totvert; i++) {
if (vmask[index[i]] != unode->mask[i]) {
SWAP(float, vmask[index[i]], unode->mask[i]);
mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
@@ -309,7 +351,7 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode)
}
}
else if (unode->maxgrid && subdiv_ccg != NULL) {
- /* multires restore */
+ /* Multires restore. */
CCGElem **grids, *grid;
CCGKey key;
float *mask;
@@ -320,16 +362,28 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode)
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
mask = unode->mask;
- for (j = 0; j < unode->totgrid; j++) {
+ for (int j = 0; j < unode->totgrid; j++) {
grid = grids[unode->grids[j]];
- for (i = 0; i < gridsize * gridsize; i++, mask++) {
+ for (int i = 0; i < gridsize * gridsize; i++, mask++) {
SWAP(float, *CCG_elem_offset_mask(&key, grid, i), *mask);
}
}
}
- return 1;
+ return true;
+}
+
+static bool sculpt_undo_restore_face_sets(bContext *C, SculptUndoNode *unode)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Mesh *me = BKE_object_get_original_mesh(ob);
+ int *face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
+ for (int i = 0; i < me->totpoly; i++) {
+ face_sets[i] = unode->face_sets[i];
+ }
+ return false;
}
static void sculpt_undo_bmesh_restore_generic_task_cb(
@@ -361,9 +415,9 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
- PBVHParallelSettings settings;
+ TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BKE_pbvh_parallel_range(
+ BLI_task_parallel_range(
0, totnode, nodes, sculpt_undo_bmesh_restore_generic_task_cb, &settings);
if (nodes) {
@@ -371,28 +425,28 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
}
}
else {
- sculpt_pbvh_clear(ob);
+ SCULPT_pbvh_clear(ob);
}
}
-/* Create empty sculpt BMesh and enable logging */
+/* Create empty sculpt BMesh and enable logging. */
static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode)
{
SculptSession *ss = ob->sculpt;
Mesh *me = ob->data;
- sculpt_pbvh_clear(ob);
+ SCULPT_pbvh_clear(ob);
- /* Create empty BMesh and enable logging */
+ /* Create empty BMesh and enable logging. */
ss->bm = BM_mesh_create(&bm_mesh_allocsize_default,
&((struct BMeshCreateParams){
.use_toolflags = false,
}));
BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
- sculpt_dyntopo_node_layers_add(ss);
+ SCULPT_dyntopo_node_layers_add(ss);
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
- /* Restore the BMLog using saved entries */
+ /* Restore the BMLog using saved entries. */
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode->bm_entry);
}
@@ -402,13 +456,13 @@ static void sculpt_undo_bmesh_restore_begin(bContext *C,
SculptSession *ss)
{
if (unode->applied) {
- sculpt_dynamic_topology_disable(C, unode);
+ SCULPT_dynamic_topology_disable(C, unode);
unode->applied = false;
}
else {
sculpt_undo_bmesh_enable(ob, unode);
- /* Restore the mesh from the first log entry */
+ /* Restore the mesh from the first log entry. */
BM_log_redo(ss->bm, ss->bm_log);
unode->applied = true;
@@ -423,42 +477,96 @@ static void sculpt_undo_bmesh_restore_end(bContext *C,
if (unode->applied) {
sculpt_undo_bmesh_enable(ob, unode);
- /* Restore the mesh from the last log entry */
+ /* Restore the mesh from the last log entry. */
BM_log_undo(ss->bm, ss->bm_log);
unode->applied = false;
}
else {
- /* Disable dynamic topology sculpting */
- sculpt_dynamic_topology_disable(C, NULL);
+ /* Disable dynamic topology sculpting. */
+ SCULPT_dynamic_topology_disable(C, NULL);
unode->applied = true;
}
}
-static void sculpt_undo_geometry_restore(SculptUndoNode *unode, Object *ob)
+static void sculpt_undo_geometry_store_data(SculptUndoNodeGeometry *geometry, Object *object)
{
- Mesh *me;
- sculpt_pbvh_clear(ob);
- me = ob->data;
- CustomData_free(&me->vdata, me->totvert);
- CustomData_free(&me->edata, me->totedge);
- CustomData_free(&me->fdata, me->totface);
- CustomData_free(&me->ldata, me->totloop);
- CustomData_free(&me->pdata, me->totpoly);
- me->totvert = unode->geom_totvert;
- me->totedge = unode->geom_totedge;
- me->totloop = unode->geom_totloop;
- me->totpoly = unode->geom_totpoly;
- me->totface = 0;
+ Mesh *mesh = object->data;
+
+ BLI_assert(!geometry->is_initialized);
+ geometry->is_initialized = true;
+
+ CustomData_copy(&mesh->vdata, &geometry->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, mesh->totvert);
+ CustomData_copy(&mesh->edata, &geometry->edata, CD_MASK_MESH.emask, CD_DUPLICATE, mesh->totedge);
+ CustomData_copy(&mesh->ldata, &geometry->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, mesh->totloop);
+ CustomData_copy(&mesh->pdata, &geometry->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, mesh->totpoly);
+
+ geometry->totvert = mesh->totvert;
+ geometry->totedge = mesh->totedge;
+ geometry->totloop = mesh->totloop;
+ geometry->totpoly = mesh->totpoly;
+}
+
+static void sculpt_undo_geometry_restore_data(SculptUndoNodeGeometry *geometry, Object *object)
+{
+ Mesh *mesh = object->data;
+
+ BLI_assert(geometry->is_initialized);
+
+ CustomData_free(&mesh->vdata, mesh->totvert);
+ CustomData_free(&mesh->edata, mesh->totedge);
+ CustomData_free(&mesh->fdata, mesh->totface);
+ CustomData_free(&mesh->ldata, mesh->totloop);
+ CustomData_free(&mesh->pdata, mesh->totpoly);
+
+ mesh->totvert = geometry->totvert;
+ mesh->totedge = geometry->totedge;
+ mesh->totloop = geometry->totloop;
+ mesh->totpoly = geometry->totpoly;
+ mesh->totface = 0;
+
CustomData_copy(
- &unode->geom_vdata, &me->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, unode->geom_totvert);
+ &geometry->vdata, &mesh->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, geometry->totvert);
CustomData_copy(
- &unode->geom_edata, &me->edata, CD_MASK_MESH.emask, CD_DUPLICATE, unode->geom_totedge);
+ &geometry->edata, &mesh->edata, CD_MASK_MESH.emask, CD_DUPLICATE, geometry->totedge);
CustomData_copy(
- &unode->geom_ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, unode->geom_totloop);
+ &geometry->ldata, &mesh->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop);
CustomData_copy(
- &unode->geom_pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, unode->geom_totpoly);
- BKE_mesh_update_customdata_pointers(me, false);
+ &geometry->pdata, &mesh->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly);
+
+ BKE_mesh_update_customdata_pointers(mesh, false);
+}
+
+static void sculpt_undo_geometry_free_data(SculptUndoNodeGeometry *geometry)
+{
+ if (geometry->totvert) {
+ CustomData_free(&geometry->vdata, geometry->totvert);
+ }
+ if (geometry->totedge) {
+ CustomData_free(&geometry->edata, geometry->totedge);
+ }
+ if (geometry->totloop) {
+ CustomData_free(&geometry->ldata, geometry->totloop);
+ }
+ if (geometry->totpoly) {
+ CustomData_free(&geometry->pdata, geometry->totpoly);
+ }
+}
+
+static void sculpt_undo_geometry_restore(SculptUndoNode *unode, Object *object)
+{
+ if (unode->geometry_clear_pbvh) {
+ SCULPT_pbvh_clear(object);
+ }
+
+ if (unode->applied) {
+ sculpt_undo_geometry_restore_data(&unode->geometry_modified, object);
+ unode->applied = false;
+ }
+ else {
+ sculpt_undo_geometry_restore_data(&unode->geometry_original, object);
+ unode->applied = true;
+ }
}
/* Handle all dynamic-topology updates
@@ -502,13 +610,13 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
bool need_mask = false;
for (unode = lb->first; unode; unode = unode->next) {
- /* restore pivot */
+ /* Restore pivot. */
copy_v3_v3(ss->pivot_pos, unode->pivot_pos);
copy_v3_v3(ss->pivot_rot, unode->pivot_rot);
if (STREQ(unode->idname, ob->id.name)) {
if (unode->type == SCULPT_UNDO_MASK) {
- /* is possible that we can't do the mask undo (below)
- * because of the vertex count */
+ /* Is possible that we can't do the mask undo (below)
+ * because of the vertex count. */
need_mask = true;
break;
}
@@ -519,26 +627,44 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
if (lb->first) {
unode = lb->first;
- if (unode->type == SCULPT_UNDO_GEOMETRY) {
- if (unode->applied) {
- sculpt_undo_geometry_restore(unode->next, ob);
- unode->next->applied = true;
- unode->applied = false;
+ if (unode->type == SCULPT_UNDO_FACE_SETS) {
+ sculpt_undo_restore_face_sets(C, unode);
+
+ rebuild = true;
+ BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, need_mask);
+
+ SCULPT_visibility_sync_all_face_sets_to_vertices(ss);
+
+ BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
+ BKE_mesh_flush_hidden_from_verts(ob->data);
}
- else {
- sculpt_undo_geometry_restore(unode, ob);
- unode->next->applied = false;
- unode->applied = true;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
+ if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
- BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask);
+
+ unode->applied = true;
return;
}
}
- BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask);
+ if (lb->first != NULL) {
+ /* Only do early object update for edits if first node needs this.
+ * Undo steps like geometry does not need object to be updated before they run and will
+ * ensure object is updated after the node is handled. */
+ const SculptUndoNode *first_unode = (const SculptUndoNode *)lb->first;
+ if (first_unode->type != SCULPT_UNDO_GEOMETRY) {
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask);
+ }
- if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss)) {
- return;
+ if (sculpt_undo_bmesh_restore(C, lb->first, ob, ss)) {
+ return;
+ }
}
char *undo_modified_grids = NULL;
@@ -550,8 +676,8 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
continue;
}
- /* check if undo data matches current data well enough to
- * continue */
+ /* Check if undo data matches current data well enough to
+ * continue. */
if (unode->maxvert) {
if (ss->totvert != unode->maxvert) {
continue;
@@ -584,34 +710,50 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
update_mask = true;
}
break;
+ case SCULPT_UNDO_FACE_SETS:
+ break;
+
+ case SCULPT_UNDO_GEOMETRY:
+ sculpt_undo_geometry_restore(unode, ob);
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask);
+ break;
case SCULPT_UNDO_DYNTOPO_BEGIN:
case SCULPT_UNDO_DYNTOPO_END:
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
BLI_assert(!"Dynamic topology should've already been handled");
break;
- case SCULPT_UNDO_GEOMETRY:
- break;
}
}
if (use_multires_undo) {
- int max_grid;
- unode = lb->first;
- max_grid = unode->maxgrid;
- undo_modified_grids = MEM_callocN(sizeof(char) * max_grid, "undo_grids");
for (unode = lb->first; unode; unode = unode->next) {
+ if (!STREQ(unode->idname, ob->id.name)) {
+ continue;
+ }
+ if (unode->maxgrid == 0) {
+ continue;
+ }
+
+ if (undo_modified_grids == NULL) {
+ undo_modified_grids = MEM_callocN(sizeof(char) * unode->maxgrid, "undo_grids");
+ }
+
for (int i = 0; i < unode->totgrid; i++) {
undo_modified_grids[unode->grids[i]] = 1;
}
}
}
+ if (subdiv_ccg != NULL) {
+ BKE_subdiv_eval_refine_from_mesh(subdiv_ccg->subdiv, ob->data, NULL);
+ }
+
if (update || rebuild) {
bool tag_update = false;
- /* we update all nodes still, should be more clever, but also
+ /* We update all nodes still, should be more clever, but also
* needs to work correct when exiting/entering sculpt mode and
- * the nodes get recreated, though in that case it could do all */
+ * the nodes get recreated, though in that case it could do all. */
struct PartialUpdateData data = {
.rebuild = rebuild,
.pbvh = ss->pbvh,
@@ -619,10 +761,16 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
};
BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb_partial, &data);
BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw);
+
if (update_mask) {
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask);
}
+ if (update_visibility) {
+ SCULPT_visibility_sync_all_vertex_to_face_sets(ss);
+ BKE_pbvh_update_visibility(ss->pbvh);
+ }
+
if (BKE_sculpt_multires_active(scene, ob)) {
if (rebuild) {
multires_mark_as_modified(depsgraph, ob, MULTIRES_HIDDEN_MODIFIED);
@@ -632,14 +780,14 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
}
- tag_update |= ID_REAL_USERS(ob->data) > 1 || !BKE_sculptsession_use_pbvh_draw(ob, v3d);
+ tag_update |= ID_REAL_USERS(ob->data) > 1 || !BKE_sculptsession_use_pbvh_draw(ob, v3d) ||
+ ss->shapekey_active || ss->deform_modifiers_active;
- if (ss->shapekey_active || ss->deform_modifiers_active) {
+ if (tag_update) {
Mesh *mesh = ob->data;
BKE_mesh_calc_normals(mesh);
BKE_sculptsession_free_deformMats(ss);
- tag_update |= true;
}
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && update_visibility) {
@@ -651,7 +799,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
else {
- sculpt_update_object_bounding_box(ob);
+ SCULPT_update_object_bounding_box(ob);
}
}
@@ -697,17 +845,11 @@ static void sculpt_undo_free_list(ListBase *lb)
BM_log_entry_drop(unode->bm_entry);
}
- if (unode->geom_totvert) {
- CustomData_free(&unode->geom_vdata, unode->geom_totvert);
- }
- if (unode->geom_totedge) {
- CustomData_free(&unode->geom_edata, unode->geom_totedge);
- }
- if (unode->geom_totloop) {
- CustomData_free(&unode->geom_ldata, unode->geom_totloop);
- }
- if (unode->geom_totpoly) {
- CustomData_free(&unode->geom_pdata, unode->geom_totpoly);
+ sculpt_undo_geometry_free_data(&unode->geometry_original);
+ sculpt_undo_geometry_free_data(&unode->geometry_modified);
+
+ if (unode->face_sets) {
+ MEM_freeN(unode->face_sets);
}
MEM_freeN(unode);
@@ -739,7 +881,7 @@ static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
}
#endif
-SculptUndoNode *sculpt_undo_get_node(PBVHNode *node)
+SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node)
{
UndoSculpt *usculpt = sculpt_undo_get_nodes();
@@ -750,6 +892,17 @@ SculptUndoNode *sculpt_undo_get_node(PBVHNode *node)
return BLI_findptr(&usculpt->nodes, node, offsetof(SculptUndoNode, node));
}
+SculptUndoNode *SCULPT_undo_get_first_node()
+{
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
+
+ if (usculpt == NULL) {
+ return NULL;
+ }
+
+ return usculpt->nodes.first;
+}
+
static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh, SculptUndoNode *unode)
{
PBVHNode *node = unode->node;
@@ -772,16 +925,43 @@ static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh, SculptUndoNode *unode
}
}
+/* Allocate node and initialize its default fields specific for the given undo type.
+ * Will also add the node to the list in the undo step. */
+static SculptUndoNode *sculpt_undo_alloc_node_type(Object *object, SculptUndoType type)
+{
+ SculptUndoNode *unode = MEM_callocN(sizeof(SculptUndoNode), "SculptUndoNode");
+ BLI_strncpy(unode->idname, object->id.name, sizeof(unode->idname));
+ unode->type = type;
+
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
+ BLI_addtail(&usculpt->nodes, unode);
+
+ return unode;
+}
+
+/* Will return first existing undo node of the given type.
+ * If such node does not exist will allocate node of this type, register it in the undo step and
+ * return it. */
+static SculptUndoNode *sculpt_undo_find_or_alloc_node_type(Object *object, SculptUndoType type)
+{
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
+
+ LISTBASE_FOREACH (SculptUndoNode *, unode, &usculpt->nodes) {
+ if (unode->type == type) {
+ return unode;
+ }
+ }
+
+ return sculpt_undo_alloc_node_type(object, type);
+}
+
static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, SculptUndoType type)
{
UndoSculpt *usculpt = sculpt_undo_get_nodes();
- SculptUndoNode *unode;
SculptSession *ss = ob->sculpt;
int totvert, allvert, totgrid, maxgrid, gridsize, *grids;
- unode = MEM_callocN(sizeof(SculptUndoNode), "SculptUndoNode");
- BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
- unode->type = type;
+ SculptUndoNode *unode = sculpt_undo_alloc_node_type(ob, type);
unode->node = node;
if (node) {
@@ -794,9 +974,9 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
maxgrid = 0;
}
- /* we will use this while sculpting, is mapalloc slow to access then? */
+ /* We will use this while sculpting, is mapalloc slow to access then? */
- /* general TODO, fix count_alloc */
+ /* General TODO, fix count_alloc. */
switch (type) {
case SCULPT_UNDO_COORDS:
unode->co = MEM_mapallocN(sizeof(float[3]) * allvert, "SculptUndoNode.co");
@@ -824,20 +1004,19 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
BLI_assert(!"Dynamic topology should've already been handled");
case SCULPT_UNDO_GEOMETRY:
+ case SCULPT_UNDO_FACE_SETS:
break;
}
- BLI_addtail(&usculpt->nodes, unode);
-
if (maxgrid) {
- /* multires */
+ /* Multires. */
unode->maxgrid = maxgrid;
unode->totgrid = totgrid;
unode->gridsize = gridsize;
unode->grids = MEM_mapallocN(sizeof(int) * totgrid, "SculptUndoNode.grids");
}
else {
- /* regular mesh */
+ /* Regular mesh. */
unode->maxvert = ss->totvert;
unode->index = MEM_mapallocN(sizeof(int) * allvert, "SculptUndoNode.index");
}
@@ -877,7 +1056,7 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
PBVHNode *node = unode->node;
if (unode->grids) {
- /* already stored during allocation */
+ /* Already stored during allocation. */
}
else {
MVert *mvert;
@@ -905,30 +1084,48 @@ static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode)
BKE_pbvh_vertex_iter_end;
}
-static SculptUndoNode *sculpt_undo_geometry_push(Object *ob, SculptUndoType type)
+static SculptUndoNodeGeometry *sculpt_undo_geometry_get(SculptUndoNode *unode)
{
- UndoSculpt *usculpt = sculpt_undo_get_nodes();
- Mesh *me = ob->data;
- bool applied;
+ if (!unode->geometry_original.is_initialized) {
+ return &unode->geometry_original;
+ }
+
+ BLI_assert(!unode->geometry_modified.is_initialized);
+ return &unode->geometry_modified;
+}
+
+static SculptUndoNode *sculpt_undo_geometry_push(Object *object, SculptUndoType type)
+{
+ SculptUndoNode *unode = sculpt_undo_find_or_alloc_node_type(object, type);
+ unode->applied = false;
+ unode->geometry_clear_pbvh = true;
+
+ SculptUndoNodeGeometry *geometry = sculpt_undo_geometry_get(unode);
+ sculpt_undo_geometry_store_data(geometry, object);
+
+ return unode;
+}
+
+static SculptUndoNode *sculpt_undo_face_sets_push(Object *ob, SculptUndoType type)
+{
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
SculptUndoNode *unode = usculpt->nodes.first;
- /* Store the original mesh in the first node, modifications in the second */
- applied = unode != NULL;
unode = MEM_callocN(sizeof(*unode), __func__);
BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
unode->type = type;
- unode->applied = applied;
+ unode->applied = true;
- CustomData_copy(&me->vdata, &unode->geom_vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, me->totvert);
- CustomData_copy(&me->edata, &unode->geom_edata, CD_MASK_MESH.emask, CD_DUPLICATE, me->totedge);
- CustomData_copy(&me->ldata, &unode->geom_ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, me->totloop);
- CustomData_copy(&me->pdata, &unode->geom_pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, me->totpoly);
- unode->geom_totvert = me->totvert;
- unode->geom_totedge = me->totedge;
- unode->geom_totloop = me->totloop;
- unode->geom_totpoly = me->totpoly;
+ Mesh *me = BKE_object_get_original_mesh(ob);
+
+ unode->face_sets = MEM_callocN(me->totpoly * sizeof(int), "sculpt face sets");
+
+ int *face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
+ for (int i = 0; i < me->totpoly; i++) {
+ unode->face_sets[i] = face_sets[i];
+ }
BLI_addtail(&usculpt->nodes, unode);
@@ -955,25 +1152,13 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
BM_log_before_all_removed(ss->bm, ss->bm_log);
}
else if (type == SCULPT_UNDO_DYNTOPO_BEGIN) {
- Mesh *me = ob->data;
-
/* Store a copy of the mesh's current vertices, loops, and
* polys. A full copy like this is needed because entering
* dynamic-topology immediately does topological edits
* (converting polys to triangles) that the BMLog can't
- * fully restore from */
- CustomData_copy(
- &me->vdata, &unode->geom_vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, me->totvert);
- CustomData_copy(
- &me->edata, &unode->geom_edata, CD_MASK_MESH.emask, CD_DUPLICATE, me->totedge);
- CustomData_copy(
- &me->ldata, &unode->geom_ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, me->totloop);
- CustomData_copy(
- &me->pdata, &unode->geom_pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, me->totpoly);
- unode->geom_totvert = me->totvert;
- unode->geom_totedge = me->totedge;
- unode->geom_totloop = me->totloop;
- unode->geom_totpoly = me->totpoly;
+ * fully restore from. */
+ SculptUndoNodeGeometry *geometry = &unode->geometry_bmesh_enter;
+ sculpt_undo_geometry_store_data(geometry, ob);
unode->bm_entry = BM_log_entry_add(ss->bm_log);
BM_log_all_added(ss->bm, ss->bm_log);
@@ -990,7 +1175,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
case SCULPT_UNDO_COORDS:
case SCULPT_UNDO_MASK:
/* Before any vertex values get modified, ensure their
- * original positions are logged */
+ * original positions are logged. */
BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
{
BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset);
@@ -1018,6 +1203,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
case SCULPT_UNDO_DYNTOPO_END:
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
case SCULPT_UNDO_GEOMETRY:
+ case SCULPT_UNDO_FACE_SETS:
break;
}
}
@@ -1025,19 +1211,19 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
return unode;
}
-SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
+SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
{
SculptSession *ss = ob->sculpt;
SculptUndoNode *unode;
- /* list is manipulated by multiple threads, so we lock */
+ /* List is manipulated by multiple threads, so we lock. */
BLI_thread_lock(LOCK_CUSTOM1);
ss->needs_flush_to_id = 1;
if (ss->bm || ELEM(type, SCULPT_UNDO_DYNTOPO_BEGIN, SCULPT_UNDO_DYNTOPO_END)) {
/* Dynamic topology stores only one undo node per stroke,
- * regardless of the number of PBVH nodes modified */
+ * regardless of the number of PBVH nodes modified. */
unode = sculpt_undo_bmesh_push(ob, node, type);
BLI_thread_unlock(LOCK_CUSTOM1);
return unode;
@@ -1047,7 +1233,12 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
BLI_thread_unlock(LOCK_CUSTOM1);
return unode;
}
- else if ((unode = sculpt_undo_get_node(node))) {
+ else if (type == SCULPT_UNDO_FACE_SETS) {
+ unode = sculpt_undo_face_sets_push(ob, type);
+ BLI_thread_unlock(LOCK_CUSTOM1);
+ return unode;
+ }
+ else if ((unode = SCULPT_undo_get_node(node))) {
BLI_thread_unlock(LOCK_CUSTOM1);
return unode;
}
@@ -1087,14 +1278,15 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
BLI_assert(!"Dynamic topology should've already been handled");
case SCULPT_UNDO_GEOMETRY:
+ case SCULPT_UNDO_FACE_SETS:
break;
}
- /* store sculpt pivot */
+ /* Store sculpt pivot. */
copy_v3_v3(unode->pivot_pos, ss->pivot_pos);
copy_v3_v3(unode->pivot_rot, ss->pivot_rot);
- /* store active shape key */
+ /* Store active shape key. */
if (ss->shapekey_active) {
BLI_strncpy(unode->shapeName, ss->shapekey_active->name, sizeof(ss->shapekey_active->name));
}
@@ -1107,35 +1299,42 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
return unode;
}
-void sculpt_undo_push_begin(const char *name)
+void SCULPT_undo_push_begin(const char *name)
{
UndoStack *ustack = ED_undo_stack_get();
- bContext *C = NULL; /* special case, we never read from this. */
+
+ /* Special case, we never read from this. */
+ bContext *C = NULL;
+
BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_SCULPT);
}
-void sculpt_undo_push_end(void)
+void SCULPT_undo_push_end(void)
+{
+ SCULPT_undo_push_end_ex(false);
+}
+
+void SCULPT_undo_push_end_ex(const bool use_nested_undo)
{
UndoSculpt *usculpt = sculpt_undo_get_nodes();
SculptUndoNode *unode;
- /* we don't need normals in the undo stack */
+ /* We don't need normals in the undo stack. */
for (unode = usculpt->nodes.first; unode; unode = unode->next) {
if (unode->no) {
MEM_freeN(unode->no);
unode->no = NULL;
}
-
- if (unode->node) {
- BKE_pbvh_node_layer_disp_free(unode->node);
- }
}
/* We could remove this and enforce all callers run in an operator using 'OPTYPE_UNDO'. */
wmWindowManager *wm = G_MAIN->wm.first;
- if (wm->op_undo_depth == 0) {
+ if (wm->op_undo_depth == 0 || use_nested_undo) {
UndoStack *ustack = ED_undo_stack_get();
BKE_undosys_step_push(ustack, NULL, NULL);
+ if (wm->op_undo_depth == 0) {
+ BKE_undosys_stack_limit_steps_and_memory_defaults(ustack);
+ }
WM_file_tag_modified();
}
}
@@ -1146,14 +1345,14 @@ void sculpt_undo_push_end(void)
typedef struct SculptUndoStep {
UndoStep step;
- /* note: will split out into list for multi-object-sculpt-mode. */
+ /* Note: will split out into list for multi-object-sculpt-mode. */
UndoSculpt data;
} SculptUndoStep;
static void sculpt_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p)
{
SculptUndoStep *us = (SculptUndoStep *)us_p;
- /* dummy, memory is cleared anyway. */
+ /* Dummy, memory is cleared anyway. */
BLI_listbase_clear(&us->data.nodes);
}
@@ -1161,7 +1360,7 @@ static bool sculpt_undosys_step_encode(struct bContext *UNUSED(C),
struct Main *bmain,
UndoStep *us_p)
{
- /* dummy, encoding is done along the way by adding tiles
+ /* Dummy, encoding is done along the way by adding tiles
* to the current 'SculptUndoStep' added by encode_init. */
SculptUndoStep *us = (SculptUndoStep *)us_p;
us->step.data_size = us->data.undo_size;
@@ -1248,7 +1447,7 @@ static void sculpt_undosys_step_decode(
Object *ob = OBACT(view_layer);
if (ob && (ob->type == OB_MESH)) {
if (ob->mode & OB_MODE_SCULPT) {
- /* pass */
+ /* Pass. */
}
else {
ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
@@ -1287,14 +1486,14 @@ static void sculpt_undosys_step_free(UndoStep *us_p)
void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name)
{
- sculpt_undo_push_begin(name);
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY);
+ SCULPT_undo_push_begin(name);
+ SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY);
}
void ED_sculpt_undo_geometry_end(struct Object *ob)
{
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY);
- sculpt_undo_push_end();
+ SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY);
+ SCULPT_undo_push_end();
}
/* Export for ED_undo_sys. */
@@ -1331,3 +1530,96 @@ static UndoSculpt *sculpt_undo_get_nodes(void)
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Undo for changes happening on a base mesh for multires sculpting.
+ *
+ * Use this for multires operators which changes base mesh and which are to be
+ * possible. Example of such operators is Apply Base.
+ *
+ * Usage:
+ *
+ * static int operator_exec((bContext *C, wmOperator *op) {
+ *
+ * ED_sculpt_undo_push_mixed_begin(C, op->type->name);
+ * // Modify base mesh.
+ * ED_sculpt_undo_push_mixed_end(C, op->type->name);
+ *
+ * return OPERATOR_FINISHED;
+ * }
+ *
+ * If object is not in sculpt mode or sculpt does not happen on multires then
+ * regular ED_undo_push() is used.
+ * *
+ * \{ */
+
+static bool sculpt_undo_use_multires_mesh(bContext *C)
+{
+ if (BKE_paintmode_get_active_from_context(C) != PAINT_MODE_SCULPT) {
+ return false;
+ }
+
+ Object *object = CTX_data_active_object(C);
+ SculptSession *sculpt_session = object->sculpt;
+
+ return sculpt_session->multires.active;
+}
+
+static void sculpt_undo_push_all_grids(Object *object)
+{
+ SculptSession *ss = object->sculpt;
+
+ /* It is possible that undo push is done from an object state where there is no PBVH. This
+ * happens, for example, when an operation which tagged for geometry update was performed prior
+ * to the current operation without making any stroke inbetween.
+ *
+ * Skip pushing nodes based on the following logic: on redo SCULPT_UNDO_COORDS will ensure
+ * PBVH for the new base geometry, which will have same coordinates as if we create PBVH here. */
+ if (ss->pbvh == NULL) {
+ return;
+ }
+
+ PBVHNode **nodes;
+ int totnodes;
+
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnodes);
+ for (int i = 0; i < totnodes; i++) {
+ SculptUndoNode *unode = SCULPT_undo_push_node(object, nodes[i], SCULPT_UNDO_COORDS);
+ unode->node = NULL;
+ }
+
+ MEM_SAFE_FREE(nodes);
+}
+
+void ED_sculpt_undo_push_multires_mesh_begin(bContext *C, const char *str)
+{
+ if (!sculpt_undo_use_multires_mesh(C)) {
+ return;
+ }
+
+ Object *object = CTX_data_active_object(C);
+
+ SCULPT_undo_push_begin(str);
+
+ SculptUndoNode *geometry_unode = SCULPT_undo_push_node(object, NULL, SCULPT_UNDO_GEOMETRY);
+ geometry_unode->geometry_clear_pbvh = false;
+
+ sculpt_undo_push_all_grids(object);
+}
+
+void ED_sculpt_undo_push_multires_mesh_end(bContext *C, const char *str)
+{
+ if (!sculpt_undo_use_multires_mesh(C)) {
+ ED_undo_push(C, str);
+ return;
+ }
+
+ Object *object = CTX_data_active_object(C);
+
+ SculptUndoNode *geometry_unode = SCULPT_undo_push_node(object, NULL, SCULPT_UNDO_GEOMETRY);
+ geometry_unode->geometry_clear_pbvh = false;
+
+ SCULPT_undo_push_end();
+}
+
+/** \} */
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 5beaff5ef00..a1094dde749 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) Blender Foundation, 2002-2009
@@ -24,14 +24,14 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
-#include "BLI_math.h"
#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
@@ -43,9 +43,9 @@
#include "DEG_depsgraph.h"
-#include "ED_screen.h"
#include "ED_image.h"
#include "ED_mesh.h"
+#include "ED_screen.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -70,8 +70,8 @@ typedef struct UvAdjacencyElement {
} UvAdjacencyElement;
typedef struct UvEdge {
- unsigned int uv1;
- unsigned int uv2;
+ uint uv1;
+ uint uv2;
/* general use flag
* (Used to check if edge is boundary here, and propagates to adjacency elements) */
char flag;
@@ -313,9 +313,9 @@ static void uv_sculpt_stroke_apply(bContext *C,
{
float co[2], radius, radius_root;
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- unsigned int tool;
+ uint tool;
UvSculptData *sculptdata = (UvSculptData *)op->customdata;
SpaceImage *sima;
int invert;
@@ -327,11 +327,11 @@ static void uv_sculpt_stroke_apply(bContext *C,
tool = sculptdata->tool;
invert = sculptdata->invert ? -1 : 1;
alpha = BKE_brush_alpha_get(scene, brush);
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
sima = CTX_wm_space_image(C);
ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
radius = BKE_brush_size_get(scene, brush) / (width * zoomx);
aspectRatio = width / (float)height;
@@ -386,7 +386,7 @@ static void uv_sculpt_stroke_apply(bContext *C,
* Smooth Tool
*/
else if (tool == UV_SCULPT_TOOL_RELAX) {
- unsigned int method = toolsettings->uv_relax_method;
+ uint method = toolsettings->uv_relax_method;
if (method == UV_SCULPT_TOOL_RELAX_HC) {
HC_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio);
}
@@ -464,7 +464,7 @@ static int uv_element_offset_from_face_get(
return element - map->buf;
}
-static unsigned int uv_edge_hash(const void *key)
+static uint uv_edge_hash(const void *key)
{
const UvEdge *edge = key;
return (BLI_ghashutil_uinthash(edge->uv2) + BLI_ghashutil_uinthash(edge->uv1));
@@ -496,7 +496,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
if (data) {
int counter = 0, i;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float co[2];
BMFace *efa;
MLoopUV *luv;
@@ -542,7 +542,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
}
/* Mouse coordinates, useful for some functions like grab and sculpt all islands */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
/* we need to find the active island here */
if (do_island_optimization) {
@@ -704,7 +704,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
radius = BKE_brush_size_get(scene, brush);
sima = CTX_wm_space_image(C);
ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
aspectRatio = width / (float)height;
radius /= (width * zoomx);
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 69745663c02..81ac8a16d8a 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -21,10 +21,10 @@
* \ingroup edsnd
*/
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -33,15 +33,15 @@
#include "DNA_packedFile_types.h"
#include "DNA_scene_types.h"
-#include "DNA_space_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
+#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
@@ -206,7 +206,7 @@ static void SOUND_OT_open_mono(wmOperatorType *ot)
static void sound_update_animation_flags(Scene *scene);
-static int sound_update_animation_flags_cb(Sequence *seq, void *user_data)
+static int sound_update_animation_flags_fn(Sequence *seq, void *user_data)
{
struct FCurve *fcu;
Scene *scene = (Scene *)user_data;
@@ -258,7 +258,7 @@ static void sound_update_animation_flags(Scene *scene)
scene->id.tag |= LIB_TAG_DOIT;
SEQ_BEGIN (scene->ed, seq) {
- BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_cb, scene);
+ BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_fn, scene);
}
SEQ_END;
@@ -800,7 +800,7 @@ static int sound_unpack_exec(bContext *C, wmOperator *op)
int method = RNA_enum_get(op->ptr, "method");
bSound *sound = NULL;
- /* find the suppplied image by name */
+ /* find the supplied image by name */
if (RNA_struct_property_is_set(op->ptr, "id")) {
char sndname[MAX_ID_NAME - 2];
RNA_string_get(op->ptr, "id", sndname);
diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c
index c9c20adcab4..ed49a1ed6d6 100644
--- a/source/blender/editors/space_action/action_buttons.c
+++ b/source/blender/editors/space_action/action_buttons.c
@@ -21,10 +21,10 @@
* \ingroup spaction
*/
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index 5fdabea62c1..b5a0c4a9e22 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -21,10 +21,10 @@
* \ingroup spaction
*/
+#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <float.h>
#include "BLI_utildefines.h"
@@ -33,33 +33,32 @@
#include "DNA_anim_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_key_types.h"
+#include "DNA_mask_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_mask_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_nla.h"
-#include "BKE_scene.h"
#include "BKE_report.h"
+#include "BKE_scene.h"
#include "UI_view2d.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
-#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
-#include "ED_screen.h"
+#include "ED_keyframing.h"
#include "ED_markers.h"
#include "ED_mask.h"
+#include "ED_screen.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -100,7 +99,7 @@ AnimData *ED_actedit_animdata_from_context(bContext *C)
/* Create new action */
static bAction *action_create_new(bContext *C, bAction *oldact)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
bAction *action;
/* create action - the way to do this depends on whether we've got an
@@ -124,8 +123,8 @@ static bAction *action_create_new(bContext *C, bAction *oldact)
id_us_min(&action->id);
/* set ID-Root type */
- if (sa->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+ if (area->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)area->spacedata.first;
if (saction->mode == SACTCONT_SHAPEKEY) {
action->idroot = ID_KE;
@@ -165,13 +164,13 @@ static void actedit_change_action(bContext *C, bAction *act)
* 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions...
* OR
* The NLA Editor is active (i.e. Animation Data panel -> new action)
- * 2) The associated AnimData block must not be in tweakmode
+ * 2) The associated AnimData block must not be in tweak-mode.
*/
static bool action_new_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */
+ /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */
/* NOTE: unlike for pushdown,
* this operator needs to be run when creating an action from nothing... */
if (ED_operator_action_active(C)) {
@@ -250,7 +249,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
* or else the user gets decremented twice!
*/
if (ptr.type == &RNA_SpaceDopeSheetEditor) {
- SpaceAction *saction = (SpaceAction *)ptr.data;
+ SpaceAction *saction = ptr.data;
saction->action = NULL;
}
}
@@ -301,7 +300,7 @@ void ACTION_OT_new(wmOperatorType *ot)
/* Criteria:
* 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
* 2) There must be an action active
- * 3) The associated AnimData block must not be in tweakmode
+ * 3) The associated AnimData block must not be in tweak-mode
*/
static bool action_pushdown_poll(bContext *C)
{
@@ -309,7 +308,7 @@ static bool action_pushdown_poll(bContext *C)
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
AnimData *adt = ED_actedit_animdata_from_context(C);
- /* Check for AnimData, Actions, and that tweakmode is off */
+ /* Check for AnimData, Actions, and that tweak-mode is off. */
if (adt && saction->action) {
/* NOTE: We check this for the AnimData block in question and not the global flag,
* as the global flag may be left dirty by some of the browsing ops here.
@@ -331,9 +330,8 @@ static int action_pushdown_exec(bContext *C, wmOperator *op)
/* Do the deed... */
if (adt) {
- /* Perform the pushdown operation
- * - This will deal with all the AnimData-side usercounts
- */
+ /* Perform the push-down operation
+ * - This will deal with all the AnimData-side user-counts. */
if (action_has_motion(adt->action) == 0) {
/* action may not be suitable... */
BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
@@ -390,7 +388,7 @@ static int action_stash_exec(bContext *C, wmOperator *op)
if (BKE_nla_action_stash(adt)) {
/* The stash operation will remove the user already,
* so the flushing step later shouldn't double up
- * the usercount fixes. Hence, we must unset this ref
+ * the user-count fixes. Hence, we must unset this ref
* first before setting the new action.
*/
saction->action = NULL;
@@ -436,14 +434,14 @@ void ACTION_OT_stash(wmOperatorType *ot)
/* Criteria:
* 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
- * 2) The associated AnimData block must not be in tweakmode
+ * 2) The associated AnimData block must not be in tweak-mode
*/
static bool action_stash_create_poll(bContext *C)
{
if (ED_operator_action_active(C)) {
AnimData *adt = ED_actedit_animdata_from_context(C);
- /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */
+ /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */
/* NOTE: unlike for pushdown,
* this operator needs to be run when creating an action from nothing... */
if (adt) {
@@ -499,7 +497,7 @@ static int action_stash_create_exec(bContext *C, wmOperator *op)
/* The stash operation will remove the user already,
* so the flushing step later shouldn't double up
- * the usercount fixes. Hence, we must unset this ref
+ * the user-count fixes. Hence, we must unset this ref
* first before setting the new action.
*/
saction->action = NULL;
@@ -550,7 +548,7 @@ void ACTION_OT_stash_and_create(wmOperatorType *ot)
void ED_animedit_unlink_action(
bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* If the old action only has a single user (that it's about to lose),
* warn user about it
@@ -609,13 +607,13 @@ void ED_animedit_unlink_action(
BKE_nla_tweakmode_exit(adt);
/* Flush this to the Action Editor (if that's where this change was initiated) */
- if (sa->spacetype == SPACE_ACTION) {
+ if (area->spacetype == SPACE_ACTION) {
actedit_change_action(C, NULL);
}
}
else {
/* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */
- if (sa->spacetype == SPACE_ACTION) {
+ if (area->spacetype == SPACE_ACTION) {
/* clear action editor -> action */
actedit_change_action(C, NULL);
}
@@ -729,8 +727,8 @@ static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime)
static void action_layer_switch_strip(
AnimData *adt, NlaTrack *old_track, NlaStrip *old_strip, NlaTrack *nlt, NlaStrip *strip)
{
- /* Exit tweakmode on old strip
- * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it
+ /* Exit tweak-mode on old strip
+ * NOTE: We need to manually clear this stuff ourselves, as tweak-mode exit doesn't do it
*/
BKE_nla_tweakmode_exit(adt);
@@ -762,11 +760,11 @@ static void action_layer_switch_strip(
adt->flag |= ADT_NLA_SOLO_TRACK;
nlt->flag |= NLATRACK_SOLO;
- // TODO: Needs restpose flushing (when we get reference track)
+ // TODO: Needs rest-pose flushing (when we get reference track)
}
}
- /* Enter tweakmode again - hopefully we're now "it" */
+ /* Enter tweak-mode again - hopefully we're now "it" */
BKE_nla_tweakmode_enter(adt);
BLI_assert(adt->actstrip == strip);
}
@@ -779,7 +777,7 @@ static bool action_layer_next_poll(bContext *C)
if (ED_operator_action_active(C)) {
AnimData *adt = ED_actedit_animdata_from_context(C);
if (adt) {
- /* only allow if we're in tweakmode, and there's something above us... */
+ /* only allow if we're in tweak-mode, and there's something above us... */
if (adt->flag & ADT_NLA_EDIT_ON) {
/* We need to check if there are any tracks above the active one
* since the track the action comes from is not stored in AnimData
@@ -841,7 +839,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op)
}
else {
/* No more actions (strips) - Go back to editing the original active action
- * NOTE: This will mean exiting tweakmode...
+ * NOTE: This will mean exiting tweak-mode...
*/
BKE_nla_tweakmode_exit(adt);
@@ -856,13 +854,12 @@ static int action_layer_next_exec(bContext *C, wmOperator *op)
/* turn on NLA muting (to keep same effect) */
adt->flag |= ADT_NLA_EVAL_OFF;
- // TODO: Needs restpose flushing (when we get reference track)
+ // TODO: Needs rest-pose flushing (when we get reference track)
}
}
/* Update the action that this editor now uses
- * NOTE: The calls above have already handled the usercount/animdata side of things
- */
+ * NOTE: The calls above have already handled the user-count/anim-data side of things. */
actedit_change_action(C, adt->action);
return OPERATOR_FINISHED;
}
@@ -961,8 +958,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op)
}
/* Update the action that this editor now uses
- * NOTE: The calls above have already handled the usercount/animdata side of things
- */
+ * NOTE: The calls above have already handled the user-count/animdata side of things. */
actedit_change_action(C, adt->action);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 0c57113956d..52287b07b28 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -23,10 +23,10 @@
/* System includes ----------------------------------------------------- */
+#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <float.h>
#include "BLI_blenlib.h"
#include "BLI_math.h"
@@ -38,8 +38,8 @@
#include "DNA_cachefile_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
-#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "BKE_action.h"
#include "BKE_context.h"
@@ -64,13 +64,13 @@
/* Channel List */
/* left hand part */
-void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
+void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
size_t items;
/* build list of channels to draw */
@@ -81,7 +81,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
v2d->tot.ymin = -height;
/* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
- UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
+ UI_view2d_sync(NULL, ac->area, v2d, V2D_LOCK_COPY);
/* loop through channels, and set up drawing depending on their type */
{ /* first pass: just the standard GL-drawing for backdrop + text */
@@ -100,7 +100,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
}
}
{ /* second pass: widgets */
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
size_t channel_index = 0;
float ymax = ACHANNEL_FIRST_TOP(ac);
@@ -132,18 +132,18 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
#define EXTRA_SCROLL_PAD 100.0f
/* draw keyframes in each channel */
-void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
+void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
bDopeSheet *ads = &saction->ads;
AnimData *adt = NULL;
- unsigned char col1[4], col2[4];
- unsigned char col1a[4], col2a[4];
- unsigned char col1b[4], col2b[4];
+ uchar col1[4], col2[4];
+ uchar col1a[4], col2a[4];
+ uchar col1b[4], col2b[4];
const bool show_group_colors = !(saction->flag & SACTION_NODRAWGCOLORS);
@@ -212,10 +212,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
bActionGroup *agrp = ale->data;
if (show_group_colors && agrp->customCol) {
if (sel) {
- immUniformColor3ubvAlpha((unsigned char *)agrp->cs.select, col1a[3]);
+ immUniformColor3ubvAlpha((uchar *)agrp->cs.select, col1a[3]);
}
else {
- immUniformColor3ubvAlpha((unsigned char *)agrp->cs.solid, col2a[3]);
+ immUniformColor3ubvAlpha((uchar *)agrp->cs.solid, col2a[3]);
}
}
else {
@@ -226,8 +226,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
case ANIMTYPE_FCURVE: {
FCurve *fcu = ale->data;
if (show_group_colors && fcu->grp && fcu->grp->customCol) {
- immUniformColor3ubvAlpha((unsigned char *)fcu->grp->cs.active,
- sel ? col1[3] : col2[3]);
+ immUniformColor3ubvAlpha((uchar *)fcu->grp->cs.active, sel ? col1[3] : col2[3]);
}
else {
immUniformColor4ubv(sel ? col1 : col2);
@@ -243,8 +242,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
- unsigned char *color;
- unsigned char gpl_col[4];
+ uchar *color;
+ uchar gpl_col[4];
if ((show_group_colors) && (ale->type == ANIMTYPE_GPLAYER)) {
bGPDlayer *gpl = (bGPDlayer *)ale->data;
rgb_float_to_uchar(gpl_col, gpl->color);
@@ -266,7 +265,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
else if (ac->datatype == ANIMCONT_MASK) {
/* TODO --- this is a copy of gpencil */
/* frames less than one get less saturated background */
- unsigned char *color = sel ? col1 : col2;
+ uchar *color = sel ? col1 : col2;
immUniformColor4ubv(color);
immRectf(pos, 0.0f, ymin, v2d->cur.xmin, ymax);
@@ -562,7 +561,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
/* Iterate over pointcaches on the active object, and draw each one's range. */
float y_offset = 0.0f;
const float cache_draw_height = 4.0f * UI_DPI_FAC * U.pixelsize;
- for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
+ LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
if (timeline_cache_is_hidden_by_setting(saction, pid)) {
continue;
}
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 6e44992ea6e..e90122f2585 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -21,10 +21,10 @@
* \ingroup spaction
*/
+#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <float.h>
#include "BLI_blenlib.h"
#include "BLI_math.h"
@@ -35,9 +35,9 @@
#include "DNA_anim_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_key_types.h"
+#include "DNA_mask_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_mask_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -47,8 +47,8 @@
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
-#include "BKE_gpencil.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
#include "BKE_key.h"
#include "BKE_nla.h"
#include "BKE_report.h"
@@ -57,11 +57,11 @@
#include "ED_anim_api.h"
#include "ED_gpencil.h"
-#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
-#include "ED_screen.h"
+#include "ED_keyframing.h"
#include "ED_markers.h"
#include "ED_mask.h"
+#include "ED_screen.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -313,8 +313,8 @@ void ACTION_OT_previewrange_set(wmOperatorType *ot)
/**
* Find the extents of the active channel
*
- * \param[out] min Bottom y-extent of channel
- * \param[out] max Top y-extent of channel
+ * \param[out] min: Bottom y-extent of channel
+ * \param[out] max: Top y-extent of channel
* \return Success of finding a selected channel
*/
static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min, float *max)
@@ -372,7 +372,7 @@ static int actkeys_viewall(bContext *C, const bool only_sel)
if (ANIM_animdata_get_context(C, &ac) == 0) {
return OPERATOR_CANCELLED;
}
- v2d = &ac.ar->v2d;
+ v2d = &ac.region->v2d;
/* set the horizontal range, with an extra offset so that the extreme keys will be in view */
found = get_keyframe_extents(&ac, &min, &max, only_sel);
@@ -448,7 +448,7 @@ static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
void ACTION_OT_view_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->idname = "ACTION_OT_view_all";
ot->description = "Reset viewable area to show full keyframe range";
@@ -463,7 +463,7 @@ void ACTION_OT_view_all(wmOperatorType *ot)
void ACTION_OT_view_selected(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Selected";
+ ot->name = "Frame Selected";
ot->idname = "ACTION_OT_view_selected";
ot->description = "Reset viewable area to show selected keyframes range";
@@ -707,7 +707,7 @@ static void insert_action_keys(bAnimContext *ac, short mode)
ReportList *reports = ac->reports;
Scene *scene = ac->scene;
ToolSettings *ts = scene->toolsettings;
- short flag = 0;
+ eInsertKeyFlags flag;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
@@ -721,8 +721,8 @@ static void insert_action_keys(bAnimContext *ac, short mode)
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* init keyframing flag */
- flag = ANIM_get_keyframing_flags(scene, 1);
+ /* Init keyframing flag. */
+ flag = ANIM_get_keyframing_flags(scene, true);
/* insert keyframes */
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -803,7 +803,7 @@ static void insert_gpencil_keys(bAnimContext *ac, short mode)
/* insert gp frames */
for (ale = anim_data.first; ale; ale = ale->next) {
bGPDlayer *gpl = (bGPDlayer *)ale->data;
- BKE_gpencil_layer_getframe(gpl, CFRA, add_frame_mode);
+ BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode);
}
ANIM_animdata_update(ac, &anim_data);
@@ -1311,35 +1311,6 @@ void ACTION_OT_extrapolation_type(wmOperatorType *ot)
/* ******************** Set Interpolation-Type Operator *********************** */
-/* this function is responsible for setting interpolation mode for keyframes */
-static void setipo_action_keys(bAnimContext *ac, short mode)
-{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
- KeyframeEditFunc set_cb = ANIM_editkeyframes_ipo(mode);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
- ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
- /* Loop through setting BezTriple interpolation
- * Note: we do not supply KeyframeEditData to the looper yet.
- * Currently that's not necessary here.
- */
- for (ale = anim_data.first; ale; ale = ale->next) {
- ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve);
-
- ale->update |= ANIM_UPDATE_DEFAULT;
- }
-
- ANIM_animdata_update(ac, &anim_data);
- ANIM_animdata_freelist(&anim_data);
-}
-
-/* ------------------- */
-
static int actkeys_ipo_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@@ -1359,7 +1330,10 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
mode = RNA_enum_get(op->ptr, "type");
/* set handle type */
- setipo_action_keys(&ac, mode);
+ ANIM_animdata_keyframe_callback(&ac,
+ (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS),
+ ANIM_editkeyframes_ipo(mode));
/* set notifier that keyframe properties have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
@@ -1388,6 +1362,54 @@ void ACTION_OT_interpolation_type(wmOperatorType *ot)
ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", "");
}
+/* ******************** Set Easing Operator *********************** */
+
+static int actkeys_easing_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get handle setting mode */
+ mode = RNA_enum_get(op->ptr, "type");
+
+ /* set handle type */
+ ANIM_animdata_keyframe_callback(&ac,
+ (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE |
+ ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS),
+ ANIM_editkeyframes_easing(mode));
+
+ /* set notifier that keyframe properties have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_easing_type(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Keyframe Easing Type";
+ ot->idname = "ACTION_OT_easing_type";
+ ot->description =
+ "Set easing type for the F-Curve segments starting from the selected keyframes";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = actkeys_easing_exec;
+ ot->poll = ED_operator_action_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* id-props */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_beztriple_interpolation_easing_items, 0, "Type", "");
+}
+
/* ******************** Set Handle-Type Operator *********************** */
/* this function is responsible for setting handle-type of selected keyframes */
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index c227b794ae7..bf1b90bbe98 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -42,8 +42,10 @@ void action_buttons_register(struct ARegionType *art);
/* ***************************************** */
/* action_draw.c */
-void draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *ar);
-void draw_channel_strips(struct bAnimContext *ac, struct SpaceAction *saction, struct ARegion *ar);
+void draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *region);
+void draw_channel_strips(struct bAnimContext *ac,
+ struct SpaceAction *saction,
+ struct ARegion *region);
void timeline_draw_cache(struct SpaceAction *saction, struct Object *ob, struct Scene *scene);
@@ -97,6 +99,7 @@ void ACTION_OT_keyframe_type(struct wmOperatorType *ot);
void ACTION_OT_handle_type(struct wmOperatorType *ot);
void ACTION_OT_interpolation_type(struct wmOperatorType *ot);
void ACTION_OT_extrapolation_type(struct wmOperatorType *ot);
+void ACTION_OT_easing_type(struct wmOperatorType *ot);
void ACTION_OT_frame_jump(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index cba86ac5131..7422c05511c 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -21,16 +21,16 @@
* \ingroup spaction
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include "DNA_space_types.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
-#include "ED_transform.h"
#include "ED_object.h"
#include "ED_select_utils.h"
+#include "ED_transform.h"
#include "action_intern.h"
@@ -63,6 +63,7 @@ void action_operatortypes(void)
WM_operatortype_append(ACTION_OT_handle_type);
WM_operatortype_append(ACTION_OT_interpolation_type);
WM_operatortype_append(ACTION_OT_extrapolation_type);
+ WM_operatortype_append(ACTION_OT_easing_type);
WM_operatortype_append(ACTION_OT_keyframe_type);
WM_operatortype_append(ACTION_OT_sample);
WM_operatortype_append(ACTION_OT_clean);
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 09a0c297d35..bbb68f632fb 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -20,10 +20,10 @@
* \ingroup spaction
*/
+#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <float.h>
#include "MEM_guardedalloc.h"
@@ -34,27 +34,27 @@
#include "DNA_anim_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_mask_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_mask_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "BKE_fcurve.h"
-#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
+#include "BKE_nla.h"
-#include "UI_view2d.h"
#include "UI_interface.h"
+#include "UI_view2d.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
-#include "ED_mask.h"
#include "ED_keyframes_draw.h"
#include "ED_keyframes_edit.h"
#include "ED_markers.h"
+#include "ED_mask.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
@@ -71,7 +71,7 @@ static bAnimListElem *actkeys_find_list_element_at_position(bAnimContext *ac,
float region_x,
float region_y)
{
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
float view_x, view_y;
int channel_index;
@@ -158,7 +158,7 @@ static void actkeys_find_key_in_list_element(bAnimContext *ac,
{
*r_found = false;
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
DLRBT_Tree anim_keys;
BLI_dlrbTree_init(&anim_keys);
@@ -437,7 +437,7 @@ static void box_select_elem(
ListBase anim_data = {NULL, NULL};
ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
- for (bAnimListElem *ale2 = anim_data.first; ale2; ale2 = ale2->next) {
+ LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
box_select_elem(sel_data, ale2, xmin, xmax, true);
}
@@ -458,7 +458,7 @@ static void box_select_action(bAnimContext *ac, const rcti rect, short mode, sho
int filter;
BoxSelectData sel_data = {.ac = ac, .selectmode = selectmode};
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
rctf rectf;
/* Convert mouse coordinates to frame ranges and channel
@@ -675,7 +675,7 @@ static void region_select_elem(RegionSelectData *sel_data, bAnimListElem *ale, b
ListBase anim_data = {NULL, NULL};
ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
- for (bAnimListElem *ale2 = anim_data.first; ale2; ale2 = ale2->next) {
+ LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
region_select_elem(sel_data, ale2, true);
}
@@ -697,7 +697,7 @@ static void region_select_action_keys(
int filter;
RegionSelectData sel_data = {.ac = ac, .mode = mode, .selectmode = selectmode};
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
rctf rectf, scaled_rectf;
/* Convert mouse coordinates to frame ranges and channel
@@ -793,8 +793,8 @@ static int actkeys_lassoselect_exec(bContext *C, wmOperator *op)
}
data_lasso.rectf_view = &rect_fl;
- data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot);
- if (data_lasso.mcords == NULL) {
+ data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len);
+ if (data_lasso.mcoords == NULL) {
return OPERATOR_CANCELLED;
}
@@ -805,13 +805,13 @@ static int actkeys_lassoselect_exec(bContext *C, wmOperator *op)
}
/* get settings from operator */
- BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
+ BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len);
BLI_rctf_rcti_copy(&rect_fl, &rect);
/* apply box_select action */
region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_LASSO, selectmode, &data_lasso);
- MEM_freeN((void *)data_lasso.mcords);
+ MEM_freeN((void *)data_lasso.mcoords);
/* send notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -1470,8 +1470,8 @@ static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wm
/* handle mode-based testing */
if (leftright == ACTKEYS_LRSEL_TEST) {
Scene *scene = ac.scene;
- ARegion *ar = ac.ar;
- View2D *v2d = &ar->v2d;
+ ARegion *region = ac.region;
+ View2D *v2d = &region->v2d;
float x;
/* determine which side of the current frame mouse is on */
@@ -1718,7 +1718,9 @@ static int mouse_action_keys(bAnimContext *ac,
/* reset selection mode for next steps */
select_mode = SELECT_ADD;
- if (wait_to_deselect_others) {
+ /* Rather than deselecting others, users may want to drag to box-select (drag from empty space)
+ * or tweak-translate an already selected item. If these cases may apply, delay deselection. */
+ if (wait_to_deselect_others && (!found || is_selected)) {
ret_value = OPERATOR_RUNNING_MODAL;
}
else {
@@ -1757,8 +1759,8 @@ static int mouse_action_keys(bAnimContext *ac,
gpl->flag |= GP_LAYER_SELECT;
/* Update other layer status. */
- if (BKE_gpencil_layer_getactive(gpd) != gpl) {
- BKE_gpencil_layer_setactive(gpd, gpl);
+ if (BKE_gpencil_layer_active_get(gpd) != gpl) {
+ BKE_gpencil_layer_active_set(gpd, gpl);
BKE_gpencil_layer_autolock_set(gpd, false);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
@@ -1823,7 +1825,7 @@ static int actkeys_clickselect_exec(bContext *C, wmOperator *op)
}
/* get useful pointers from animation context data */
- /* ar = ac.ar; */ /* UNUSED */
+ /* region = ac.region; */ /* UNUSED */
/* select mode is either replace (deselect all, then add) or add/extend */
const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 901efbdf0ff..e92ea906237 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -21,8 +21,8 @@
* \ingroup spaction
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "DNA_action_types.h"
#include "DNA_collection_types.h"
@@ -42,28 +42,28 @@
#include "RNA_enum_types.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "ED_space_api.h"
-#include "ED_screen.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
#include "ED_time_scrub_ui.h"
-#include "action_intern.h" /* own include */
#include "GPU_framebuffer.h"
+#include "action_intern.h" /* own include */
/* ******************** default callbacks for action space ***************** */
-static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
+static SpaceLink *action_new(const ScrArea *area, const Scene *scene)
{
SpaceAction *saction;
- ARegion *ar;
+ ARegion *region;
saction = MEM_callocN(sizeof(SpaceAction), "initaction");
saction->spacetype = SPACE_ACTION;
@@ -82,57 +82,57 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
saction->cache_display |= TIME_CACHE_RIGIDBODY;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for action");
+ region = MEM_callocN(sizeof(ARegion), "header for action");
- BLI_addtail(&saction->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&saction->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* channel list region */
- ar = MEM_callocN(sizeof(ARegion), "channel region for action");
- BLI_addtail(&saction->regionbase, ar);
- ar->regiontype = RGN_TYPE_CHANNELS;
- ar->alignment = RGN_ALIGN_LEFT;
+ region = MEM_callocN(sizeof(ARegion), "channel region for action");
+ BLI_addtail(&saction->regionbase, region);
+ region->regiontype = RGN_TYPE_CHANNELS;
+ region->alignment = RGN_ALIGN_LEFT;
/* only need to set scroll settings, as this will use 'listview' v2d configuration */
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
- ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+ region->v2d.scroll = V2D_SCROLL_BOTTOM;
+ region->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
/* ui buttons */
- ar = MEM_callocN(sizeof(ARegion), "buttons region for action");
+ region = MEM_callocN(sizeof(ARegion), "buttons region for action");
- BLI_addtail(&saction->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_RIGHT;
- ar->flag = RGN_FLAG_HIDDEN;
+ BLI_addtail(&saction->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_RIGHT;
+ region->flag = RGN_FLAG_HIDDEN;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for action");
+ region = MEM_callocN(sizeof(ARegion), "main region for action");
- BLI_addtail(&saction->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&saction->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.tot.xmin = (float)(SFRA - 10);
- ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f;
- ar->v2d.tot.xmax = (float)(EFRA + 10);
- ar->v2d.tot.ymax = 0.0f;
+ region->v2d.tot.xmin = (float)(SFRA - 10);
+ region->v2d.tot.ymin = (float)(-area->winy) / 3.0f;
+ region->v2d.tot.xmax = (float)(EFRA + 10);
+ region->v2d.tot.ymax = 0.0f;
- ar->v2d.cur = ar->v2d.tot;
+ region->v2d.cur = region->v2d.tot;
- ar->v2d.min[0] = 0.0f;
- ar->v2d.min[1] = 0.0f;
+ region->v2d.min[0] = 0.0f;
+ region->v2d.min[1] = 0.0f;
- ar->v2d.max[0] = MAXFRAMEF;
- ar->v2d.max[1] = FLT_MAX;
+ region->v2d.max[0] = MAXFRAMEF;
+ region->v2d.max[1] = FLT_MAX;
- ar->v2d.minzoom = 0.01f;
- ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
- ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
- ar->v2d.keepofs = V2D_KEEPOFS_Y;
- ar->v2d.align = V2D_ALIGN_NO_POS_Y;
- ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+ region->v2d.minzoom = 0.01f;
+ region->v2d.maxzoom = 50;
+ region->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ region->v2d.scroll |= (V2D_SCROLL_RIGHT);
+ region->v2d.keepzoom = V2D_LOCKZOOM_Y;
+ region->v2d.keepofs = V2D_KEEPOFS_Y;
+ region->v2d.align = V2D_ALIGN_NO_POS_Y;
+ region->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
return (SpaceLink *)saction;
}
@@ -144,9 +144,9 @@ static void action_free(SpaceLink *UNUSED(sl))
}
/* spacetype; init callback */
-static void action_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void action_init(struct wmWindowManager *UNUSED(wm), ScrArea *area)
{
- SpaceAction *saction = sa->spacedata.first;
+ SpaceAction *saction = area->spacedata.first;
saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
}
@@ -160,27 +160,27 @@ static SpaceLink *action_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void action_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void action_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet", SPACE_ACTION, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void action_main_region_draw(const bContext *C, ARegion *ar)
+static void action_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceAction *saction = CTX_wm_space_action(C);
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
bAnimContext ac;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
short marker_flag = 0;
short cfra_flag = 0;
@@ -194,14 +194,14 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
/* time grid */
UI_view2d_draw_lines_x__discrete_frames_or_seconds(v2d, scene, saction->flag & SACTION_DRAWTIME);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
/* start and end frame */
ANIM_draw_framerange(scene, v2d);
/* data */
if (ANIM_animdata_get_context(C, &ac)) {
- draw_channel_strips(&ac, saction, ar);
+ draw_channel_strips(&ac, saction, region);
}
/* current frame */
@@ -211,7 +211,7 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
ANIM_draw_cfra(C, v2d, cfra_flag);
/* markers */
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ UI_view2d_view_orthoSpecial(region, v2d, 1);
marker_flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) |
DRAW_MARKERS_MARGIN;
@@ -231,13 +231,13 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
/* callback */
UI_view2d_view_ortho(v2d);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
/* reset view matrix */
UI_view2d_view_restore(C);
/* scrubbing region */
- ED_time_scrub_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true);
+ ED_time_scrub_draw(region, scene, saction->flag & SACTION_DRAWTIME, true);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -246,28 +246,28 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void action_channel_region_init(wmWindowManager *wm, ARegion *ar)
+static void action_channel_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
/* ensure the 2d view sync works - main region has bottom scroller */
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+ region->v2d.scroll = V2D_SCROLL_BOTTOM;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void action_channel_region_draw(const bContext *C, ARegion *ar)
+static void action_channel_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
bAnimContext ac;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
@@ -277,11 +277,11 @@ static void action_channel_region_draw(const bContext *C, ARegion *ar)
/* data */
if (ANIM_animdata_get_context(C, &ac)) {
- draw_channel_names((bContext *)C, &ac, ar);
+ draw_channel_names((bContext *)C, &ac, region);
}
/* channel filter next to scrubbing area */
- ED_time_scrub_channel_search_draw(C, ar, ac.ads);
+ ED_time_scrub_channel_search_draw(C, region, ac.ads);
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -290,32 +290,32 @@ static void action_channel_region_draw(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void action_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void action_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void action_header_region_draw(const bContext *C, ARegion *ar)
+static void action_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
static void action_channel_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_SCENE:
switch (wmn->data) {
case ND_OB_ACTIVE:
case ND_FRAME:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -324,28 +324,28 @@ static void action_channel_region_listener(wmWindow *UNUSED(win),
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
case ND_KEYS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_MODIFIER:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
break;
case NC_GPENCIL:
if (ELEM(wmn->action, NA_RENAME, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
default:
if (wmn->data == ND_KEYS) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -355,16 +355,16 @@ static void saction_channel_region_message_subscribe(const struct bContext *UNUS
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr);
+ RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, area->spacedata.first, &ptr);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -397,15 +397,15 @@ static void saction_channel_region_message_subscribe(const struct bContext *UNUS
}
static void action_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_SCENE:
switch (wmn->data) {
@@ -414,7 +414,7 @@ static void action_main_region_listener(wmWindow *UNUSED(win),
case ND_FRAME:
case ND_FRAME_RANGE:
case ND_MARKERS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -426,30 +426,30 @@ static void action_main_region_listener(wmWindow *UNUSED(win),
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
case ND_KEYS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_NODE:
switch (wmn->action) {
case NA_EDITED:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
default:
if (wmn->data == ND_KEYS) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -459,16 +459,16 @@ static void saction_main_region_message_subscribe(const struct bContext *C,
struct WorkSpace *workspace,
struct Scene *scene,
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr);
+ RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, area->spacedata.first, &ptr);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -497,16 +497,16 @@ static void saction_main_region_message_subscribe(const struct bContext *C,
}
/* Now run the general "channels region" one - since channels and main should be in sync */
- saction_channel_region_message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
+ saction_channel_region_message_subscribe(C, workspace, scene, screen, area, region, mbus);
}
/* editor level listener */
static void action_listener(wmWindow *UNUSED(win),
- ScrArea *sa,
+ ScrArea *area,
wmNotifier *wmn,
Scene *UNUSED(scene))
{
- SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+ SpaceAction *saction = (SpaceAction *)area->spacedata.first;
/* context changes */
switch (wmn->category) {
@@ -514,11 +514,11 @@ static void action_listener(wmWindow *UNUSED(win),
/* only handle these events in GPencil mode for performance considerations */
if (saction->mode == SACTCONT_GPENCIL) {
if (wmn->action == NA_EDITED) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
else if (wmn->action == NA_SELECTED) {
saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
}
break;
@@ -526,7 +526,7 @@ static void action_listener(wmWindow *UNUSED(win),
/* for NLA tweakmode enter/exit, need complete refresh */
if (wmn->data == ND_NLA_ACTCHANGE) {
saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
/* autocolor only really needs to change when channels are added/removed,
* or previously hidden stuff appears
@@ -534,34 +534,40 @@ static void action_listener(wmWindow *UNUSED(win),
*/
else if (((wmn->data == ND_KEYFRAME) && ELEM(wmn->action, NA_ADDED, NA_REMOVED)) ||
((wmn->data == ND_ANIMCHAN) && (wmn->action != NA_SELECTED))) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
/* for simple edits to the curve data though (or just plain selections),
* a simple redraw should work
* (see T39851 for an example of how this can go wrong)
*/
else {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
case NC_SCENE:
switch (wmn->data) {
+ case ND_SEQUENCER:
+ if (wmn->action == NA_SELECTED) {
+ saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
+ ED_area_tag_refresh(area);
+ }
+ break;
case ND_OB_ACTIVE:
case ND_OB_SELECT:
/* Selection changed, so force refresh to flush
* (needs flag set to do syncing). */
saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case ND_RENDER_RESULT:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case ND_FRAME_RANGE:
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
Scene *scene = wmn->reference;
- ar->v2d.tot.xmin = (float)(SFRA - 4);
- ar->v2d.tot.xmax = (float)(EFRA + 4);
+ region->v2d.tot.xmin = (float)(SFRA - 4);
+ region->v2d.tot.xmax = (float)(EFRA + 4);
break;
}
}
@@ -569,7 +575,7 @@ static void action_listener(wmWindow *UNUSED(win),
default:
if (saction->mode != SACTCONT_TIMELINE) {
/* Just redrawing the view will do. */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
}
@@ -580,7 +586,7 @@ static void action_listener(wmWindow *UNUSED(win),
* (needs flag set to do syncing). */
case ND_BONE_ACTIVE:
saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case ND_TRANSFORM:
/* moving object shouldn't need to redraw action */
@@ -590,12 +596,12 @@ static void action_listener(wmWindow *UNUSED(win),
case ND_PARTICLE:
/* only needed in timeline mode */
if (saction->mode == SACTCONT_TIMELINE) {
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(area);
+ ED_area_tag_redraw(area);
}
break;
default: /* just redrawing the view will do */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
break;
@@ -603,11 +609,11 @@ static void action_listener(wmWindow *UNUSED(win),
if (saction->mode == SACTCONT_MASK) {
switch (wmn->data) {
case ND_DATA:
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(area);
+ ED_area_tag_redraw(area);
break;
default: /* just redrawing the view will do */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
}
@@ -616,50 +622,53 @@ static void action_listener(wmWindow *UNUSED(win),
if (wmn->action == NA_SELECTED) {
/* selection changed, so force refresh to flush (needs flag set to do syncing) */
saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
break;
case NC_SPACE:
switch (wmn->data) {
case ND_SPACE_DOPESHEET:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case ND_SPACE_TIME:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case ND_SPACE_CHANGED:
saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
}
break;
case NC_WINDOW:
if (saction->runtime.flag & SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC) {
/* force redraw/refresh after undo/redo - [#28962] */
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
break;
case NC_WM:
switch (wmn->data) {
case ND_FILEREAD:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
}
break;
}
}
-static void action_header_region_listener(
- wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
+static void action_header_region_listener(wmWindow *UNUSED(win),
+ ScrArea *area,
+ ARegion *region,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+ SpaceAction *saction = (SpaceAction *)area->spacedata.first;
/* context changes */
switch (wmn->category) {
case NC_SCREEN:
if (saction->mode == SACTCONT_TIMELINE) {
if (wmn->data == ND_ANIMPLAY) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
break;
@@ -672,21 +681,21 @@ static void action_header_region_listener(
case ND_FRAME_RANGE:
case ND_KEYINGSET:
case ND_RENDER_OPTIONS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
}
else {
switch (wmn->data) {
case ND_OB_ACTIVE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ANIMATION:
@@ -695,12 +704,12 @@ static void action_header_region_listener(
/* NOTE: for now, this should usually just mean that the filters changed
* It may be better if we had a dedicated flag for that though
*/
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_KEYFRAME: /* new keyframed added -> active action may have changed */
// saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -708,38 +717,38 @@ static void action_header_region_listener(
}
/* add handlers, stuff you only do once or on area/region changes */
-static void action_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+static void action_buttons_area_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void action_buttons_area_draw(const bContext *C, ARegion *ar)
+static void action_buttons_area_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
static void action_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_SCENE:
switch (wmn->data) {
case ND_OB_ACTIVE:
case ND_FRAME:
case ND_MARKERS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -748,27 +757,27 @@ static void action_region_listener(wmWindow *UNUSED(win),
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
case ND_KEYS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
default:
if (wmn->data == ND_KEYS) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
}
-static void action_refresh(const bContext *C, ScrArea *sa)
+static void action_refresh(const bContext *C, ScrArea *area)
{
- SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+ SpaceAction *saction = (SpaceAction *)area->spacedata.first;
/* Update the state of the animchannels in response to changes from the data they represent
* NOTE: the temp flag is used to indicate when this needs to be done,
* and will be cleared once handled. */
if (saction->runtime.flag & SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC) {
- ARegion *ar;
+ ARegion *region;
/* Perform syncing of channel state incl. selection
* Active action setting also occurs here
@@ -780,9 +789,9 @@ static void action_refresh(const bContext *C, ScrArea *sa)
* - Regions (such as header) need to be manually tagged for redraw too
* or else they don't update [#28962]
*/
- ED_area_tag_redraw(sa);
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- ED_region_tag_redraw(ar);
+ ED_area_tag_redraw(area);
+ for (region = area->regionbase.first; region; region = region->next) {
+ ED_region_tag_redraw(region);
}
}
@@ -790,7 +799,7 @@ static void action_refresh(const bContext *C, ScrArea *sa)
// XXX re-sizing y-extents of tot should go here?
}
-static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void action_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceAction *sact = (SpaceAction *)slink;
@@ -811,15 +820,15 @@ static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, I
* The previous non-timeline mode is stored so switching back to the
* dope-sheet doesn't always reset the sub-mode.
*/
-static int action_space_subtype_get(ScrArea *sa)
+static int action_space_subtype_get(ScrArea *area)
{
- SpaceAction *sact = sa->spacedata.first;
+ SpaceAction *sact = area->spacedata.first;
return sact->mode == SACTCONT_TIMELINE ? SACTCONT_TIMELINE : SACTCONT_DOPESHEET;
}
-static void action_space_subtype_set(ScrArea *sa, int value)
+static void action_space_subtype_set(ScrArea *area, int value)
{
- SpaceAction *sact = sa->spacedata.first;
+ SpaceAction *sact = area->spacedata.first;
if (value == SACTCONT_TIMELINE) {
if (sact->mode != SACTCONT_TIMELINE) {
sact->mode_prev = sact->mode;
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 46a62b6f0a8..7c2e055b1fb 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -38,10 +38,16 @@
#include "ED_anim_api.h"
#include "ED_armature.h"
+#include "ED_clip.h"
#include "ED_curve.h"
#include "ED_fileselect.h"
+#include "ED_gizmo_library.h"
#include "ED_gpencil.h"
+#include "ED_lattice.h"
+#include "ED_logic.h"
#include "ED_markers.h"
+#include "ED_mask.h"
+#include "ED_mball.h"
#include "ED_mesh.h"
#include "ED_node.h"
#include "ED_object.h"
@@ -51,18 +57,12 @@
#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
-#include "ED_space_api.h"
-#include "ED_sound.h"
-#include "ED_uvedit.h"
-#include "ED_userpref.h"
-#include "ED_lattice.h"
-#include "ED_mball.h"
-#include "ED_logic.h"
-#include "ED_clip.h"
-#include "ED_mask.h"
#include "ED_sequencer.h"
-#include "ED_gizmo_library.h"
+#include "ED_sound.h"
+#include "ED_space_api.h"
#include "ED_transform.h"
+#include "ED_userpref.h"
+#include "ED_uvedit.h"
#ifdef WITH_LANPR
# include "ED_lanpr.h"
@@ -271,13 +271,13 @@ void ED_region_draw_cb_exit(ARegionType *art, void *handle)
}
}
-void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type)
+void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type)
{
RegionDrawCB *rdc;
- for (rdc = ar->type->drawcalls.first; rdc; rdc = rdc->next) {
+ for (rdc = region->type->drawcalls.first; rdc; rdc = rdc->next) {
if (rdc->type == type) {
- rdc->draw(C, ar, rdc->customdata);
+ rdc->draw(C, region, rdc->customdata);
}
}
}
@@ -287,7 +287,7 @@ void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type)
void ED_spacetype_xxx(void);
/* allocate and init some vars */
-static SpaceLink *xxx_new(const ScrArea *UNUSED(sa), const Scene *UNUSED(scene))
+static SpaceLink *xxx_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
return NULL;
}
@@ -298,7 +298,7 @@ static void xxx_free(SpaceLink *UNUSED(sl))
}
/* spacetype; init callback for usage, should be redoable */
-static void xxx_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void xxx_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
/* link area to SpaceXXX struct */
diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt
index c8a3577de6b..41eab7a9b6d 100644
--- a/source/blender/editors/space_buttons/CMakeLists.txt
+++ b/source/blender/editors/space_buttons/CMakeLists.txt
@@ -58,4 +58,8 @@ if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
+if(WITH_NEW_OBJECT_TYPES)
+ add_definitions(-DWITH_NEW_OBJECT_TYPES)
+endif()
+
blender_add_lib(bf_editor_space_buttons "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index fb095a57835..2eab9eddf10 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -32,33 +32,33 @@
#include "BLT_translation.h"
#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
#include "DNA_collection_types.h"
#include "DNA_light_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
-#include "DNA_world_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_linestyle_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
-#include "BKE_context.h"
#include "BKE_action.h"
+#include "BKE_context.h"
#include "BKE_layer.h"
+#include "BKE_linestyle.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_screen.h"
#include "BKE_texture.h"
-#include "BKE_linestyle.h"
#include "RNA_access.h"
-#include "ED_buttons.h"
#include "ED_armature.h"
-#include "ED_screen.h"
+#include "ED_buttons.h"
#include "ED_physics.h"
+#include "ED_screen.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -274,6 +274,17 @@ static int buttons_context_path_data(ButsContextPath *path, int type)
else if (RNA_struct_is_a(ptr->type, &RNA_GreasePencil) && (type == -1 || type == OB_GPENCIL)) {
return 1;
}
+#ifdef WITH_NEW_OBJECT_TYPES
+ else if (RNA_struct_is_a(ptr->type, &RNA_Hair) && (type == -1 || type == OB_HAIR)) {
+ return 1;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_PointCloud) && (type == -1 || type == OB_POINTCLOUD)) {
+ return 1;
+ }
+#endif
+ else if (RNA_struct_is_a(ptr->type, &RNA_Volume) && (type == -1 || type == OB_VOLUME)) {
+ return 1;
+ }
/* try to get an object in the path, no pinning supported here */
else if (buttons_context_path_object(path)) {
ob = path->ptr[path->len - 1].data;
@@ -297,7 +308,16 @@ static int buttons_context_path_modifier(ButsContextPath *path)
if (buttons_context_path_object(path)) {
ob = path->ptr[path->len - 1].data;
- if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE, OB_GPENCIL)) {
+ if (ob && ELEM(ob->type,
+ OB_MESH,
+ OB_CURVE,
+ OB_FONT,
+ OB_SURF,
+ OB_LATTICE,
+ OB_GPENCIL,
+ OB_HAIR,
+ OB_POINTCLOUD,
+ OB_VOLUME)) {
return 1;
}
}
@@ -335,7 +355,7 @@ static int buttons_context_path_material(ButsContextPath *path)
ob = path->ptr[path->len - 1].data;
if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
- ma = give_current_material(ob, ob->actcol);
+ ma = BKE_object_material_get(ob, ob->actcol);
RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
path->len++;
return 1;
@@ -819,6 +839,11 @@ const char *buttons_context_dir[] = {
"line_style",
"collection",
"gpencil",
+#ifdef WITH_NEW_OBJECT_TYPES
+ "hair",
+ "pointcloud",
+#endif
+ "volume",
NULL,
};
@@ -896,6 +921,20 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_LightProbe);
return 1;
}
+#ifdef WITH_NEW_OBJECT_TYPES
+ else if (CTX_data_equals(member, "hair")) {
+ set_pointer_type(path, result, &RNA_Hair);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "pointcloud")) {
+ set_pointer_type(path, result, &RNA_PointCloud);
+ return 1;
+ }
+#endif
+ else if (CTX_data_equals(member, "volume")) {
+ set_pointer_type(path, result, &RNA_Volume);
+ return 1;
+ }
else if (CTX_data_equals(member, "material")) {
set_pointer_type(path, result, &RNA_Material);
return 1;
@@ -1045,7 +1084,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
if (ptr && ptr->data) {
Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
+ ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Cloth);
CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
return 1;
}
@@ -1055,7 +1094,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
if (ptr && ptr->data) {
Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
+ ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Softbody);
CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
return 1;
}
@@ -1066,7 +1105,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
if (ptr && ptr->data) {
Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Fluid);
+ ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid);
CTX_data_pointer_set(result, &ob->id, &RNA_FluidModifier, md);
return 1;
}
@@ -1076,7 +1115,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
if (ptr && ptr->data) {
Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
+ ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Collision);
CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
return 1;
}
@@ -1090,7 +1129,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
if (ptr && ptr->data) {
Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint);
+ ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_DynamicPaint);
CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md);
return 1;
}
@@ -1276,7 +1315,7 @@ ID *buttons_context_id_path(const bContext *C)
/* pin particle settings instead of system, since only settings are an idblock*/
if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
if (ptr->type == &RNA_ParticleSystem && ptr->data) {
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
+ ParticleSystem *psys = ptr->data;
return &psys->part->id;
}
}
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index 3ea6d183969..9af623d8065 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -28,10 +28,10 @@
#include "DNA_userdef_types.h"
-#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -110,7 +110,7 @@ static int file_browse_exec(bContext *C, wmOperator *op)
if (BLI_is_dir(path)) {
/* do this first so '//' isnt converted to '//\' on windows */
- BLI_add_slash(path);
+ BLI_path_slash_ensure(path);
if (is_relative) {
BLI_strncpy(path, str, FILE_MAX);
BLI_path_rel(path, BKE_main_blendfile_path(bmain));
@@ -122,7 +122,7 @@ static int file_browse_exec(bContext *C, wmOperator *op)
}
}
else {
- char *const lslash = (char *)BLI_last_slash(str);
+ char *const lslash = (char *)BLI_path_slash_rfind(str);
if (lslash) {
lslash[1] = '\0';
}
@@ -187,7 +187,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
PointerRNA props_ptr;
if (event->alt) {
- char *lslash = (char *)BLI_last_slash(str);
+ char *lslash = (char *)BLI_path_slash_rfind(str);
if (lslash) {
*lslash = '\0';
}
@@ -227,7 +227,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
is_relative = false;
}
- /* annoying exception!, if were dealing with the user prefs, default relative to be off */
+ /* annoying exception!, if we're dealing with the user prefs, default relative to be off */
RNA_property_boolean_set(op->ptr, prop_relpath, is_relative);
}
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 03c8fbb4e66..6b7f86a9143 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -32,23 +32,23 @@
#include "BLT_translation.h"
-#include "DNA_brush_types.h"
#include "DNA_ID.h"
+#include "DNA_brush_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_node_types.h"
-#include "DNA_object_types.h"
#include "DNA_object_force_types.h"
+#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "DNA_linestyle_types.h"
#include "DNA_windowmanager_types.h"
#include "BKE_context.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_layer.h"
#include "BKE_linestyle.h"
#include "BKE_modifier.h"
-#include "BKE_gpencil_modifier.h"
#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
@@ -236,10 +236,10 @@ static void buttons_texture_users_from_context(ListBase *users,
int a;
/* modifiers */
- modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users);
+ BKE_modifiers_foreach_tex_link(ob, buttons_texture_modifier_foreach, users);
/* grease pencil modifiers */
- BKE_gpencil_modifiers_foreachTexLink(ob, buttons_texture_modifier_gpencil_foreach, users);
+ BKE_gpencil_modifiers_foreach_tex_link(ob, buttons_texture_modifier_gpencil_foreach, users);
/* particle systems */
if (psys && !limited_mode) {
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index dd4b38e5b3f..a91f3e60fac 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -21,8 +21,8 @@
* \ingroup spbuttons
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -32,13 +32,13 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "ED_view3d.h" /* To draw toolbar UI. */
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -54,7 +54,7 @@
static SpaceLink *buttons_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceProperties *sbuts;
sbuts = MEM_callocN(sizeof(SpaceProperties), "initbuts");
@@ -63,32 +63,32 @@ static SpaceLink *buttons_new(const ScrArea *UNUSED(area), const Scene *UNUSED(s
sbuts->mainb = sbuts->mainbuser = BCONTEXT_OBJECT;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for buts");
+ region = MEM_callocN(sizeof(ARegion), "header for buts");
- BLI_addtail(&sbuts->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&sbuts->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* navigation bar */
- ar = MEM_callocN(sizeof(ARegion), "navigation bar for buts");
+ region = MEM_callocN(sizeof(ARegion), "navigation bar for buts");
- BLI_addtail(&sbuts->regionbase, ar);
- ar->regiontype = RGN_TYPE_NAV_BAR;
- ar->alignment = RGN_ALIGN_LEFT;
+ BLI_addtail(&sbuts->regionbase, region);
+ region->regiontype = RGN_TYPE_NAV_BAR;
+ region->alignment = RGN_ALIGN_LEFT;
#if 0
/* context region */
- ar = MEM_callocN(sizeof(ARegion), "context region for buts");
- BLI_addtail(&sbuts->regionbase, ar);
- ar->regiontype = RGN_TYPE_CHANNELS;
- ar->alignment = RGN_ALIGN_TOP;
+ region = MEM_callocN(sizeof(ARegion), "context region for buts");
+ BLI_addtail(&sbuts->regionbase, region);
+ region->regiontype = RGN_TYPE_CHANNELS;
+ region->alignment = RGN_ALIGN_TOP;
#endif
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for buts");
+ region = MEM_callocN(sizeof(ARegion), "main region for buts");
- BLI_addtail(&sbuts->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sbuts->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
return (SpaceLink *)sbuts;
}
@@ -110,7 +110,7 @@ static void buttons_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void buttons_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void buttons_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -126,19 +126,19 @@ static SpaceLink *buttons_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void buttons_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void buttons_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "Property Editor", SPACE_PROPERTIES, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
static void buttons_main_region_layout_properties(const bContext *C,
SpaceProperties *sbuts,
- ARegion *ar)
+ ARegion *region)
{
buttons_context_compute(C, sbuts);
@@ -214,27 +214,28 @@ static void buttons_main_region_layout_properties(const bContext *C,
}
const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts, sbuts->mainb, vertical, NULL);
+ ED_region_panels_layout_ex(
+ C, region, &region->type->paneltypes, contexts, sbuts->mainb, vertical, NULL);
}
-static void buttons_main_region_layout(const bContext *C, ARegion *ar)
+static void buttons_main_region_layout(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceProperties *sbuts = CTX_wm_space_properties(C);
if (sbuts->mainb == BCONTEXT_TOOL) {
- ED_view3d_buttons_region_layout_ex(C, ar, "Tool");
+ ED_view3d_buttons_region_layout_ex(C, region, "Tool");
}
else {
- buttons_main_region_layout_properties(C, sbuts, ar);
+ buttons_main_region_layout_properties(C, sbuts, region);
}
sbuts->mainbo = sbuts->mainb;
}
static void buttons_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -242,7 +243,7 @@ static void buttons_main_region_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -261,41 +262,41 @@ static void buttons_keymap(struct wmKeyConfig *keyconf)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void buttons_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void buttons_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
#ifdef USE_HEADER_CONTEXT_PATH
/* Reinsert context buttons header-type at the end of the list so it's drawn last. */
HeaderType *context_ht = BLI_findstring(
- &ar->type->headertypes, "BUTTONS_HT_context", offsetof(HeaderType, idname));
- BLI_remlink(&ar->type->headertypes, context_ht);
- BLI_addtail(&ar->type->headertypes, context_ht);
+ &region->type->headertypes, "BUTTONS_HT_context", offsetof(HeaderType, idname));
+ BLI_remlink(&region->type->headertypes, context_ht);
+ BLI_addtail(&region->type->headertypes, context_ht);
#endif
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void buttons_header_region_draw(const bContext *C, ARegion *ar)
+static void buttons_header_region_draw(const bContext *C, ARegion *region)
{
SpaceProperties *sbuts = CTX_wm_space_properties(C);
/* Needed for RNA to get the good values! */
buttons_context_compute(C, sbuts);
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
static void buttons_header_region_message_subscribe(const bContext *UNUSED(C),
WorkSpace *UNUSED(workspace),
Scene *UNUSED(scene),
bScreen *UNUSED(screen),
- ScrArea *sa,
- ARegion *ar,
+ ScrArea *area,
+ ARegion *region,
struct wmMsgBus *mbus)
{
- SpaceProperties *sbuts = sa->spacedata.first;
+ SpaceProperties *sbuts = area->spacedata.first;
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -316,37 +317,37 @@ static void buttons_header_region_message_subscribe(const bContext *UNUSED(C),
#endif
}
-static void buttons_navigation_bar_region_init(wmWindowManager *wm, ARegion *ar)
+static void buttons_navigation_bar_region_init(wmWindowManager *wm, ARegion *region)
{
- ar->flag |= RGN_FLAG_PREFSIZE_OR_HIDDEN;
+ region->flag |= RGN_FLAG_PREFSIZE_OR_HIDDEN;
- ED_region_panels_init(wm, ar);
- ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
+ ED_region_panels_init(wm, region);
+ region->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
}
-static void buttons_navigation_bar_region_draw(const bContext *C, ARegion *ar)
+static void buttons_navigation_bar_region_draw(const bContext *C, ARegion *region)
{
- for (PanelType *pt = ar->type->paneltypes.first; pt; pt = pt->next) {
+ LISTBASE_FOREACH (PanelType *, pt, &region->type->paneltypes) {
pt->flag |= PNL_LAYOUT_VERT_BAR;
}
- ED_region_panels_layout(C, ar);
+ ED_region_panels_layout(C, region);
/* ED_region_panels_layout adds vertical scrollbars, we don't want them. */
- ar->v2d.scroll &= ~V2D_SCROLL_VERTICAL;
- ED_region_panels_draw(C, ar);
+ region->v2d.scroll &= ~V2D_SCROLL_VERTICAL;
+ ED_region_panels_draw(C, region);
}
static void buttons_navigation_bar_region_message_subscribe(const bContext *UNUSED(C),
WorkSpace *UNUSED(workspace),
Scene *UNUSED(scene),
bScreen *UNUSED(screen),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
struct wmMsgBus *mbus)
{
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -355,96 +356,96 @@ static void buttons_navigation_bar_region_message_subscribe(const bContext *UNUS
/* draw a certain button set only if properties area is currently
* showing that button set, to reduce unnecessary drawing. */
-static void buttons_area_redraw(ScrArea *sa, short buttons)
+static void buttons_area_redraw(ScrArea *area, short buttons)
{
- SpaceProperties *sbuts = sa->spacedata.first;
+ SpaceProperties *sbuts = area->spacedata.first;
/* if the area's current button set is equal to the one to redraw */
if (sbuts->mainb == buttons) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
}
/* reused! */
static void buttons_area_listener(wmWindow *UNUSED(win),
- ScrArea *sa,
+ ScrArea *area,
wmNotifier *wmn,
Scene *UNUSED(scene))
{
- SpaceProperties *sbuts = sa->spacedata.first;
+ SpaceProperties *sbuts = area->spacedata.first;
/* context changes */
switch (wmn->category) {
case NC_SCENE:
switch (wmn->data) {
case ND_RENDER_OPTIONS:
- buttons_area_redraw(sa, BCONTEXT_RENDER);
- buttons_area_redraw(sa, BCONTEXT_OUTPUT);
- buttons_area_redraw(sa, BCONTEXT_VIEW_LAYER);
+ buttons_area_redraw(area, BCONTEXT_RENDER);
+ buttons_area_redraw(area, BCONTEXT_OUTPUT);
+ buttons_area_redraw(area, BCONTEXT_VIEW_LAYER);
break;
case ND_WORLD:
- buttons_area_redraw(sa, BCONTEXT_WORLD);
+ buttons_area_redraw(area, BCONTEXT_WORLD);
sbuts->preview = 1;
break;
case ND_FRAME:
/* any buttons area can have animated properties so redraw all */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
sbuts->preview = 1;
break;
case ND_OB_ACTIVE:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
sbuts->preview = 1;
break;
case ND_KEYINGSET:
- buttons_area_redraw(sa, BCONTEXT_SCENE);
+ buttons_area_redraw(area, BCONTEXT_SCENE);
break;
case ND_RENDER_RESULT:
break;
case ND_MODE:
case ND_LAYER:
default:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
break;
case NC_OBJECT:
switch (wmn->data) {
case ND_TRANSFORM:
- buttons_area_redraw(sa, BCONTEXT_OBJECT);
- buttons_area_redraw(sa, BCONTEXT_DATA); /* autotexpace flag */
+ buttons_area_redraw(area, BCONTEXT_OBJECT);
+ buttons_area_redraw(area, BCONTEXT_DATA); /* autotexpace flag */
break;
case ND_POSE:
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
- buttons_area_redraw(sa, BCONTEXT_BONE);
- buttons_area_redraw(sa, BCONTEXT_BONE_CONSTRAINT);
- buttons_area_redraw(sa, BCONTEXT_DATA);
+ buttons_area_redraw(area, BCONTEXT_BONE);
+ buttons_area_redraw(area, BCONTEXT_BONE_CONSTRAINT);
+ buttons_area_redraw(area, BCONTEXT_DATA);
break;
case ND_MODIFIER:
if (wmn->action == NA_RENAME) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
else {
- buttons_area_redraw(sa, BCONTEXT_MODIFIER);
+ buttons_area_redraw(area, BCONTEXT_MODIFIER);
}
- buttons_area_redraw(sa, BCONTEXT_PHYSICS);
+ buttons_area_redraw(area, BCONTEXT_PHYSICS);
break;
case ND_CONSTRAINT:
- buttons_area_redraw(sa, BCONTEXT_CONSTRAINT);
- buttons_area_redraw(sa, BCONTEXT_BONE_CONSTRAINT);
+ buttons_area_redraw(area, BCONTEXT_CONSTRAINT);
+ buttons_area_redraw(area, BCONTEXT_BONE_CONSTRAINT);
break;
case ND_PARTICLE:
if (wmn->action == NA_EDITED) {
- buttons_area_redraw(sa, BCONTEXT_PARTICLE);
+ buttons_area_redraw(area, BCONTEXT_PARTICLE);
}
sbuts->preview = 1;
break;
case ND_DRAW:
- buttons_area_redraw(sa, BCONTEXT_OBJECT);
- buttons_area_redraw(sa, BCONTEXT_DATA);
- buttons_area_redraw(sa, BCONTEXT_PHYSICS);
+ buttons_area_redraw(area, BCONTEXT_OBJECT);
+ buttons_area_redraw(area, BCONTEXT_DATA);
+ buttons_area_redraw(area, BCONTEXT_PHYSICS);
/* Needed to refresh context path when changing active particle system index. */
- buttons_area_redraw(sa, BCONTEXT_PARTICLE);
+ buttons_area_redraw(area, BCONTEXT_PARTICLE);
break;
case ND_SHADING:
case ND_SHADING_DRAW:
@@ -455,7 +456,7 @@ static void buttons_area_listener(wmWindow *UNUSED(win),
break;
default:
/* Not all object RNA props have a ND_ notifier (yet) */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
break;
@@ -464,12 +465,12 @@ static void buttons_area_listener(wmWindow *UNUSED(win),
case ND_SELECT:
case ND_DATA:
case ND_VERTEX_GROUP:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
break;
case NC_MATERIAL:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
switch (wmn->data) {
case ND_SHADING:
case ND_SHADING_DRAW:
@@ -482,43 +483,43 @@ static void buttons_area_listener(wmWindow *UNUSED(win),
}
break;
case NC_WORLD:
- buttons_area_redraw(sa, BCONTEXT_WORLD);
+ buttons_area_redraw(area, BCONTEXT_WORLD);
sbuts->preview = 1;
break;
case NC_LAMP:
- buttons_area_redraw(sa, BCONTEXT_DATA);
+ buttons_area_redraw(area, BCONTEXT_DATA);
sbuts->preview = 1;
break;
case NC_GROUP:
- buttons_area_redraw(sa, BCONTEXT_OBJECT);
+ buttons_area_redraw(area, BCONTEXT_OBJECT);
break;
case NC_BRUSH:
- buttons_area_redraw(sa, BCONTEXT_TEXTURE);
- buttons_area_redraw(sa, BCONTEXT_TOOL);
+ buttons_area_redraw(area, BCONTEXT_TEXTURE);
+ buttons_area_redraw(area, BCONTEXT_TOOL);
sbuts->preview = 1;
break;
case NC_TEXTURE:
case NC_IMAGE:
if (wmn->action != NA_PAINTING) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
sbuts->preview = 1;
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_PROPERTIES) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
case NC_ANIMATION:
switch (wmn->data) {
case ND_KEYFRAME:
if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
}
@@ -527,14 +528,14 @@ static void buttons_area_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_DATA:
if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED, NA_SELECTED)) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
}
break;
case NC_NODE:
if (wmn->action == NA_SELECTED) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
/* new active node, update texture preview */
if (sbuts->mainb == BCONTEXT_TEXTURE) {
sbuts->preview = 1;
@@ -544,24 +545,24 @@ static void buttons_area_listener(wmWindow *UNUSED(win),
/* Listener for preview render, when doing an global undo. */
case NC_WM:
if (wmn->data == ND_UNDO) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
sbuts->preview = 1;
}
break;
#ifdef WITH_FREESTYLE
case NC_LINESTYLE:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
sbuts->preview = 1;
break;
#endif
}
if (wmn->data == ND_KEYS) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
}
-static void buttons_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void buttons_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceProperties *sbuts = (SpaceProperties *)slink;
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 34b4967beaf..3b1cc6fcab0 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -21,8 +21,8 @@
* \ingroup spclip
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -30,17 +30,17 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "BKE_movieclip.h"
+#include "BKE_screen.h"
#include "BKE_tracking.h"
#include "DEG_depsgraph.h"
@@ -57,8 +57,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "clip_intern.h" /* own include */
@@ -259,8 +259,6 @@ typedef struct {
MovieTrackingTrack *track;
MovieTrackingMarker *marker;
- /** current frame number */
- int framenr;
/** position of marker in pixel coords */
float marker_pos[2];
/** position and dimensions of marker pattern in pixel coords */
@@ -283,14 +281,12 @@ static void to_pixel_space(float r[2], float a[2], int width, int height)
static void marker_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
{
MarkerUpdateCb *cb = (MarkerUpdateCb *)arg_cb;
- MovieTrackingMarker *marker;
if (!cb->compact) {
return;
}
- marker = BKE_tracking_marker_ensure(cb->track, cb->framenr);
-
+ MovieTrackingMarker *marker = cb->marker;
marker->flag = cb->marker_flag;
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
@@ -299,14 +295,12 @@ static void marker_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
static void marker_block_handler(bContext *C, void *arg_cb, int event)
{
MarkerUpdateCb *cb = (MarkerUpdateCb *)arg_cb;
- MovieTrackingMarker *marker;
int width, height;
bool ok = false;
BKE_movieclip_get_size(cb->clip, cb->user, &width, &height);
- marker = BKE_tracking_marker_ensure(cb->track, cb->framenr);
-
+ MovieTrackingMarker *marker = cb->marker;
if (event == B_MARKER_POS) {
marker->pos[0] = cb->marker_pos[0] / width;
marker->pos[1] = cb->marker_pos[1] / height;
@@ -452,7 +446,8 @@ void uiTemplateMarker(uiLayout *layout,
user = userptr->data;
track = trackptr->data;
- marker = BKE_tracking_marker_get(track, user->framenr);
+ int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
+ marker = BKE_tracking_marker_get(track, clip_framenr);
cb = MEM_callocN(sizeof(MarkerUpdateCb), "uiTemplateMarker update_cb");
cb->compact = compact;
@@ -461,7 +456,6 @@ void uiTemplateMarker(uiLayout *layout,
cb->track = track;
cb->marker = marker;
cb->marker_flag = marker->flag;
- cb->framenr = user->framenr;
if (compact) {
block = uiLayoutGetBlock(layout);
@@ -878,7 +872,7 @@ void uiTemplateMovieclipInformation(uiLayout *layout,
if (framenr <= clip->len) {
BKE_movieclip_filename_for_frame(clip, user, filepath);
- file = BLI_last_slash(filepath);
+ file = BLI_path_slash_rfind(filepath);
}
else {
file = "-";
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index e64f21f9307..84ab5e6524b 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -24,15 +24,15 @@
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_movieclip.h"
-#include "ED_screen.h"
#include "ED_clip.h"
+#include "ED_screen.h"
#include "WM_types.h"
@@ -68,7 +68,7 @@ static void track_channel_color(MovieTrackingTrack *track, float default_color[3
}
static void draw_keyframe_shape(
- float x, float y, bool sel, float alpha, unsigned int pos_id, unsigned int color_id)
+ float x, float y, bool sel, float alpha, uint pos_id, uint color_id)
{
float color[4] = {0.91f, 0.91f, 0.91f, alpha};
if (sel) {
@@ -79,9 +79,9 @@ static void draw_keyframe_shape(
immVertex2f(pos_id, x, y);
}
-static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip, unsigned int pos_id)
+static void clip_draw_dopesheet_background(ARegion *region, MovieClip *clip, uint pos_id)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
MovieTracking *tracking = &clip->tracking;
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
MovieTrackingDopesheetCoverageSegment *coverage_segment;
@@ -105,10 +105,10 @@ static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip, unsigne
}
}
-void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
+void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *region, Scene *scene)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
/* frame range */
clip_draw_sfra_efra(v2d, scene);
@@ -142,7 +142,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
GPU_blend(true);
- clip_draw_dopesheet_background(ar, clip, pos_id);
+ clip_draw_dopesheet_background(region, clip, pos_id);
for (channel = dopesheet->channels.first; channel; channel = channel->next) {
float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
@@ -290,13 +290,13 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
}
}
-void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
+void clip_draw_dopesheet_channels(const bContext *C, ARegion *region)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceClip *sc = CTX_wm_space_clip(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
MovieClip *clip = ED_space_clip_get_clip(sc);
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
int fontid = style->widget.uifont_id;
if (!clip) {
@@ -316,7 +316,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
/* need to do a view-sync here, so that the keys area doesn't jump around
* (it must copy this) */
- UI_view2d_sync(NULL, sa, v2d, V2D_LOCK_COPY);
+ UI_view2d_sync(NULL, area, v2d, V2D_LOCK_COPY);
/* loop through channels, and set up drawing depending on their type
* first pass: just the standard GL-drawing for backdrop + text
@@ -380,7 +380,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
}
/* third pass: widgets */
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
y = (float)CHANNEL_FIRST;
/* get RNA properties (once) */
diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c
index 785ced96b13..c3323491085 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_ops.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c
@@ -23,9 +23,9 @@
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_tracking.h"
@@ -33,8 +33,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_screen.h"
#include "ED_clip.h"
+#include "ED_screen.h"
#include "UI_interface.h"
@@ -51,9 +51,9 @@ static bool space_clip_dopesheet_poll(bContext *C)
SpaceClip *sc = CTX_wm_space_clip(C);
if (sc->view == SC_VIEW_DOPESHEET) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- return ar->regiontype == RGN_TYPE_PREVIEW;
+ return region->regiontype == RGN_TYPE_PREVIEW;
}
}
@@ -123,10 +123,11 @@ static int dopesheet_select_channel_exec(bContext *C, wmOperator *op)
static int dopesheet_select_channel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float location[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
RNA_float_set_array(op->ptr, "location", location);
return dopesheet_select_channel_exec(C, op);
@@ -170,8 +171,8 @@ void CLIP_OT_dopesheet_select_channel(wmOperatorType *ot)
static int dopesheet_view_all_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
@@ -194,7 +195,7 @@ static int dopesheet_view_all_exec(bContext *C, wmOperator *UNUSED(op))
v2d->cur.xmin -= extra;
v2d->cur.xmax += extra;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
return OPERATOR_FINISHED;
@@ -203,7 +204,7 @@ static int dopesheet_view_all_exec(bContext *C, wmOperator *UNUSED(op))
void CLIP_OT_dopesheet_view_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->description = "Reset viewable area to show full keyframe range";
ot->idname = "CLIP_OT_dopesheet_view_all";
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index f9899135e2d..fe7ae7096a0 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -28,24 +28,24 @@
#include "MEM_guardedalloc.h"
#include "IMB_colormanagement.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLI_string.h"
#include "BLI_math_base.h"
#include "BLI_rect.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_image.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
-#include "ED_screen.h"
#include "ED_clip.h"
-#include "ED_mask.h"
#include "ED_gpencil.h"
+#include "ED_mask.h"
+#include "ED_screen.h"
#include "BIF_glutil.h"
@@ -66,8 +66,7 @@
/*********************** main area drawing *************************/
-static void draw_keyframe(
- int frame, int cfra, int sfra, float framelen, int width, unsigned int pos)
+static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width, uint pos)
{
int height = (frame == cfra) ? 22 : 10;
int x = (frame - sfra) * framelen;
@@ -143,11 +142,11 @@ static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track,
return false;
}
-static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
+static void draw_movieclip_cache(SpaceClip *sc, ARegion *region, MovieClip *clip, Scene *scene)
{
float x;
int *points, totseg, i, a;
- float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
+ float sfra = SFRA, efra = EFRA, framelen = region->winx / (efra - sfra + 1);
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *act_object = BKE_tracking_object_get_active(tracking);
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
@@ -159,11 +158,11 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
/* cache background */
- ED_region_cache_draw_background(ar);
+ ED_region_cache_draw_background(region);
/* cached segments -- could be useful to debug caching strategies */
BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
- ED_region_cache_draw_cached_segments(ar, totseg, points, sfra, efra);
+ ED_region_cache_draw_cached_segments(region, totseg, points, sfra, efra);
uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
@@ -249,7 +248,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
GPU_blend(false);
/* current frame */
- x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
+ x = (sc->user.framenr - sfra) / (efra - sfra + 1) * region->winx;
immUniformThemeColor(TH_CFRAME);
immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
@@ -270,11 +269,11 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
/* movie clip animation */
if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask_info.mask) {
- ED_mask_draw_frames(sc->mask_info.mask, ar, CFRA, sfra, efra);
+ ED_mask_draw_frames(sc->mask_info.mask, region, CFRA, sfra, efra);
}
}
-static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
+static void draw_movieclip_notes(SpaceClip *sc, ARegion *region)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@@ -293,11 +292,11 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
if (str[0]) {
float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.6f};
- ED_region_info_draw(ar, str, fill_color, full_redraw);
+ ED_region_info_draw(region, str, fill_color, full_redraw);
}
}
-static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx, float zoomy)
+static void draw_movieclip_muted(ARegion *region, int width, int height, float zoomx, float zoomy)
{
int x, y;
@@ -305,7 +304,7 @@ static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* find window pixel coordinates of origin */
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &x, &y);
immUniformColor3f(0.0f, 0.0f, 0.0f);
immRectf(pos, x, y, x + zoomx * width, y + zoomy * height);
@@ -315,7 +314,7 @@ static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx
static void draw_movieclip_buffer(const bContext *C,
SpaceClip *sc,
- ARegion *ar,
+ ARegion *region,
ImBuf *ibuf,
int width,
int height,
@@ -327,7 +326,7 @@ static void draw_movieclip_buffer(const bContext *C,
int x, y;
/* find window pixel coordinates of origin */
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &x, &y);
/* checkerboard for case alpha */
if (ibuf->planes == 32) {
@@ -359,13 +358,13 @@ static void draw_movieclip_buffer(const bContext *C,
}
static void draw_stabilization_border(
- SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy)
+ SpaceClip *sc, ARegion *region, int width, int height, float zoomx, float zoomy)
{
int x, y;
MovieClip *clip = ED_space_clip_get_clip(sc);
/* find window pixel coordinates of origin */
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &x, &y);
/* draw boundary border for frame if stabilization is enabled */
if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
@@ -592,7 +591,7 @@ static void draw_marker_outline(SpaceClip *sc,
const float marker_pos[2],
int width,
int height,
- unsigned int position)
+ uint position)
{
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
bool show_search = false;
@@ -895,7 +894,7 @@ static float get_shortest_pattern_side(MovieTrackingMarker *marker)
}
static void draw_marker_slide_square(
- float x, float y, float dx, float dy, int outline, const float px[2], unsigned int pos)
+ float x, float y, float dx, float dy, int outline, const float px[2], uint pos)
{
float tdx, tdy;
@@ -911,7 +910,7 @@ static void draw_marker_slide_square(
}
static void draw_marker_slide_triangle(
- float x, float y, float dx, float dy, int outline, const float px[2], unsigned int pos)
+ float x, float y, float dx, float dy, int outline, const float px[2], uint pos)
{
float tdx, tdy;
@@ -939,7 +938,7 @@ static void draw_marker_slide_zones(SpaceClip *sc,
int act,
int width,
int height,
- unsigned int pos)
+ uint pos)
{
float dx, dy, patdx, patdy, searchdx, searchdy;
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
@@ -1056,7 +1055,7 @@ static void draw_marker_texts(SpaceClip *sc,
UI_FontThemeColor(fontid, TH_ACT_MARKER);
}
else {
- unsigned char color[4];
+ uchar color[4];
UI_GetThemeColorShade4ubv(TH_DIS_MARKER, 128, color);
BLF_color4ubv(fontid, color);
}
@@ -1191,7 +1190,7 @@ static void draw_plane_marker_image(Scene *scene,
ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
if (ibuf) {
- unsigned char *display_buffer;
+ uchar *display_buffer;
void *cache_handle;
if (image->flag & IMA_VIEW_AS_RENDER) {
@@ -1459,7 +1458,7 @@ static void draw_plane_track(SpaceClip *sc,
/* Draw all kind of tracks. */
static void draw_tracking_tracks(SpaceClip *sc,
Scene *scene,
- ARegion *ar,
+ ARegion *region,
MovieClip *clip,
int width,
int height,
@@ -1484,7 +1483,7 @@ static void draw_tracking_tracks(SpaceClip *sc,
* to avoid this flickering, calculate base point in the same way as it happens
* in UI_view2d_view_to_region_no_clip, but do it in floats here */
- UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region_fl(&region->v2d, 0.0f, 0.0f, &x, &y);
GPU_matrix_push();
GPU_matrix_translate_2f(x, y);
@@ -1652,7 +1651,7 @@ static void draw_tracking_tracks(SpaceClip *sc,
pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width;
pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy;
- BKE_tracking_distort_v2(tracking, pos, npos);
+ BKE_tracking_distort_v2(tracking, width, height, pos, npos);
if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) {
vec[0] = (marker->pos[0] + track->offset[0]) * width;
@@ -1721,13 +1720,17 @@ static void draw_tracking_tracks(SpaceClip *sc,
}
}
-static void draw_distortion(
- SpaceClip *sc, ARegion *ar, MovieClip *clip, int width, int height, float zoomx, float zoomy)
+static void draw_distortion(SpaceClip *sc,
+ ARegion *region,
+ MovieClip *clip,
+ int width,
+ int height,
+ float zoomx,
+ float zoomy)
{
float x, y;
const int n = 10;
- int i, j, a;
- float pos[2], tpos[2], grid[11][11][2];
+ float tpos[2], grid[11][11][2];
MovieTracking *tracking = &clip->tracking;
bGPdata *gpd = NULL;
float aspy = 1.0f / tracking->camera.pixel_aspect;
@@ -1742,7 +1745,7 @@ static void draw_distortion(
return;
}
- UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region_fl(&region->v2d, 0.0f, 0.0f, &x, &y);
GPU_matrix_push();
GPU_matrix_translate_2f(x, y);
@@ -1760,7 +1763,7 @@ static void draw_distortion(
float val[4][2], idx[4][2];
float min[2], max[2];
- for (a = 0; a < 4; a++) {
+ for (int a = 0; a < 4; a++) {
if (a < 2) {
val[a][a % 2] = FLT_MAX;
}
@@ -1769,13 +1772,13 @@ static void draw_distortion(
}
}
- zero_v2(pos);
- for (i = 0; i <= n; i++) {
- for (j = 0; j <= n; j++) {
+ for (int i = 0; i <= n; i++) {
+ for (int j = 0; j <= n; j++) {
if (i == 0 || j == 0 || i == n || j == n) {
- BKE_tracking_distort_v2(tracking, pos, tpos);
+ const float pos[2] = {dx * j, dy * i};
+ BKE_tracking_distort_v2(tracking, width, height, pos, tpos);
- for (a = 0; a < 4; a++) {
+ for (int a = 0; a < 4; a++) {
int ok;
if (a < 2) {
@@ -1792,59 +1795,49 @@ static void draw_distortion(
}
}
}
-
- pos[0] += dx;
}
-
- pos[0] = 0.0f;
- pos[1] += dy;
}
INIT_MINMAX2(min, max);
- for (a = 0; a < 4; a++) {
- pos[0] = idx[a][0] * dx;
- pos[1] = idx[a][1] * dy;
+ for (int a = 0; a < 4; a++) {
+ const float pos[2] = {idx[a][0] * dx, idx[a][1] * dy};
- BKE_tracking_undistort_v2(tracking, pos, tpos);
+ BKE_tracking_undistort_v2(tracking, width, height, pos, tpos);
minmax_v2v2_v2(min, max, tpos);
}
- copy_v2_v2(pos, min);
dx = (max[0] - min[0]) / n;
dy = (max[1] - min[1]) / n;
- for (i = 0; i <= n; i++) {
- for (j = 0; j <= n; j++) {
- BKE_tracking_distort_v2(tracking, pos, grid[i][j]);
+ for (int i = 0; i <= n; i++) {
+ for (int j = 0; j <= n; j++) {
+ const float pos[2] = {min[0] + dx * j, min[1] + dy * i};
+
+ BKE_tracking_distort_v2(tracking, width, height, pos, grid[i][j]);
grid[i][j][0] /= width;
grid[i][j][1] /= height * aspy;
-
- pos[0] += dx;
}
-
- pos[0] = min[0];
- pos[1] += dy;
}
immUniformColor3f(1.0f, 0.0f, 0.0f);
- for (i = 0; i <= n; i++) {
+ for (int i = 0; i <= n; i++) {
immBegin(GPU_PRIM_LINE_STRIP, n + 1);
- for (j = 0; j <= n; j++) {
+ for (int j = 0; j <= n; j++) {
immVertex2fv(position, grid[i][j]);
}
immEnd();
}
- for (j = 0; j <= n; j++) {
+ for (int j = 0; j <= n; j++) {
immBegin(GPU_PRIM_LINE_STRIP, n + 1);
- for (i = 0; i <= n; i++) {
+ for (int i = 0; i <= n; i++) {
immVertex2fv(position, grid[i][j]);
}
@@ -1878,8 +1871,8 @@ static void draw_distortion(
while (stroke) {
if (stroke->flag & GP_STROKE_2DSPACE) {
if (stroke->totpoints > 1) {
- for (i = 0; i < stroke->totpoints - 1; i++) {
- float npos[2], dpos[2], len;
+ for (int i = 0; i < stroke->totpoints - 1; i++) {
+ float pos[2], npos[2], dpos[2], len;
int steps;
pos[0] = (stroke->points[i].x + offsx) * width;
@@ -1893,8 +1886,8 @@ static void draw_distortion(
/* we want to distort only long straight lines */
if (stroke->totpoints == 2) {
- BKE_tracking_undistort_v2(tracking, pos, pos);
- BKE_tracking_undistort_v2(tracking, npos, npos);
+ BKE_tracking_undistort_v2(tracking, width, height, pos, pos);
+ BKE_tracking_undistort_v2(tracking, width, height, npos, npos);
}
sub_v2_v2v2(dpos, npos, pos);
@@ -1902,8 +1895,8 @@ static void draw_distortion(
immBegin(GPU_PRIM_LINE_STRIP, steps + 1);
- for (j = 0; j <= steps; j++) {
- BKE_tracking_distort_v2(tracking, pos, tpos);
+ for (int j = 0; j <= steps; j++) {
+ BKE_tracking_distort_v2(tracking, width, height, pos, tpos);
immVertex2f(position, tpos[0] / width, tpos[1] / (height * aspy));
add_v2_v2(pos, dpos);
@@ -1934,7 +1927,7 @@ static void draw_distortion(
GPU_matrix_pop();
}
-void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
+void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *region)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
Scene *scene = CTX_data_scene(C);
@@ -1943,11 +1936,11 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
float zoomx, zoomy;
ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+ ED_space_clip_get_zoom(sc, region, &zoomx, &zoomy);
/* if no clip, nothing to do */
if (!clip) {
- ED_region_grid_draw(ar, zoomx, zoomy, 0.0f, 0.0f);
+ ED_region_grid_draw(region, zoomx, zoomy, 0.0f, 0.0f);
return;
}
@@ -1987,30 +1980,30 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
}
if (ibuf) {
- draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
+ draw_movieclip_buffer(C, sc, region, ibuf, width, height, zoomx, zoomy);
IMB_freeImBuf(ibuf);
}
else if (sc->flag & SC_MUTE_FOOTAGE) {
- draw_movieclip_muted(ar, width, height, zoomx, zoomy);
+ draw_movieclip_muted(region, width, height, zoomx, zoomy);
}
else {
- ED_region_grid_draw(ar, zoomx, zoomy, 0.0f, 0.0f);
+ ED_region_grid_draw(region, zoomx, zoomy, 0.0f, 0.0f);
}
if (width && height) {
- draw_stabilization_border(sc, ar, width, height, zoomx, zoomy);
- draw_tracking_tracks(sc, scene, ar, clip, width, height, zoomx, zoomy);
- draw_distortion(sc, ar, clip, width, height, zoomx, zoomy);
+ draw_stabilization_border(sc, region, width, height, zoomx, zoomy);
+ draw_tracking_tracks(sc, scene, region, clip, width, height, zoomx, zoomy);
+ draw_distortion(sc, region, clip, width, height, zoomx, zoomy);
}
}
-void clip_draw_cache_and_notes(const bContext *C, SpaceClip *sc, ARegion *ar)
+void clip_draw_cache_and_notes(const bContext *C, SpaceClip *sc, ARegion *region)
{
Scene *scene = CTX_data_scene(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
if (clip) {
- draw_movieclip_cache(sc, ar, clip, scene);
- draw_movieclip_notes(sc, ar);
+ draw_movieclip_cache(sc, region, clip, scene);
+ draw_movieclip_notes(sc, region);
}
}
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index fbefc884589..5be4b2d5df0 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -21,10 +21,10 @@
* \ingroup spclip
*/
-#include <stddef.h>
#include <errno.h>
-#include <sys/types.h>
#include <fcntl.h>
+#include <stddef.h>
+#include <sys/types.h>
#ifndef WIN32
# include <unistd.h>
@@ -36,27 +36,28 @@
#include "DNA_mask_types.h"
-#include "BLI_utildefines.h"
#include "BLI_fileops.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_task.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
#include "IMB_colormanagement.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
-#include "ED_screen.h"
#include "ED_clip.h"
#include "ED_mask.h"
+#include "ED_screen.h"
#include "ED_select_utils.h"
#include "WM_api.h"
@@ -147,14 +148,16 @@ void ED_space_clip_get_size_fl(SpaceClip *sc, float size[2])
size[1] = size_i[1];
}
-void ED_space_clip_get_zoom(SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy)
+void ED_space_clip_get_zoom(SpaceClip *sc, ARegion *region, float *zoomx, float *zoomy)
{
int width, height;
ED_space_clip_get_size(sc, &width, &height);
- *zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / (BLI_rctf_size_x(&ar->v2d.cur) * width);
- *zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / (BLI_rctf_size_y(&ar->v2d.cur) * height);
+ *zoomx = (float)(BLI_rcti_size_x(&region->winrct) + 1) /
+ (BLI_rctf_size_x(&region->v2d.cur) * width);
+ *zoomy = (float)(BLI_rcti_size_y(&region->winrct) + 1) /
+ (BLI_rctf_size_y(&region->v2d.cur) * height);
}
void ED_space_clip_get_aspect(SpaceClip *sc, float *aspx, float *aspy)
@@ -186,7 +189,7 @@ void ED_space_clip_get_aspect_dimension_aware(SpaceClip *sc, float *aspx, float
* due to they're invariant to this stuff, but some transformation tools like rotation
* should be aware of aspect correction caused by different resolution in different
* directions.
- * mainly this is sued for transformation stuff
+ * mainly this is used for transformation stuff
*/
if (!sc->clip) {
@@ -261,7 +264,7 @@ ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale
}
/* Returns color in linear space, matching ED_space_image_color_sample(). */
-bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3])
+bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *region, int mval[2], float r_col[3])
{
ImBuf *ibuf;
float fx, fy, co[2];
@@ -273,14 +276,14 @@ bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r
}
/* map the mouse coords to the backdrop image space */
- ED_clip_mouse_pos(sc, ar, mval, co);
+ ED_clip_mouse_pos(sc, region, mval, co);
fx = co[0];
fy = co[1];
if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
const float *fp;
- unsigned char *cp;
+ uchar *cp;
int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
CLAMP(x, 0, ibuf->x - 1);
@@ -292,7 +295,7 @@ bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r
ret = true;
}
else if (ibuf->rect) {
- cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
+ cp = (uchar *)(ibuf->rect + y * ibuf->x + x);
rgb_uchar_to_float(r_col, cp);
IMB_colormanagement_colorspace_to_scene_linear_v3(r_col, ibuf->rect_colorspace);
ret = true;
@@ -308,12 +311,12 @@ void ED_clip_update_frame(const Main *mainp, int cfra)
{
/* image window, compo node users */
for (wmWindowManager *wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
bScreen *screen = WM_window_get_active_screen(win);
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_CLIP) {
- SpaceClip *sc = sa->spacedata.first;
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = area->spacedata.first;
sc->scopes.ok = false;
@@ -395,7 +398,7 @@ static bool selected_boundbox(const bContext *C, float min[2], float max[2])
}
}
-bool ED_clip_view_selection(const bContext *C, ARegion *ar, bool fit)
+bool ED_clip_view_selection(const bContext *C, ARegion *region, bool fit)
{
SpaceClip *sc = CTX_wm_space_clip(C);
int w, h, frame_width, frame_height;
@@ -425,8 +428,8 @@ bool ED_clip_view_selection(const bContext *C, ARegion *ar, bool fit)
ED_space_clip_get_aspect(sc, &aspx, &aspy);
- width = BLI_rcti_size_x(&ar->winrct) + 1;
- height = BLI_rcti_size_y(&ar->winrct) + 1;
+ width = BLI_rcti_size_x(&region->winrct) + 1;
+ height = BLI_rcti_size_y(&region->winrct) + 1;
zoomx = (float)width / w / aspx;
zoomy = (float)height / h / aspy;
@@ -543,22 +546,23 @@ void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[
r_co[0] *= width;
r_co[1] *= height * aspy;
- BKE_tracking_undistort_v2(&clip->tracking, r_co, r_co);
+ BKE_tracking_undistort_v2(&clip->tracking, width, height, r_co, r_co);
r_co[0] /= width;
r_co[1] /= height * aspy;
}
}
-void ED_clip_point_stable_pos(SpaceClip *sc, ARegion *ar, float x, float y, float *xr, float *yr)
+void ED_clip_point_stable_pos(
+ SpaceClip *sc, ARegion *region, float x, float y, float *xr, float *yr)
{
int sx, sy, width, height;
float zoomx, zoomy, pos[3], imat[4][4];
- ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+ ED_space_clip_get_zoom(sc, region, &zoomx, &zoomy);
ED_space_clip_get_size(sc, &width, &height);
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &sx, &sy);
pos[0] = (x - sx) / zoomx;
pos[1] = (y - sy) / zoomy;
@@ -576,7 +580,7 @@ void ED_clip_point_stable_pos(SpaceClip *sc, ARegion *ar, float x, float y, floa
float aspy = 1.0f / tracking->camera.pixel_aspect;
float tmp[2] = {*xr * width, *yr * height * aspy};
- BKE_tracking_distort_v2(tracking, tmp, tmp);
+ BKE_tracking_distort_v2(tracking, width, height, tmp, tmp);
*xr = tmp[0] / width;
*yr = tmp[1] / (height * aspy);
@@ -588,7 +592,7 @@ void ED_clip_point_stable_pos(SpaceClip *sc, ARegion *ar, float x, float y, floa
* better name here? view_to_track / track_to_view or so?
*/
void ED_clip_point_stable_pos__reverse(SpaceClip *sc,
- ARegion *ar,
+ ARegion *region,
const float co[2],
float r_co[2])
{
@@ -597,9 +601,9 @@ void ED_clip_point_stable_pos__reverse(SpaceClip *sc,
int width, height;
int sx, sy;
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &sx, &sy);
ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+ ED_space_clip_get_zoom(sc, region, &zoomx, &zoomy);
ED_clip_point_undistorted_pos(sc, co, pos);
pos[2] = 0.0f;
@@ -612,9 +616,9 @@ void ED_clip_point_stable_pos__reverse(SpaceClip *sc,
}
/* takes event->mval */
-void ED_clip_mouse_pos(SpaceClip *sc, ARegion *ar, const int mval[2], float co[2])
+void ED_clip_mouse_pos(SpaceClip *sc, ARegion *region, const int mval[2], float co[2])
{
- ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &co[0], &co[1]);
+ ED_clip_point_stable_pos(sc, region, mval[0], mval[1], &co[0], &co[1]);
}
bool ED_space_clip_check_show_trackedit(SpaceClip *sc)
@@ -741,7 +745,7 @@ static bool check_prefetch_break(void)
}
/* read file for specified frame number to the memory */
-static unsigned char *prefetch_read_file_to_memory(
+static uchar *prefetch_read_file_to_memory(
MovieClip *clip, int current_frame, short render_size, short render_flag, size_t *r_size)
{
MovieClipUser user = {0};
@@ -763,7 +767,7 @@ static unsigned char *prefetch_read_file_to_memory(
return NULL;
}
- unsigned char *mem = MEM_mallocN(size, "movieclip prefetch memory file");
+ uchar *mem = MEM_mallocN(size, "movieclip prefetch memory file");
if (mem == NULL) {
close(file);
return NULL;
@@ -819,12 +823,12 @@ static int prefetch_find_uncached_frame(MovieClip *clip,
}
/* get memory buffer for first uncached frame within prefetch frame range */
-static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue,
- MovieClip *clip,
- size_t *r_size,
- int *r_current_frame)
+static uchar *prefetch_thread_next_frame(PrefetchQueue *queue,
+ MovieClip *clip,
+ size_t *r_size,
+ int *r_current_frame)
{
- unsigned char *mem = NULL;
+ uchar *mem = NULL;
BLI_spin_lock(&queue->spin);
if (!*queue->stop && !check_prefetch_break() &&
@@ -881,11 +885,11 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue,
return mem;
}
-static void prefetch_task_func(TaskPool *__restrict pool, void *task_data, int UNUSED(threadid))
+static void prefetch_task_func(TaskPool *__restrict pool, void *task_data)
{
- PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_userdata(pool);
+ PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_user_data(pool);
MovieClip *clip = (MovieClip *)task_data;
- unsigned char *mem;
+ uchar *mem;
size_t size;
int current_frame;
@@ -938,9 +942,8 @@ static void start_prefetch_threads(MovieClip *clip,
float *progress)
{
PrefetchQueue queue;
- TaskScheduler *task_scheduler = BLI_task_scheduler_get();
TaskPool *task_pool;
- int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
+ int i, tot_thread = BLI_task_scheduler_num_threads();
/* initialize queue */
BLI_spin_init(&queue.spin);
@@ -957,9 +960,9 @@ static void start_prefetch_threads(MovieClip *clip,
queue.do_update = do_update;
queue.progress = progress;
- task_pool = BLI_task_pool_create(task_scheduler, &queue);
+ task_pool = BLI_task_pool_create(&queue, TASK_PRIORITY_LOW);
for (i = 0; i < tot_thread; i++) {
- BLI_task_pool_push(task_pool, prefetch_task_func, clip, false, TASK_PRIORITY_LOW);
+ BLI_task_pool_push(task_pool, prefetch_task_func, clip, false, NULL);
}
BLI_task_pool_work_and_wait(task_pool);
BLI_task_pool_free(task_pool);
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 3f705aad89a..277930495bd 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -24,15 +24,15 @@
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
-#include "ED_screen.h"
#include "ED_clip.h"
+#include "ED_screen.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
@@ -52,7 +52,7 @@ typedef struct TrackMotionCurveUserData {
MovieTrackingTrack *act_track;
bool sel;
float xscale, yscale, hsize;
- unsigned int pos;
+ uint pos;
} TrackMotionCurveUserData;
static void tracking_segment_point_cb(void *userdata,
@@ -159,7 +159,7 @@ static void tracking_segment_knot_cb(void *userdata,
}
}
-static void draw_tracks_motion_and_error_curves(View2D *v2d, SpaceClip *sc, unsigned int pos)
+static void draw_tracks_motion_and_error_curves(View2D *v2d, SpaceClip *sc, uint pos)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@@ -215,44 +215,59 @@ static void draw_tracks_motion_and_error_curves(View2D *v2d, SpaceClip *sc, unsi
}
}
-static void draw_frame_curves(SpaceClip *sc, unsigned int pos)
+static void draw_frame_curves(SpaceClip *sc, uint pos)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
- int i, lines = 0, prevfra = 0;
+
+ int previous_frame;
+ float previous_error;
+ bool have_previous_point = false;
+
+ /* Indicates whether immBegin() was called. */
+ bool is_lines_segment_open = false;
immUniformColor3f(0.0f, 0.0f, 1.0f);
- for (i = 0; i < reconstruction->camnr; i++) {
+ for (int i = 0; i < reconstruction->camnr; i++) {
MovieReconstructedCamera *camera = &reconstruction->cameras[i];
- int framenr;
- if (lines && camera->framenr != prevfra + 1) {
- immEnd();
- lines = 0;
- }
+ const int current_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, camera->framenr);
+ const float current_error = camera->error;
- if (!lines) {
- immBeginAtMost(GPU_PRIM_LINE_STRIP, reconstruction->camnr);
- lines = 1;
+ if (have_previous_point && current_frame != previous_frame + 1) {
+ if (is_lines_segment_open) {
+ immEnd();
+ is_lines_segment_open = false;
+ }
+ have_previous_point = false;
}
- framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, camera->framenr);
- immVertex2f(pos, framenr, camera->error);
+ if (have_previous_point) {
+ if (!is_lines_segment_open) {
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, reconstruction->camnr);
+ is_lines_segment_open = true;
+
+ immVertex2f(pos, previous_frame, previous_error);
+ }
+ immVertex2f(pos, current_frame, current_error);
+ }
- prevfra = camera->framenr;
+ previous_frame = current_frame;
+ previous_error = current_error;
+ have_previous_point = true;
}
- if (lines) {
+ if (is_lines_segment_open) {
immEnd();
}
}
-void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
+void clip_draw_graph(SpaceClip *sc, ARegion *region, Scene *scene)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
/* grid */
UI_view2d_draw_lines_x__values(v2d);
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index 58a00d2e6b9..589831b1c45 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -23,9 +23,9 @@
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_tracking.h"
@@ -35,9 +35,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_clip.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "ED_clip.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -182,8 +182,8 @@ static bool mouse_select_knot(bContext *C, float co[2], bool extend)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
MovieTracking *tracking = &clip->tracking;
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
static const int delta = 6;
@@ -316,10 +316,10 @@ static int select_exec(bContext *C, wmOperator *op)
static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float co[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
RNA_float_set_array(op->ptr, "location", co);
return select_exec(C, op);
@@ -403,7 +403,7 @@ static void box_select_cb(void *userdata,
static int box_select_graph_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@@ -417,7 +417,7 @@ static int box_select_graph_exec(bContext *C, wmOperator *op)
/* get rectangle from operator */
WM_operator_properties_border_to_rctf(op, &rect);
- UI_view2d_region_to_view_rctf(&ar->v2d, &rect, &userdata.rect);
+ UI_view2d_region_to_view_rctf(&region->v2d, &rect, &userdata.rect);
userdata.changed = false;
userdata.select = !RNA_boolean_get(op->ptr, "deselect");
@@ -624,9 +624,9 @@ static void view_all_cb(void *userdata,
static int view_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceClip *sc = CTX_wm_space_clip(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
ViewAllUserData userdata;
float extra;
@@ -663,7 +663,7 @@ static int view_all_exec(bContext *C, wmOperator *UNUSED(op))
v2d->cur.ymin -= extra;
v2d->cur.ymax += extra;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -671,7 +671,7 @@ static int view_all_exec(bContext *C, wmOperator *UNUSED(op))
void CLIP_OT_graph_view_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->description = "View all curves in editor";
ot->idname = "CLIP_OT_graph_view_all";
@@ -682,9 +682,9 @@ void CLIP_OT_graph_view_all(wmOperatorType *ot)
/******************** jump to current frame operator ********************/
-void ED_clip_graph_center_current_frame(Scene *scene, ARegion *ar)
+void ED_clip_graph_center_current_frame(Scene *scene, ARegion *region)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
float extra = BLI_rctf_size_x(&v2d->cur) / 2.0f;
/* set extents of view to start/end frames */
@@ -695,11 +695,11 @@ void ED_clip_graph_center_current_frame(Scene *scene, ARegion *ar)
static int center_current_frame_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- ED_clip_graph_center_current_frame(scene, ar);
+ ED_clip_graph_center_current_frame(scene, region);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index bd54d4f0016..27493bb5ccd 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -54,26 +54,26 @@ struct wmOperatorType;
void ED_clip_buttons_register(struct ARegionType *art);
/* clip_dopesheet_draw.c */
-void clip_draw_dopesheet_main(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scene);
-void clip_draw_dopesheet_channels(const struct bContext *C, struct ARegion *ar);
+void clip_draw_dopesheet_main(struct SpaceClip *sc, struct ARegion *region, struct Scene *scene);
+void clip_draw_dopesheet_channels(const struct bContext *C, struct ARegion *region);
/* clip_dopesheet_ops.c */
void CLIP_OT_dopesheet_select_channel(struct wmOperatorType *ot);
void CLIP_OT_dopesheet_view_all(struct wmOperatorType *ot);
/* clip_draw.c */
-void clip_draw_main(const struct bContext *C, struct SpaceClip *sc, struct ARegion *ar);
+void clip_draw_main(const struct bContext *C, struct SpaceClip *sc, struct ARegion *region);
void clip_draw_grease_pencil(struct bContext *C, int onlyv2d);
-void clip_draw_cache_and_notes(const bContext *C, SpaceClip *sc, ARegion *ar);
+void clip_draw_cache_and_notes(const bContext *C, SpaceClip *sc, ARegion *region);
/* clip_editor.c */
void clip_start_prefetch_job(const struct bContext *C);
/* clip_graph_draw.c */
-void clip_draw_graph(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scene);
+void clip_draw_graph(struct SpaceClip *sc, struct ARegion *region, struct Scene *scene);
/* clip_graph_ops.c */
-void ED_clip_graph_center_current_frame(struct Scene *scene, struct ARegion *ar);
+void ED_clip_graph_center_current_frame(struct Scene *scene, struct ARegion *region);
void CLIP_OT_graph_select(struct wmOperatorType *ot);
void CLIP_OT_graph_select_box(struct wmOperatorType *ot);
@@ -112,7 +112,7 @@ void CLIP_OT_cursor_set(struct wmOperatorType *ot);
void CLIP_OT_lock_selection_toggle(struct wmOperatorType *ot);
/* clip_toolbar.c */
-struct ARegion *ED_clip_has_properties_region(struct ScrArea *sa);
+struct ARegion *ED_clip_has_properties_region(struct ScrArea *area);
/* clip_utils.c */
@@ -178,7 +178,7 @@ void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene);
/* tracking_ops.c */
struct MovieTrackingTrack *tracking_marker_check_slide(
- struct bContext *C, const struct wmEvent *event, int *area_r, int *action_r, int *corner_r);
+ struct bContext *C, const struct wmEvent *event, int *r_area, int *r_action, int *r_corner);
void CLIP_OT_add_marker(struct wmOperatorType *ot);
void CLIP_OT_add_marker_at_click(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 3ede0158f7a..984aa0a63ad 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -22,8 +22,8 @@
*/
#include <errno.h>
-#include <sys/types.h>
#include <fcntl.h>
+#include <sys/types.h>
#ifndef WIN32
# include <unistd.h>
@@ -33,22 +33,22 @@
#include "MEM_guardedalloc.h"
-#include "DNA_userdef_types.h"
#include "DNA_scene_types.h" /* min/max frames */
+#include "DNA_userdef_types.h"
-#include "BLI_utildefines.h"
#include "BLI_fileops.h"
-#include "BLI_path_util.h"
#include "BLI_math.h"
+#include "BLI_path_util.h"
#include "BLI_rect.h"
-#include "BLI_task.h"
#include "BLI_string.h"
+#include "BLI_task.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_movieclip.h"
#include "BKE_report.h"
@@ -57,11 +57,11 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
-#include "ED_screen.h"
#include "ED_clip.h"
+#include "ED_screen.h"
#include "UI_interface.h"
@@ -88,7 +88,7 @@ static void sclip_zoom_set(const bContext *C,
const bool zoom_to_pos)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float oldzoom = sc->zoom;
int width, height;
@@ -105,10 +105,10 @@ static void sclip_zoom_set(const bContext *C,
if ((width < 4) && (height < 4) && sc->zoom < oldzoom) {
sc->zoom = oldzoom;
}
- else if (BLI_rcti_size_x(&ar->winrct) <= sc->zoom) {
+ else if (BLI_rcti_size_x(&region->winrct) <= sc->zoom) {
sc->zoom = oldzoom;
}
- else if (BLI_rcti_size_y(&ar->winrct) <= sc->zoom) {
+ else if (BLI_rcti_size_y(&region->winrct) <= sc->zoom) {
sc->zoom = oldzoom;
}
}
@@ -148,20 +148,20 @@ static void sclip_zoom_set_factor(const bContext *C,
static void sclip_zoom_set_factor_exec(bContext *C, const wmEvent *event, float factor)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float location[2], *mpos = NULL;
if (event) {
SpaceClip *sc = CTX_wm_space_clip(C);
- ED_clip_mouse_pos(sc, ar, event->mval, location);
+ ED_clip_mouse_pos(sc, region, event->mval, location);
mpos = location;
}
sclip_zoom_set_factor(C, factor, mpos, mpos ? (U.uiflag & USER_ZOOM_TO_MOUSEPOS) : false);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
/** \} */
@@ -209,7 +209,7 @@ static int open_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "directory", dir_only);
if (relative) {
- BLI_path_rel(dir_only, CTX_data_main(C)->name);
+ BLI_path_rel(dir_only, bmain->name);
}
prop = RNA_struct_find_property(op->ptr, "files");
@@ -286,7 +286,7 @@ static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
BLI_strncpy(path, clip->name, sizeof(path));
BLI_path_abs(path, CTX_data_main(C)->name);
- BLI_parent_dir(path);
+ BLI_path_parent_dir(path);
}
else {
BLI_strncpy(path, U.textudir, sizeof(path));
@@ -484,11 +484,11 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
RNA_float_set_array(op->ptr, "offset", offset);
view_pan_exec(C, op);
break;
- case ESCKEY:
+ case EVT_ESCKEY:
view_pan_exit(C, op, 1);
return OPERATOR_CANCELLED;
- case SPACEKEY:
+ case EVT_SPACEKEY:
view_pan_exit(C, op, 0);
return OPERATOR_FINISHED;
@@ -559,7 +559,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ViewZoomData *vpd;
op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ClipViewZoomData");
@@ -581,7 +581,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
vpd->zoom = sc->zoom;
vpd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
- ED_clip_mouse_pos(sc, ar, event->mval, vpd->location);
+ ED_clip_mouse_pos(sc, region, event->mval, vpd->location);
WM_event_add_modal_handler(C, op);
}
@@ -769,11 +769,11 @@ static int view_zoom_in_exec(bContext *C, wmOperator *op)
static int view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float location[2];
- ED_clip_mouse_pos(sc, ar, event->mval, location);
+ ED_clip_mouse_pos(sc, region, event->mval, location);
RNA_float_set_array(op->ptr, "location", location);
return view_zoom_in_exec(C, op);
@@ -784,7 +784,7 @@ void CLIP_OT_view_zoom_in(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "View Zoom In";
+ ot->name = "Zoom In";
ot->idname = "CLIP_OT_view_zoom_in";
ot->description = "Zoom in the view";
@@ -826,11 +826,11 @@ static int view_zoom_out_exec(bContext *C, wmOperator *op)
static int view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float location[2];
- ED_clip_mouse_pos(sc, ar, event->mval, location);
+ ED_clip_mouse_pos(sc, region, event->mval, location);
RNA_float_set_array(op->ptr, "location", location);
return view_zoom_out_exec(C, op);
@@ -841,7 +841,7 @@ void CLIP_OT_view_zoom_out(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "View Zoom Out";
+ ot->name = "Zoom Out";
ot->idname = "CLIP_OT_view_zoom_out";
ot->description = "Zoom out the view";
@@ -922,7 +922,7 @@ void CLIP_OT_view_zoom_ratio(wmOperatorType *ot)
static int view_all_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc;
- ARegion *ar;
+ ARegion *region;
int w, h, width, height;
float aspx, aspy;
bool fit_view = RNA_boolean_get(op->ptr, "fit_view");
@@ -930,7 +930,7 @@ static int view_all_exec(bContext *C, wmOperator *op)
/* retrieve state */
sc = CTX_wm_space_clip(C);
- ar = CTX_wm_region(C);
+ region = CTX_wm_region(C);
ED_space_clip_get_size(sc, &w, &h);
ED_space_clip_get_aspect(sc, &aspx, &aspy);
@@ -939,8 +939,8 @@ static int view_all_exec(bContext *C, wmOperator *op)
h = h * aspy;
/* check if the image will fit in the image with zoom == 1 */
- width = BLI_rcti_size_x(&ar->winrct) + 1;
- height = BLI_rcti_size_y(&ar->winrct) + 1;
+ width = BLI_rcti_size_x(&region->winrct) + 1;
+ height = BLI_rcti_size_y(&region->winrct) + 1;
if (fit_view) {
const int margin = 5; /* margin from border */
@@ -965,7 +965,7 @@ static int view_all_exec(bContext *C, wmOperator *op)
sc->xof = sc->yof = 0.0f;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -975,7 +975,7 @@ void CLIP_OT_view_all(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->idname = "CLIP_OT_view_all";
ot->description = "View whole image with markers";
@@ -999,11 +999,11 @@ void CLIP_OT_view_all(wmOperatorType *ot)
static int view_center_cursor_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
clip_view_center_to_point(sc, sc->cursor[0], sc->cursor[1]);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -1023,19 +1023,19 @@ void CLIP_OT_view_center_cursor(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Selected Operator
+/** \name Frame Selected Operator
* \{ */
static int view_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
sc->xlockof = 0.0f;
sc->ylockof = 0.0f;
- ED_clip_view_selection(C, ar, 1);
- ED_region_tag_redraw(ar);
+ ED_clip_view_selection(C, region, 1);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -1043,7 +1043,7 @@ static int view_selected_exec(bContext *C, wmOperator *UNUSED(op))
void CLIP_OT_view_selected(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Selected";
+ ot->name = "Frame Selected";
ot->idname = "CLIP_OT_view_selected";
ot->description = "View all selected elements";
@@ -1093,19 +1093,19 @@ static int change_frame_exec(bContext *C, wmOperator *op)
static int frame_from_event(bContext *C, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
int framenr = 0;
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ float sfra = SFRA, efra = EFRA, framelen = region->winx / (efra - sfra + 1);
framenr = sfra + event->mval[0] / framelen;
}
else {
float viewx, viewy;
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
framenr = round_fl_to_int(viewx);
}
@@ -1115,9 +1115,9 @@ static int frame_from_event(bContext *C, const wmEvent *event)
static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- if (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
if (event->mval[1] > 16 * UI_DPI_FAC) {
return OPERATOR_PASS_THROUGH;
}
@@ -1136,7 +1136,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
return OPERATOR_FINISHED;
case MOUSEMOVE:
@@ -1313,12 +1313,12 @@ typedef struct ProxyThread {
int *build_undistort_sizes, build_undistort_count;
} ProxyThread;
-static unsigned char *proxy_thread_next_frame(ProxyQueue *queue,
- MovieClip *clip,
- size_t *size_r,
- int *cfra_r)
+static uchar *proxy_thread_next_frame(ProxyQueue *queue,
+ MovieClip *clip,
+ size_t *r_size,
+ int *r_cfra)
{
- unsigned char *mem = NULL;
+ uchar *mem = NULL;
BLI_spin_lock(&queue->spin);
if (!*queue->stop && queue->cfra <= queue->efra) {
@@ -1353,8 +1353,8 @@ static unsigned char *proxy_thread_next_frame(ProxyQueue *queue,
return NULL;
}
- *size_r = size;
- *cfra_r = queue->cfra;
+ *r_size = size;
+ *r_cfra = queue->cfra;
queue->cfra++;
close(file);
@@ -1367,11 +1367,11 @@ static unsigned char *proxy_thread_next_frame(ProxyQueue *queue,
return mem;
}
-static void proxy_task_func(TaskPool *__restrict pool, void *task_data, int UNUSED(threadid))
+static void proxy_task_func(TaskPool *__restrict pool, void *task_data)
{
ProxyThread *data = (ProxyThread *)task_data;
- ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_userdata(pool);
- unsigned char *mem;
+ ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_user_data(pool);
+ uchar *mem;
size_t size;
int cfra;
@@ -1413,11 +1413,10 @@ static void do_sequence_proxy(void *pjv,
ProxyJob *pj = pjv;
MovieClip *clip = pj->clip;
Scene *scene = pj->scene;
- TaskScheduler *task_scheduler = BLI_task_scheduler_get();
TaskPool *task_pool;
int sfra = SFRA, efra = EFRA;
ProxyThread *handles;
- int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
+ int i, tot_thread = BLI_task_scheduler_num_threads();
int width, height;
ProxyQueue queue;
@@ -1434,7 +1433,7 @@ static void do_sequence_proxy(void *pjv,
queue.do_update = do_update;
queue.progress = progress;
- task_pool = BLI_task_pool_create(task_scheduler, &queue);
+ task_pool = BLI_task_pool_create(&queue, TASK_PRIORITY_LOW);
handles = MEM_callocN(sizeof(ProxyThread) * tot_thread, "proxy threaded handles");
for (i = 0; i < tot_thread; i++) {
ProxyThread *handle = &handles[i];
@@ -1451,7 +1450,7 @@ static void do_sequence_proxy(void *pjv,
handle->distortion = BKE_tracking_distortion_new(&clip->tracking, width, height);
}
- BLI_task_pool_push(task_pool, proxy_task_func, handle, false, TASK_PRIORITY_LOW);
+ BLI_task_pool_push(task_pool, proxy_task_func, handle, false, NULL);
}
BLI_task_pool_work_and_wait(task_pool);
@@ -1533,7 +1532,7 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
wmJob *wm_job;
ProxyJob *pj;
Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -1570,7 +1569,7 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
@@ -1649,7 +1648,7 @@ static int clip_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmEv
}
else {
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float pan_vec[3];
const wmNDOFMotionData *ndof = event->customdata;
@@ -1664,7 +1663,7 @@ static int clip_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmEv
sc->xof += pan_vec[0];
sc->yof += pan_vec[1];
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -1702,7 +1701,7 @@ static int clip_prefetch_modal(bContext *C, wmOperator *UNUSED(op), const wmEven
/* running render */
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
return OPERATOR_RUNNING_MODAL;
}
@@ -1797,11 +1796,11 @@ static int clip_set_2d_cursor_exec(bContext *C, wmOperator *op)
static int clip_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceClip *sclip = CTX_wm_space_clip(C);
float location[2];
- ED_clip_mouse_pos(sclip, ar, event->mval, location);
+ ED_clip_mouse_pos(sclip, region, event->mval, location);
RNA_float_set_array(op->ptr, "location", location);
return clip_set_2d_cursor_exec(C, op);
diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c
index fb0362fffd3..b02f3fe16f6 100644
--- a/source/blender/editors/space_clip/clip_toolbar.c
+++ b/source/blender/editors/space_clip/clip_toolbar.c
@@ -38,8 +38,8 @@
#include "RNA_access.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "ED_screen.h"
#include "ED_undo.h"
@@ -53,26 +53,26 @@
/************************** properties ******************************/
-ARegion *ED_clip_has_properties_region(ScrArea *sa)
+ARegion *ED_clip_has_properties_region(ScrArea *area)
{
- ARegion *ar, *arnew;
+ ARegion *region, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) {
- return ar;
+ region = BKE_area_find_region_type(area, RGN_TYPE_UI);
+ if (region) {
+ return region;
}
/* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ region = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
/* is error! */
- if (ar == NULL) {
+ if (region == NULL) {
return NULL;
}
arnew = MEM_callocN(sizeof(ARegion), "clip properties region");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ BLI_insertlinkafter(&area->regionbase, region, arnew);
arnew->regiontype = RGN_TYPE_UI;
arnew->alignment = RGN_ALIGN_RIGHT;
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 902229c0bba..03f791ad70d 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -25,9 +25,9 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
@@ -43,8 +43,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_screen.h"
#include "ED_clip.h"
+#include "ED_screen.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -166,7 +166,8 @@ static float calculate_reprojection_error_at_marker(MovieClip *clip,
reprojected_position[1] = (reprojected_position[1] / (reprojected_position[3] * 2.0f) + 0.5f) *
clip_height * aspy;
- BKE_tracking_distort_v2(tracking, reprojected_position, reprojected_position);
+ BKE_tracking_distort_v2(
+ tracking, clip_width, clip_height, reprojected_position, reprojected_position);
marker_position[0] = (marker->pos[0] + track->offset[0]) * clip_width;
marker_position[1] = (marker->pos[1] + track->offset[1]) * clip_height * aspy;
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 04c939ec41b..a68e06951f7 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -21,43 +21,43 @@
* \ingroup spclip
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
-#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
#include "DNA_movieclip_types.h"
+#include "DNA_scene_types.h"
#include "DNA_view3d_types.h" /* for pivot point */
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_movieclip.h"
-#include "BKE_tracking.h"
#include "BKE_screen.h"
+#include "BKE_tracking.h"
#include "IMB_imbuf_types.h"
#include "ED_anim_api.h" /* for timeline cursor drawing */
+#include "ED_clip.h"
#include "ED_mask.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
-#include "ED_time_scrub_ui.h"
#include "ED_select_utils.h"
-#include "ED_clip.h"
+#include "ED_space_api.h"
+#include "ED_time_scrub_ui.h"
#include "ED_transform.h"
#include "ED_uvedit.h" /* just for ED_image_draw_cursor */
#include "IMB_imbuf.h"
+#include "GPU_framebuffer.h"
#include "GPU_glew.h"
#include "GPU_matrix.h"
-#include "GPU_framebuffer.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -71,128 +71,128 @@
#include "clip_intern.h" /* own include */
static void init_preview_region(const Scene *scene,
- const ScrArea *sa,
+ const ScrArea *area,
const SpaceClip *sc,
- ARegion *ar)
+ ARegion *region)
{
- ar->regiontype = RGN_TYPE_PREVIEW;
- ar->alignment = RGN_ALIGN_TOP;
- ar->flag |= RGN_FLAG_HIDDEN;
+ region->regiontype = RGN_TYPE_PREVIEW;
+ region->alignment = RGN_ALIGN_TOP;
+ region->flag |= RGN_FLAG_HIDDEN;
if (sc->view == SC_VIEW_DOPESHEET) {
- ar->v2d.tot.xmin = -10.0f;
- ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f;
- ar->v2d.tot.xmax = (float)(sa->winx);
- ar->v2d.tot.ymax = 0.0f;
-
- ar->v2d.cur = ar->v2d.tot;
-
- ar->v2d.min[0] = 0.0f;
- ar->v2d.min[1] = 0.0f;
-
- ar->v2d.max[0] = MAXFRAMEF;
- ar->v2d.max[1] = FLT_MAX;
-
- ar->v2d.minzoom = 0.01f;
- ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
- ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
- ar->v2d.keepofs = V2D_KEEPOFS_Y;
- ar->v2d.align = V2D_ALIGN_NO_POS_Y;
- ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+ region->v2d.tot.xmin = -10.0f;
+ region->v2d.tot.ymin = (float)(-area->winy) / 3.0f;
+ region->v2d.tot.xmax = (float)(area->winx);
+ region->v2d.tot.ymax = 0.0f;
+
+ region->v2d.cur = region->v2d.tot;
+
+ region->v2d.min[0] = 0.0f;
+ region->v2d.min[1] = 0.0f;
+
+ region->v2d.max[0] = MAXFRAMEF;
+ region->v2d.max[1] = FLT_MAX;
+
+ region->v2d.minzoom = 0.01f;
+ region->v2d.maxzoom = 50;
+ region->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ region->v2d.scroll |= (V2D_SCROLL_RIGHT);
+ region->v2d.keepzoom = V2D_LOCKZOOM_Y;
+ region->v2d.keepofs = V2D_KEEPOFS_Y;
+ region->v2d.align = V2D_ALIGN_NO_POS_Y;
+ region->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
}
else {
- ar->v2d.tot.xmin = 0.0f;
- ar->v2d.tot.ymin = -10.0f;
- ar->v2d.tot.xmax = (float)scene->r.efra;
- ar->v2d.tot.ymax = 10.0f;
+ region->v2d.tot.xmin = 0.0f;
+ region->v2d.tot.ymin = -10.0f;
+ region->v2d.tot.xmax = (float)scene->r.efra;
+ region->v2d.tot.ymax = 10.0f;
- ar->v2d.cur = ar->v2d.tot;
+ region->v2d.cur = region->v2d.tot;
- ar->v2d.min[0] = FLT_MIN;
- ar->v2d.min[1] = FLT_MIN;
+ region->v2d.min[0] = FLT_MIN;
+ region->v2d.min[1] = FLT_MIN;
- ar->v2d.max[0] = MAXFRAMEF;
- ar->v2d.max[1] = FLT_MAX;
+ region->v2d.max[0] = MAXFRAMEF;
+ region->v2d.max[1] = FLT_MAX;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
+ region->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ region->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
- ar->v2d.minzoom = 0.0f;
- ar->v2d.maxzoom = 0.0f;
- ar->v2d.keepzoom = 0;
- ar->v2d.keepofs = 0;
- ar->v2d.align = 0;
- ar->v2d.flag = 0;
+ region->v2d.minzoom = 0.0f;
+ region->v2d.maxzoom = 0.0f;
+ region->v2d.keepzoom = 0;
+ region->v2d.keepofs = 0;
+ region->v2d.align = 0;
+ region->v2d.flag = 0;
- ar->v2d.keeptot = 0;
+ region->v2d.keeptot = 0;
}
}
-static void reinit_preview_region(const bContext *C, ARegion *ar)
+static void reinit_preview_region(const bContext *C, ARegion *region)
{
Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceClip *sc = CTX_wm_space_clip(C);
if (sc->view == SC_VIEW_DOPESHEET) {
- if ((ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) == 0) {
- init_preview_region(scene, sa, sc, ar);
+ if ((region->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) == 0) {
+ init_preview_region(scene, area, sc, region);
}
}
else {
- if (ar->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) {
- init_preview_region(scene, sa, sc, ar);
+ if (region->v2d.flag & V2D_VIEWSYNC_AREA_VERTICAL) {
+ init_preview_region(scene, area, sc, region);
}
}
}
-static ARegion *ED_clip_has_preview_region(const bContext *C, ScrArea *sa)
+static ARegion *ED_clip_has_preview_region(const bContext *C, ScrArea *area)
{
- ARegion *ar, *arnew;
+ ARegion *region, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
- if (ar) {
- return ar;
+ region = BKE_area_find_region_type(area, RGN_TYPE_PREVIEW);
+ if (region) {
+ return region;
}
/* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
/* is error! */
- if (ar == NULL) {
+ if (region == NULL) {
return NULL;
}
arnew = MEM_callocN(sizeof(ARegion), "clip preview region");
- BLI_insertlinkbefore(&sa->regionbase, ar, arnew);
- init_preview_region(CTX_data_scene(C), sa, CTX_wm_space_clip(C), arnew);
+ BLI_insertlinkbefore(&area->regionbase, region, arnew);
+ init_preview_region(CTX_data_scene(C), area, CTX_wm_space_clip(C), arnew);
return arnew;
}
-static ARegion *ED_clip_has_channels_region(ScrArea *sa)
+static ARegion *ED_clip_has_channels_region(ScrArea *area)
{
- ARegion *ar, *arnew;
+ ARegion *region, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
- if (ar) {
- return ar;
+ region = BKE_area_find_region_type(area, RGN_TYPE_CHANNELS);
+ if (region) {
+ return region;
}
/* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
+ region = BKE_area_find_region_type(area, RGN_TYPE_PREVIEW);
/* is error! */
- if (ar == NULL) {
+ if (region == NULL) {
return NULL;
}
arnew = MEM_callocN(sizeof(ARegion), "clip channels region");
- BLI_insertlinkbefore(&sa->regionbase, ar, arnew);
+ BLI_insertlinkbefore(&area->regionbase, region, arnew);
arnew->regiontype = RGN_TYPE_CHANNELS;
arnew->alignment = RGN_ALIGN_LEFT;
@@ -202,18 +202,18 @@ static ARegion *ED_clip_has_channels_region(ScrArea *sa)
return arnew;
}
-static void clip_scopes_tag_refresh(ScrArea *sa)
+static void clip_scopes_tag_refresh(ScrArea *area)
{
- SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
- ARegion *ar;
+ SpaceClip *sc = (SpaceClip *)area->spacedata.first;
+ ARegion *region;
if (sc->mode != SC_MODE_TRACKING) {
return;
}
/* only while properties are visible */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_UI && ar->flag & RGN_FLAG_HIDDEN) {
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_UI && region->flag & RGN_FLAG_HIDDEN) {
return;
}
}
@@ -221,26 +221,26 @@ static void clip_scopes_tag_refresh(ScrArea *sa)
sc->scopes.ok = false;
}
-static void clip_scopes_check_gpencil_change(ScrArea *sa)
+static void clip_scopes_check_gpencil_change(ScrArea *area)
{
- SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
+ SpaceClip *sc = (SpaceClip *)area->spacedata.first;
if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
- clip_scopes_tag_refresh(sa);
+ clip_scopes_tag_refresh(area);
}
}
-static void clip_area_sync_frame_from_scene(ScrArea *sa, Scene *scene)
+static void clip_area_sync_frame_from_scene(ScrArea *area, Scene *scene)
{
- SpaceClip *space_clip = (SpaceClip *)sa->spacedata.first;
+ SpaceClip *space_clip = (SpaceClip *)area->spacedata.first;
BKE_movieclip_user_set_frame(&space_clip->user, scene->r.cfra);
}
/* ******************** default callbacks for clip space ***************** */
-static SpaceLink *clip_new(const ScrArea *sa, const Scene *scene)
+static SpaceLink *clip_new(const ScrArea *area, const Scene *scene)
{
- ARegion *ar;
+ ARegion *region;
SpaceClip *sc;
sc = MEM_callocN(sizeof(SpaceClip), "initclip");
@@ -253,47 +253,47 @@ static SpaceLink *clip_new(const ScrArea *sa, const Scene *scene)
sc->around = V3D_AROUND_CENTER_MEDIAN;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for clip");
+ region = MEM_callocN(sizeof(ARegion), "header for clip");
- BLI_addtail(&sc->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&sc->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* tools view */
- ar = MEM_callocN(sizeof(ARegion), "tools for clip");
+ region = MEM_callocN(sizeof(ARegion), "tools for clip");
- BLI_addtail(&sc->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOLS;
- ar->alignment = RGN_ALIGN_LEFT;
+ BLI_addtail(&sc->regionbase, region);
+ region->regiontype = RGN_TYPE_TOOLS;
+ region->alignment = RGN_ALIGN_LEFT;
/* properties view */
- ar = MEM_callocN(sizeof(ARegion), "properties for clip");
+ region = MEM_callocN(sizeof(ARegion), "properties for clip");
- BLI_addtail(&sc->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_RIGHT;
+ BLI_addtail(&sc->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_RIGHT;
/* channels view */
- ar = MEM_callocN(sizeof(ARegion), "channels for clip");
+ region = MEM_callocN(sizeof(ARegion), "channels for clip");
- BLI_addtail(&sc->regionbase, ar);
- ar->regiontype = RGN_TYPE_CHANNELS;
- ar->alignment = RGN_ALIGN_LEFT;
+ BLI_addtail(&sc->regionbase, region);
+ region->regiontype = RGN_TYPE_CHANNELS;
+ region->alignment = RGN_ALIGN_LEFT;
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
- ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+ region->v2d.scroll = V2D_SCROLL_BOTTOM;
+ region->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
/* preview view */
- ar = MEM_callocN(sizeof(ARegion), "preview for clip");
+ region = MEM_callocN(sizeof(ARegion), "preview for clip");
- BLI_addtail(&sc->regionbase, ar);
- init_preview_region(scene, sa, sc, ar);
+ BLI_addtail(&sc->regionbase, region);
+ init_preview_region(scene, area, sc, region);
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for clip");
+ region = MEM_callocN(sizeof(ARegion), "main region for clip");
- BLI_addtail(&sc->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sc->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
return (SpaceLink *)sc;
}
@@ -315,12 +315,12 @@ static void clip_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void clip_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void clip_init(struct wmWindowManager *UNUSED(wm), ScrArea *area)
{
ListBase *lb = WM_dropboxmap_find("Clip", SPACE_CLIP, 0);
/* add drop boxes */
- WM_event_add_dropbox_handler(&sa->handlers, lb);
+ WM_event_add_dropbox_handler(&area->handlers, lb);
}
static SpaceLink *clip_duplicate(SpaceLink *sl)
@@ -335,18 +335,18 @@ static SpaceLink *clip_duplicate(SpaceLink *sl)
return (SpaceLink *)scn;
}
-static void clip_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *scene)
+static void clip_listener(wmWindow *UNUSED(win), ScrArea *area, wmNotifier *wmn, Scene *scene)
{
/* context changes */
switch (wmn->category) {
case NC_SCENE:
switch (wmn->data) {
case ND_FRAME:
- clip_scopes_tag_refresh(sa);
+ clip_scopes_tag_refresh(area);
ATTR_FALLTHROUGH;
case ND_FRAME_RANGE:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
break;
@@ -354,8 +354,8 @@ static void clip_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, S
switch (wmn->data) {
case ND_DISPLAY:
case ND_SELECT:
- clip_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ clip_scopes_tag_refresh(area);
+ ED_area_tag_redraw(area);
break;
}
switch (wmn->action) {
@@ -365,8 +365,8 @@ static void clip_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, S
/* fall-through */
case NA_SELECTED:
- clip_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ clip_scopes_tag_refresh(area);
+ ED_area_tag_redraw(area);
break;
}
break;
@@ -375,56 +375,56 @@ static void clip_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, S
case ND_SELECT:
case ND_DATA:
case ND_DRAW:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
switch (wmn->action) {
case NA_SELECTED:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case NA_EDITED:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
break;
case NC_GEOM:
switch (wmn->data) {
case ND_SELECT:
- clip_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ clip_scopes_tag_refresh(area);
+ ED_area_tag_redraw(area);
break;
}
break;
case NC_SCREEN:
switch (wmn->data) {
case ND_ANIMPLAY:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case ND_LAYOUTSET:
- clip_area_sync_frame_from_scene(sa, scene);
+ clip_area_sync_frame_from_scene(area, scene);
break;
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_CLIP) {
- clip_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ clip_scopes_tag_refresh(area);
+ ED_area_tag_redraw(area);
}
break;
case NC_GPENCIL:
if (wmn->action == NA_EDITED) {
- clip_scopes_check_gpencil_change(sa);
- ED_area_tag_redraw(sa);
+ clip_scopes_check_gpencil_change(area);
+ ED_area_tag_redraw(area);
}
else if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
case NC_WM:
switch (wmn->data) {
case ND_FILEREAD:
case ND_UNDO:
- clip_area_sync_frame_from_scene(sa, scene);
+ clip_area_sync_frame_from_scene(area, scene);
break;
}
break;
@@ -605,7 +605,7 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul
static bool clip_drop_poll(bContext *UNUSED(C),
wmDrag *drag,
const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
if (drag->type == WM_DRAG_PATH) {
/* rule might not work? */
@@ -639,17 +639,17 @@ static void clip_dropboxes(void)
WM_dropbox_add(lb, "CLIP_OT_open", clip_drop_poll, clip_drop_copy);
}
-static void clip_refresh(const bContext *C, ScrArea *sa)
+static void clip_refresh(const bContext *C, ScrArea *area)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *window = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
- SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
- ARegion *ar_main = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- ARegion *ar_tools = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
- ARegion *ar_preview = ED_clip_has_preview_region(C, sa);
- ARegion *ar_properties = ED_clip_has_properties_region(sa);
- ARegion *ar_channels = ED_clip_has_channels_region(sa);
+ SpaceClip *sc = (SpaceClip *)area->spacedata.first;
+ ARegion *region_main = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+ ARegion *region_tools = BKE_area_find_region_type(area, RGN_TYPE_TOOLS);
+ ARegion *region_preview = ED_clip_has_preview_region(C, area);
+ ARegion *region_properties = ED_clip_has_properties_region(area);
+ ARegion *region_channels = ED_clip_has_channels_region(area);
bool main_visible = false, preview_visible = false, tools_visible = false;
bool properties_visible = false, channels_visible = false;
bool view_changed = false;
@@ -669,7 +669,7 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
properties_visible = false;
channels_visible = false;
- reinit_preview_region(C, ar_preview);
+ reinit_preview_region(C, region_preview);
break;
case SC_VIEW_DOPESHEET:
main_visible = false;
@@ -678,135 +678,135 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
properties_visible = false;
channels_visible = true;
- reinit_preview_region(C, ar_preview);
+ reinit_preview_region(C, region_preview);
break;
}
if (main_visible) {
- if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
- ar_main->flag &= ~RGN_FLAG_HIDDEN;
- ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
+ if (region_main && (region_main->flag & RGN_FLAG_HIDDEN)) {
+ region_main->flag &= ~RGN_FLAG_HIDDEN;
+ region_main->v2d.flag &= ~V2D_IS_INITIALISED;
view_changed = true;
}
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
+ if (region_main && region_main->alignment != RGN_ALIGN_NONE) {
+ region_main->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
}
else {
- if (ar_main && !(ar_main->flag & RGN_FLAG_HIDDEN)) {
- ar_main->flag |= RGN_FLAG_HIDDEN;
- ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
- WM_event_remove_handlers((bContext *)C, &ar_main->handlers);
+ if (region_main && !(region_main->flag & RGN_FLAG_HIDDEN)) {
+ region_main->flag |= RGN_FLAG_HIDDEN;
+ region_main->v2d.flag &= ~V2D_IS_INITIALISED;
+ WM_event_remove_handlers((bContext *)C, &region_main->handlers);
view_changed = true;
}
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
+ if (region_main && region_main->alignment != RGN_ALIGN_NONE) {
+ region_main->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
}
if (properties_visible) {
- if (ar_properties && (ar_properties->flag & RGN_FLAG_HIDDEN)) {
- ar_properties->flag &= ~RGN_FLAG_HIDDEN;
- ar_properties->v2d.flag &= ~V2D_IS_INITIALISED;
+ if (region_properties && (region_properties->flag & RGN_FLAG_HIDDEN)) {
+ region_properties->flag &= ~RGN_FLAG_HIDDEN;
+ region_properties->v2d.flag &= ~V2D_IS_INITIALISED;
view_changed = true;
}
- if (ar_properties && ar_properties->alignment != RGN_ALIGN_RIGHT) {
- ar_properties->alignment = RGN_ALIGN_RIGHT;
+ if (region_properties && region_properties->alignment != RGN_ALIGN_RIGHT) {
+ region_properties->alignment = RGN_ALIGN_RIGHT;
view_changed = true;
}
}
else {
- if (ar_properties && !(ar_properties->flag & RGN_FLAG_HIDDEN)) {
- ar_properties->flag |= RGN_FLAG_HIDDEN;
- ar_properties->v2d.flag &= ~V2D_IS_INITIALISED;
- WM_event_remove_handlers((bContext *)C, &ar_properties->handlers);
+ if (region_properties && !(region_properties->flag & RGN_FLAG_HIDDEN)) {
+ region_properties->flag |= RGN_FLAG_HIDDEN;
+ region_properties->v2d.flag &= ~V2D_IS_INITIALISED;
+ WM_event_remove_handlers((bContext *)C, &region_properties->handlers);
view_changed = true;
}
- if (ar_properties && ar_properties->alignment != RGN_ALIGN_NONE) {
- ar_properties->alignment = RGN_ALIGN_NONE;
+ if (region_properties && region_properties->alignment != RGN_ALIGN_NONE) {
+ region_properties->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
}
if (tools_visible) {
- if (ar_tools && (ar_tools->flag & RGN_FLAG_HIDDEN)) {
- ar_tools->flag &= ~RGN_FLAG_HIDDEN;
- ar_tools->v2d.flag &= ~V2D_IS_INITIALISED;
+ if (region_tools && (region_tools->flag & RGN_FLAG_HIDDEN)) {
+ region_tools->flag &= ~RGN_FLAG_HIDDEN;
+ region_tools->v2d.flag &= ~V2D_IS_INITIALISED;
view_changed = true;
}
- if (ar_tools && ar_tools->alignment != RGN_ALIGN_LEFT) {
- ar_tools->alignment = RGN_ALIGN_LEFT;
+ if (region_tools && region_tools->alignment != RGN_ALIGN_LEFT) {
+ region_tools->alignment = RGN_ALIGN_LEFT;
view_changed = true;
}
}
else {
- if (ar_tools && !(ar_tools->flag & RGN_FLAG_HIDDEN)) {
- ar_tools->flag |= RGN_FLAG_HIDDEN;
- ar_tools->v2d.flag &= ~V2D_IS_INITIALISED;
- WM_event_remove_handlers((bContext *)C, &ar_tools->handlers);
+ if (region_tools && !(region_tools->flag & RGN_FLAG_HIDDEN)) {
+ region_tools->flag |= RGN_FLAG_HIDDEN;
+ region_tools->v2d.flag &= ~V2D_IS_INITIALISED;
+ WM_event_remove_handlers((bContext *)C, &region_tools->handlers);
view_changed = true;
}
- if (ar_tools && ar_tools->alignment != RGN_ALIGN_NONE) {
- ar_tools->alignment = RGN_ALIGN_NONE;
+ if (region_tools && region_tools->alignment != RGN_ALIGN_NONE) {
+ region_tools->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
}
if (preview_visible) {
- if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
- ar_preview->flag &= ~RGN_FLAG_HIDDEN;
- ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
- ar_preview->v2d.cur = ar_preview->v2d.tot;
+ if (region_preview && (region_preview->flag & RGN_FLAG_HIDDEN)) {
+ region_preview->flag &= ~RGN_FLAG_HIDDEN;
+ region_preview->v2d.flag &= ~V2D_IS_INITIALISED;
+ region_preview->v2d.cur = region_preview->v2d.tot;
view_changed = true;
}
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
- ar_preview->alignment = RGN_ALIGN_NONE;
+ if (region_preview && region_preview->alignment != RGN_ALIGN_NONE) {
+ region_preview->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
}
else {
- if (ar_preview && !(ar_preview->flag & RGN_FLAG_HIDDEN)) {
- ar_preview->flag |= RGN_FLAG_HIDDEN;
- ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
- WM_event_remove_handlers((bContext *)C, &ar_preview->handlers);
+ if (region_preview && !(region_preview->flag & RGN_FLAG_HIDDEN)) {
+ region_preview->flag |= RGN_FLAG_HIDDEN;
+ region_preview->v2d.flag &= ~V2D_IS_INITIALISED;
+ WM_event_remove_handlers((bContext *)C, &region_preview->handlers);
view_changed = true;
}
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
- ar_preview->alignment = RGN_ALIGN_NONE;
+ if (region_preview && region_preview->alignment != RGN_ALIGN_NONE) {
+ region_preview->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
}
if (channels_visible) {
- if (ar_channels && (ar_channels->flag & RGN_FLAG_HIDDEN)) {
- ar_channels->flag &= ~RGN_FLAG_HIDDEN;
- ar_channels->v2d.flag &= ~V2D_IS_INITIALISED;
+ if (region_channels && (region_channels->flag & RGN_FLAG_HIDDEN)) {
+ region_channels->flag &= ~RGN_FLAG_HIDDEN;
+ region_channels->v2d.flag &= ~V2D_IS_INITIALISED;
view_changed = true;
}
- if (ar_channels && ar_channels->alignment != RGN_ALIGN_LEFT) {
- ar_channels->alignment = RGN_ALIGN_LEFT;
+ if (region_channels && region_channels->alignment != RGN_ALIGN_LEFT) {
+ region_channels->alignment = RGN_ALIGN_LEFT;
view_changed = true;
}
}
else {
- if (ar_channels && !(ar_channels->flag & RGN_FLAG_HIDDEN)) {
- ar_channels->flag |= RGN_FLAG_HIDDEN;
- ar_channels->v2d.flag &= ~V2D_IS_INITIALISED;
- WM_event_remove_handlers((bContext *)C, &ar_channels->handlers);
+ if (region_channels && !(region_channels->flag & RGN_FLAG_HIDDEN)) {
+ region_channels->flag |= RGN_FLAG_HIDDEN;
+ region_channels->v2d.flag &= ~V2D_IS_INITIALISED;
+ WM_event_remove_handlers((bContext *)C, &region_channels->handlers);
view_changed = true;
}
- if (ar_channels && ar_channels->alignment != RGN_ALIGN_NONE) {
- ar_channels->alignment = RGN_ALIGN_NONE;
+ if (region_channels && region_channels->alignment != RGN_ALIGN_NONE) {
+ region_channels->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
}
if (view_changed) {
- ED_area_initialize(wm, window, sa);
- ED_area_tag_redraw(sa);
+ ED_area_initialize(wm, window, area);
+ ED_area_tag_redraw(area);
}
BKE_movieclip_user_set_frame(&sc->user, scene->r.cfra);
@@ -828,7 +828,7 @@ static void clip_gizmos(void)
/********************* main region ********************/
/* sets up the fields of the View2D from zoom and offset */
-static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar)
+static void movieclip_main_area_set_view2d(const bContext *C, ARegion *region)
{
SpaceClip *sc = CTX_wm_space_clip(C);
float x1, y1, w, h, aspx, aspy;
@@ -840,60 +840,60 @@ static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar)
w = width * aspx;
h = height * aspy;
- winx = BLI_rcti_size_x(&ar->winrct) + 1;
- winy = BLI_rcti_size_y(&ar->winrct) + 1;
+ winx = BLI_rcti_size_x(&region->winrct) + 1;
+ winy = BLI_rcti_size_y(&region->winrct) + 1;
- ar->v2d.tot.xmin = 0;
- ar->v2d.tot.ymin = 0;
- ar->v2d.tot.xmax = w;
- ar->v2d.tot.ymax = h;
+ region->v2d.tot.xmin = 0;
+ region->v2d.tot.ymin = 0;
+ region->v2d.tot.xmax = w;
+ region->v2d.tot.ymax = h;
- ar->v2d.mask.xmin = ar->v2d.mask.ymin = 0;
- ar->v2d.mask.xmax = winx;
- ar->v2d.mask.ymax = winy;
+ region->v2d.mask.xmin = region->v2d.mask.ymin = 0;
+ region->v2d.mask.xmax = winx;
+ region->v2d.mask.ymax = winy;
/* which part of the image space do we see? */
- x1 = ar->winrct.xmin + (winx - sc->zoom * w) / 2.0f;
- y1 = ar->winrct.ymin + (winy - sc->zoom * h) / 2.0f;
+ x1 = region->winrct.xmin + (winx - sc->zoom * w) / 2.0f;
+ y1 = region->winrct.ymin + (winy - sc->zoom * h) / 2.0f;
x1 -= sc->zoom * sc->xof;
y1 -= sc->zoom * sc->yof;
/* relative display right */
- ar->v2d.cur.xmin = (ar->winrct.xmin - (float)x1) / sc->zoom;
- ar->v2d.cur.xmax = ar->v2d.cur.xmin + ((float)winx / sc->zoom);
+ region->v2d.cur.xmin = (region->winrct.xmin - (float)x1) / sc->zoom;
+ region->v2d.cur.xmax = region->v2d.cur.xmin + ((float)winx / sc->zoom);
/* relative display left */
- ar->v2d.cur.ymin = (ar->winrct.ymin - (float)y1) / sc->zoom;
- ar->v2d.cur.ymax = ar->v2d.cur.ymin + ((float)winy / sc->zoom);
+ region->v2d.cur.ymin = (region->winrct.ymin - (float)y1) / sc->zoom;
+ region->v2d.cur.ymax = region->v2d.cur.ymin + ((float)winy / sc->zoom);
/* normalize 0.0..1.0 */
- ar->v2d.cur.xmin /= w;
- ar->v2d.cur.xmax /= w;
- ar->v2d.cur.ymin /= h;
- ar->v2d.cur.ymax /= h;
+ region->v2d.cur.xmin /= w;
+ region->v2d.cur.xmax /= w;
+ region->v2d.cur.ymin /= h;
+ region->v2d.cur.ymax /= h;
}
/* add handlers, stuff you only do once or on area/region changes */
-static void clip_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void clip_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_STANDARD, region->winx, region->winy);
/* mask polls mode */
keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Clip Editor", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void clip_main_region_draw(const bContext *C, ARegion *ar)
+static void clip_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceClip *sc = CTX_wm_space_clip(C);
@@ -915,7 +915,7 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
tmpibuf = ED_space_clip_get_stable_buffer(sc, NULL, NULL, NULL);
}
- if (ED_clip_view_selection(C, ar, 0)) {
+ if (ED_clip_view_selection(C, region, 0)) {
sc->xof += sc->xlockof;
sc->yof += sc->ylockof;
}
@@ -930,28 +930,28 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
GPU_clear(GPU_COLOR_BIT);
/* data... */
- movieclip_main_area_set_view2d(C, ar);
+ movieclip_main_area_set_view2d(C, region);
/* callback */
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
- clip_draw_main(C, sc, ar);
+ clip_draw_main(C, sc, region);
/* TODO(sergey): would be nice to find a way to de-duplicate all this space conversions */
- UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region_fl(&region->v2d, 0.0f, 0.0f, &x, &y);
ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+ ED_space_clip_get_zoom(sc, region, &zoomx, &zoomy);
ED_space_clip_get_aspect(sc, &aspx, &aspy);
if (sc->mode == SC_MODE_MASKEDIT) {
Mask *mask = CTX_data_edit_mask(C);
if (mask && clip) {
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
int mask_width, mask_height;
- ED_mask_get_size(sa, &mask_width, &mask_height);
+ ED_mask_get_size(area, &mask_width, &mask_height);
ED_mask_draw_region(CTX_data_expect_evaluated_depsgraph(C),
mask,
- ar,
+ region,
sc->mask_info.draw_flag,
sc->mask_info.draw_type,
sc->mask_info.overlay_mode,
@@ -975,11 +975,11 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
GPU_matrix_scale_2f(zoomx, zoomy);
GPU_matrix_mul(sc->stabmat);
GPU_matrix_scale_2f(width, height);
- ED_image_draw_cursor(ar, sc->cursor);
+ ED_image_draw_cursor(region, sc->cursor);
GPU_matrix_pop();
}
- clip_draw_cache_and_notes(C, sc, ar);
+ clip_draw_cache_and_notes(C, sc, region);
if (sc->flag & SC_SHOW_ANNOTATION) {
/* Grease Pencil */
@@ -987,7 +987,7 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
}
/* callback */
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -997,12 +997,12 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
clip_draw_grease_pencil((bContext *)C, false);
}
- WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
+ WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
}
static void clip_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -1010,10 +1010,10 @@ static void clip_main_region_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_GPENCIL:
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
else if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -1021,37 +1021,37 @@ static void clip_main_region_listener(wmWindow *UNUSED(win),
/****************** preview region ******************/
-static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar)
+static void clip_preview_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Clip Time Scrub", SPACE_CLIP, RGN_TYPE_PREVIEW);
- WM_event_add_keymap_handler_poll(&ar->handlers, keymap, ED_time_scrub_event_in_region);
+ WM_event_add_keymap_handler_poll(&region->handlers, keymap, ED_time_scrub_event_in_region);
keymap = WM_keymap_ensure(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void graph_region_draw(const bContext *C, ARegion *ar)
+static void graph_region_draw(const bContext *C, ARegion *region)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
SpaceClip *sc = CTX_wm_space_clip(C);
Scene *scene = CTX_data_scene(C);
short cfra_flag = 0;
if (sc->flag & SC_LOCK_TIMECURSOR) {
- ED_clip_graph_center_current_frame(scene, ar);
+ ED_clip_graph_center_current_frame(scene, region);
}
/* clear and setup matrix */
@@ -1061,7 +1061,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_ortho(v2d);
/* data... */
- clip_draw_graph(sc, ar, scene);
+ clip_draw_graph(sc, region, scene);
/* current frame indicator line */
if (sc->flag & SC_SHOW_SECONDS) {
@@ -1073,7 +1073,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* time-scrubbing */
- ED_time_scrub_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
+ ED_time_scrub_draw(region, scene, sc->flag & SC_SHOW_SECONDS, true);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -1083,17 +1083,18 @@ static void graph_region_draw(const bContext *C, ARegion *ar)
/* scale indicators */
{
rcti rect;
- BLI_rcti_init(&rect, 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, ar->winy - UI_TIME_SCRUB_MARGIN_Y);
- UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_TEXT);
+ BLI_rcti_init(
+ &rect, 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, region->winy - UI_TIME_SCRUB_MARGIN_Y);
+ UI_view2d_draw_scale_y__values(region, v2d, &rect, TH_TEXT);
}
}
-static void dopesheet_region_draw(const bContext *C, ARegion *ar)
+static void dopesheet_region_draw(const bContext *C, ARegion *region)
{
Scene *scene = CTX_data_scene(C);
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
short cfra_flag = 0;
@@ -1111,7 +1112,7 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar)
UI_view2d_draw_lines_x__discrete_frames_or_seconds(v2d, scene, sc->flag & SC_SHOW_SECONDS);
/* data... */
- clip_draw_dopesheet_main(sc, ar, scene);
+ clip_draw_dopesheet_main(sc, region, scene);
/* current frame indicator line */
if (sc->flag & SC_SHOW_SECONDS) {
@@ -1123,7 +1124,7 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* time-scrubbing */
- ED_time_scrub_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
+ ED_time_scrub_draw(region, scene, sc->flag & SC_SHOW_SECONDS, true);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -1131,21 +1132,21 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
}
-static void clip_preview_region_draw(const bContext *C, ARegion *ar)
+static void clip_preview_region_draw(const bContext *C, ARegion *region)
{
SpaceClip *sc = CTX_wm_space_clip(C);
if (sc->view == SC_VIEW_GRAPH) {
- graph_region_draw(C, ar);
+ graph_region_draw(C, region);
}
else if (sc->view == SC_VIEW_DOPESHEET) {
- dopesheet_region_draw(C, ar);
+ dopesheet_region_draw(C, region);
}
}
static void clip_preview_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *UNUSED(ar),
+ ScrArea *UNUSED(area),
+ ARegion *UNUSED(region),
wmNotifier *UNUSED(wmn),
const Scene *UNUSED(scene))
{
@@ -1153,24 +1154,24 @@ static void clip_preview_region_listener(wmWindow *UNUSED(win),
/****************** channels region ******************/
-static void clip_channels_region_init(wmWindowManager *wm, ARegion *ar)
+static void clip_channels_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
/* ensure the 2d view sync works - main region has bottom scroller */
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+ region->v2d.scroll = V2D_SCROLL_BOTTOM;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
keymap = WM_keymap_ensure(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void clip_channels_region_draw(const bContext *C, ARegion *ar)
+static void clip_channels_region_draw(const bContext *C, ARegion *region)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
if (clip) {
BKE_tracking_dopesheet_update(&clip->tracking);
@@ -1183,15 +1184,15 @@ static void clip_channels_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_ortho(v2d);
/* data... */
- clip_draw_dopesheet_channels(C, ar);
+ clip_draw_dopesheet_channels(C, region);
/* reset view matrix */
UI_view2d_view_restore(C);
}
static void clip_channels_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *UNUSED(ar),
+ ScrArea *UNUSED(area),
+ ARegion *UNUSED(region),
wmNotifier *UNUSED(wmn),
const Scene *UNUSED(scene))
{
@@ -1200,19 +1201,19 @@ static void clip_channels_region_listener(wmWindow *UNUSED(win),
/****************** header region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void clip_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void clip_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void clip_header_region_draw(const bContext *C, ARegion *ar)
+static void clip_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
static void clip_header_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -1225,7 +1226,7 @@ static void clip_header_region_listener(wmWindow *UNUSED(win),
/* TODO - should do this when in mask mode only but no data available */
// if (sc->mode == SC_MODE_MASKEDIT)
{
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
}
@@ -1236,26 +1237,26 @@ static void clip_header_region_listener(wmWindow *UNUSED(win),
/****************** tools region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void clip_tools_region_init(wmWindowManager *wm, ARegion *ar)
+static void clip_tools_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void clip_tools_region_draw(const bContext *C, ARegion *ar)
+static void clip_tools_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
/****************** tool properties region ******************/
static void clip_props_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -1263,22 +1264,22 @@ static void clip_props_region_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_WM:
if (wmn->data == ND_HISTORY) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
if (wmn->data == ND_MODE) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_CLIP) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_GPENCIL:
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -1287,28 +1288,28 @@ static void clip_props_region_listener(wmWindow *UNUSED(win),
/****************** properties region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void clip_properties_region_init(wmWindowManager *wm, ARegion *ar)
+static void clip_properties_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void clip_properties_region_draw(const bContext *C, ARegion *ar)
+static void clip_properties_region_draw(const bContext *C, ARegion *region)
{
SpaceClip *sc = CTX_wm_space_clip(C);
BKE_movieclip_update_scopes(sc->clip, &sc->user, &sc->scopes);
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
static void clip_properties_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -1316,12 +1317,12 @@ static void clip_properties_region_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_GPENCIL:
if (ELEM(wmn->data, ND_DATA, ND_GPENCIL_EDITMODE)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_BRUSH:
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -1329,7 +1330,7 @@ static void clip_properties_region_listener(wmWindow *UNUSED(win),
/********************* registration ********************/
-static void clip_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void clip_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceClip *sclip = (SpaceClip *)slink;
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index f1bce00ea0b..739701b5595 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -26,23 +26,23 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
-#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_movieclip.h"
-#include "BKE_tracking.h"
#include "BKE_report.h"
+#include "BKE_tracking.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_screen.h"
#include "ED_clip.h"
+#include "ED_screen.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -108,12 +108,12 @@ static int add_marker_exec(bContext *C, wmOperator *op)
static int add_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
if (!RNA_struct_property_is_set(op->ptr, "location")) {
/* If location is not set, use mouse positio nas default. */
float co[2];
- ED_clip_mouse_pos(sc, ar, event->mval, co);
+ ED_clip_mouse_pos(sc, region, event->mval, co);
RNA_float_set_array(op->ptr, "location", co);
}
@@ -169,13 +169,17 @@ static int add_marker_at_click_modal(bContext *C, wmOperator *UNUSED(op), const
case LEFTMOUSE: {
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float pos[2];
ED_workspace_status_text(C, NULL);
- ED_clip_point_stable_pos(
- sc, ar, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin, &pos[0], &pos[1]);
+ ED_clip_point_stable_pos(sc,
+ region,
+ event->x - region->winrct.xmin,
+ event->y - region->winrct.ymin,
+ &pos[0],
+ &pos[1]);
if (!add_marker(C, pos[0], pos[1])) {
return OPERATOR_CANCELLED;
@@ -185,7 +189,7 @@ static int add_marker_at_click_modal(bContext *C, wmOperator *UNUSED(op), const
return OPERATOR_FINISHED;
}
- case ESCKEY:
+ case EVT_ESCKEY:
ED_workspace_status_text(C, NULL);
return OPERATOR_CANCELLED;
}
@@ -450,7 +454,7 @@ static float mouse_to_slide_zone_distance_squared(const float co[2],
{
const float pixel_co[2] = {co[0] * width, co[1] * height},
pixel_slide_zone[2] = {slide_zone[0] * width, slide_zone[1] * height};
- return SQUARE(pixel_co[0] - pixel_slide_zone[0]) + SQUARE(pixel_co[1] - pixel_slide_zone[1]);
+ return square_f(pixel_co[0] - pixel_slide_zone[0]) + square_f(pixel_co[1] - pixel_slide_zone[1]);
}
static float mouse_to_search_corner_distance_squared(
@@ -540,11 +544,11 @@ static bool slide_check_corners(float (*corners)[2])
}
MovieTrackingTrack *tracking_marker_check_slide(
- bContext *C, const wmEvent *event, int *area_r, int *action_r, int *corner_r)
+ bContext *C, const wmEvent *event, int *r_area, int *r_action, int *r_corner)
{
const float distance_clip_squared = 12.0f * 12.0f;
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTrackingTrack *track;
@@ -566,7 +570,7 @@ MovieTrackingTrack *tracking_marker_check_slide(
return NULL;
}
- ED_clip_mouse_pos(sc, ar, event->mval, co);
+ ED_clip_mouse_pos(sc, region, event->mval, co);
track = tracksbase->first;
while (track) {
@@ -653,14 +657,14 @@ MovieTrackingTrack *tracking_marker_check_slide(
}
if (global_min_distance_squared < distance_clip_squared / sc->zoom) {
- if (area_r) {
- *area_r = min_area;
+ if (r_area) {
+ *r_area = min_area;
}
- if (action_r) {
- *action_r = min_action;
+ if (r_action) {
+ *r_action = min_action;
}
- if (corner_r) {
- *corner_r = min_corner;
+ if (r_corner) {
+ *r_corner = min_corner;
}
return min_track;
}
@@ -670,7 +674,7 @@ MovieTrackingTrack *tracking_marker_check_slide(
static void *slide_marker_customdata(bContext *C, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
MovieTrackingTrack *track;
int width, height;
@@ -685,7 +689,7 @@ static void *slide_marker_customdata(bContext *C, const wmEvent *event)
return NULL;
}
- ED_clip_mouse_pos(sc, ar, event->mval, co);
+ ED_clip_mouse_pos(sc, region, event->mval, co);
track = tracking_marker_check_slide(C, event, &area, &action, &corner);
if (track != NULL) {
@@ -770,23 +774,23 @@ static void free_slide_data(SlideMarkerData *data)
static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SlideMarkerData *data = (SlideMarkerData *)op->customdata;
float dx, dy, mdelta[2];
switch (event->type) {
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY:
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
+ case EVT_LEFTCTRLKEY:
+ case EVT_RIGHTCTRLKEY:
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
if (data->action == SLIDE_ACTION_SIZE) {
- if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) {
+ if (ELEM(event->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY)) {
data->lock = event->val == KM_RELEASE;
}
}
- if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
+ if (ELEM(event->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY)) {
data->accurate = event->val == KM_PRESS;
}
ATTR_FALLTHROUGH;
@@ -826,7 +830,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
float start[2], end[2];
float scale;
- ED_clip_point_stable_pos(sc, ar, data->mval[0], data->mval[1], &start[0], &start[1]);
+ ED_clip_point_stable_pos(sc, region, data->mval[0], data->mval[1], &start[0], &start[1]);
sub_v2_v2(start, data->old_pos);
@@ -842,7 +846,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
mval[1] = event->mval[1];
}
- ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &end[0], &end[1]);
+ ED_clip_point_stable_pos(sc, region, mval[0], mval[1], &end[0], &end[1]);
sub_v2_v2(end, data->old_pos);
scale = len_v2(end) / len_v2(start);
@@ -896,7 +900,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
sub_v2_v2v2(start, data->spos, data->old_pos);
- ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &end[0], &end[1]);
+ ED_clip_point_stable_pos(sc, region, mval[0], mval[1], &end[0], &end[1]);
sub_v2_v2(end, data->old_pos);
if (len_squared_v2(start) != 0.0f) {
@@ -962,7 +966,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
- case ESCKEY:
+ case EVT_ESCKEY:
cancel_mouse_slide(op->customdata);
free_slide_data(op->customdata);
diff --git a/source/blender/editors/space_clip/tracking_ops_detect.c b/source/blender/editors/space_clip/tracking_ops_detect.c
index a9c97258def..dd620e85324 100644
--- a/source/blender/editors/space_clip/tracking_ops_detect.c
+++ b/source/blender/editors/space_clip/tracking_ops_detect.c
@@ -31,16 +31,16 @@
#include "BKE_context.h"
#include "BKE_movieclip.h"
-#include "BKE_tracking.h"
#include "BKE_report.h"
+#include "BKE_tracking.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_clip.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c
index de0025a53d2..25e30c116c5 100644
--- a/source/blender/editors/space_clip/tracking_ops_orient.c
+++ b/source/blender/editors/space_clip/tracking_ops_orient.c
@@ -28,15 +28,15 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
-#include "BKE_context.h"
#include "BKE_constraint.h"
-#include "BKE_tracking.h"
+#include "BKE_context.h"
#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "BKE_tracking.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -210,7 +210,7 @@ static int set_origin_exec(bContext *C, wmOperator *op)
mul_v3_fl(median, 1.0f / selected_count);
float mat[4][4], vec[3];
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(camera, mat);
mul_v3_m4v3(vec, mat, median);
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
@@ -267,7 +267,7 @@ static void set_axis(Scene *scene,
BKE_object_to_mat4(ob, obmat);
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(camera, mat);
mul_v3_m4v3(vec, mat, track->bundle_pos);
copy_v3_v3(dvec, vec);
@@ -422,7 +422,7 @@ static int set_plane_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(camera, mat);
/* Get 3 bundles to use as reference. */
track = tracksbase->first;
@@ -629,7 +629,7 @@ static int do_set_scale(bContext *C, wmOperator *op, bool scale_solution, bool a
}
}
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(camera, mat);
track = tracksbase->first;
while (track) {
diff --git a/source/blender/editors/space_clip/tracking_ops_plane.c b/source/blender/editors/space_clip/tracking_ops_plane.c
index 03fe1c74e2a..3c5646911a3 100644
--- a/source/blender/editors/space_clip/tracking_ops_plane.c
+++ b/source/blender/editors/space_clip/tracking_ops_plane.c
@@ -26,12 +26,12 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_tracking.h"
#include "BKE_report.h"
+#include "BKE_tracking.h"
#include "DEG_depsgraph.h"
@@ -117,16 +117,16 @@ static float mouse_to_plane_slide_zone_distance_squared(const float co[2],
{
const float pixel_co[2] = {co[0] * width, co[1] * height},
pixel_slide_zone[2] = {slide_zone[0] * width, slide_zone[1] * height};
- return SQUARE(pixel_co[0] - pixel_slide_zone[0]) + SQUARE(pixel_co[1] - pixel_slide_zone[1]);
+ return square_f(pixel_co[0] - pixel_slide_zone[0]) + square_f(pixel_co[1] - pixel_slide_zone[1]);
}
static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C,
const wmEvent *event,
- int *corner_r)
+ int *r_corner)
{
const float distance_clip_squared = 12.0f * 12.0f;
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
int width, height;
@@ -139,7 +139,7 @@ static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C,
return NULL;
}
- ED_clip_mouse_pos(sc, ar, event->mval, co);
+ ED_clip_mouse_pos(sc, region, event->mval, co);
float min_distance_squared = FLT_MAX;
int min_corner = -1;
@@ -162,8 +162,8 @@ static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C,
}
if (min_distance_squared < distance_clip_squared / sc->zoom) {
- if (corner_r != NULL) {
- *corner_r = min_corner;
+ if (r_corner != NULL) {
+ *r_corner = min_corner;
}
return min_plane_track;
}
@@ -174,7 +174,7 @@ static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C,
static void *slide_plane_marker_customdata(bContext *C, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
MovieTrackingPlaneTrack *plane_track;
int width, height;
float co[2];
@@ -187,7 +187,7 @@ static void *slide_plane_marker_customdata(bContext *C, const wmEvent *event)
return NULL;
}
- ED_clip_mouse_pos(sc, ar, event->mval, co);
+ ED_clip_mouse_pos(sc, region, event->mval, co);
plane_track = tracking_plane_marker_check_slide(C, event, &corner);
if (plane_track) {
@@ -270,11 +270,11 @@ static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *
float next_edge[2], prev_edge[2], next_diag_edge[2], prev_diag_edge[2];
switch (event->type) {
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY:
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
+ case EVT_LEFTCTRLKEY:
+ case EVT_RIGHTCTRLKEY:
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
+ if (ELEM(event->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY)) {
data->accurate = event->val == KM_PRESS;
}
ATTR_FALLTHROUGH;
@@ -363,7 +363,7 @@ static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *
break;
- case ESCKEY:
+ case EVT_ESCKEY:
cancel_mouse_slide_plane_marker(op->customdata);
free_slide_plane_marker_data(op->customdata);
diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c
index 7e2671382b9..c18207d7045 100644
--- a/source/blender/editors/space_clip/tracking_ops_solve.c
+++ b/source/blender/editors/space_clip/tracking_ops_solve.c
@@ -28,12 +28,12 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_movieclip.h"
#include "BKE_report.h"
#include "BKE_tracking.h"
@@ -261,7 +261,7 @@ static int solve_camera_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent
/* Running solver. */
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c
index adbb3e30850..05623347366 100644
--- a/source/blender/editors/space_clip/tracking_ops_track.c
+++ b/source/blender/editors/space_clip/tracking_ops_track.c
@@ -23,21 +23,21 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
-#include "BKE_main.h"
#include "BKE_context.h"
-#include "BKE_movieclip.h"
-#include "BKE_tracking.h"
#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_movieclip.h"
#include "BKE_report.h"
+#include "BKE_tracking.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_screen.h"
#include "ED_clip.h"
+#include "ED_screen.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -86,7 +86,7 @@ static int track_count_markers(SpaceClip *sc, MovieClip *clip, int framenr)
return tot;
}
-static void track_init_markers(SpaceClip *sc, MovieClip *clip, int framenr, int *frames_limit_r)
+static void track_init_markers(SpaceClip *sc, MovieClip *clip, int framenr, int *r_frames_limit)
{
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
int frames_limit = 0;
@@ -109,7 +109,7 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int framenr, int
}
}
}
- *frames_limit_r = frames_limit;
+ *r_frames_limit = frames_limit;
}
static bool track_markers_check_direction(int backwards, int curfra, int efra)
@@ -387,7 +387,7 @@ static int track_markers_modal(bContext *C, wmOperator *UNUSED(op), const wmEven
/* Running tracking. */
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index f6063b49005..81cc858c69f 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -26,10 +26,10 @@
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
+#include "BLI_lasso_2d.h"
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_lasso_2d.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_tracking.h"
@@ -49,10 +49,10 @@
#include "DEG_depsgraph.h"
-#include "tracking_ops_intern.h" /* own include */
#include "clip_intern.h" /* own include */
+#include "tracking_ops_intern.h" /* own include */
-static float dist_to_crns(float co[2], float pos[2], float crns[4][2]);
+static float dist_to_crns(const float co[2], const float pos[2], const float crns[4][2]);
/********************** mouse select operator *********************/
@@ -70,8 +70,12 @@ static int mouse_on_side(
return (co[0] >= x1 - epsx && co[0] <= x2 + epsx) && (co[1] >= y1 - epsy && co[1] <= y2 + epsy);
}
-static int mouse_on_rect(
- const float co[2], float pos[2], float min[2], float max[2], float epsx, float epsy)
+static int mouse_on_rect(const float co[2],
+ const float pos[2],
+ const float min[2],
+ const float max[2],
+ float epsx,
+ float epsy)
{
return mouse_on_side(
co, pos[0] + min[0], pos[1] + min[1], pos[0] + max[0], pos[1] + min[1], epsx, epsy) ||
@@ -83,14 +87,15 @@ static int mouse_on_rect(
co, pos[0] + max[0], pos[1] + min[1], pos[0] + max[0], pos[1] + max[1], epsx, epsy);
}
-static int mouse_on_crns(float co[2], float pos[2], float crns[4][2], float epsx, float epsy)
+static int mouse_on_crns(
+ const float co[2], const float pos[2], const float crns[4][2], float epsx, float epsy)
{
float dist = dist_to_crns(co, pos, crns);
return dist < max_ff(epsx, epsy);
}
-static int track_mouse_area(const bContext *C, float co[2], MovieTrackingTrack *track)
+static int track_mouse_area(const bContext *C, const float co[2], MovieTrackingTrack *track)
{
SpaceClip *sc = CTX_wm_space_clip(C);
int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -142,7 +147,10 @@ static int track_mouse_area(const bContext *C, float co[2], MovieTrackingTrack *
return TRACK_AREA_NONE;
}
-static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
+static float dist_to_rect(const float co[2],
+ const float pos[2],
+ const float min[2],
+ const float max[2])
{
float d1, d2, d3, d4;
float p[2] = {co[0] - pos[0], co[1] - pos[1]};
@@ -158,7 +166,7 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
}
/* Distance to quad defined by it's corners, corners are relative to pos */
-static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
+static float dist_to_crns(const float co[2], const float pos[2], const float crns[4][2])
{
float d1, d2, d3, d4;
float p[2] = {co[0] - pos[0], co[1] - pos[1]};
@@ -174,7 +182,7 @@ static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
}
/* Same as above, but all the coordinates are absolute */
-static float dist_to_crns_abs(float co[2], float corners[4][2])
+static float dist_to_crns_abs(const float co[2], const float corners[4][2])
{
float d1, d2, d3, d4;
const float *v1 = corners[0], *v2 = corners[1];
@@ -190,8 +198,8 @@ static float dist_to_crns_abs(float co[2], float corners[4][2])
static MovieTrackingTrack *find_nearest_track(SpaceClip *sc,
ListBase *tracksbase,
- float co[2],
- float *distance_r)
+ const float co[2],
+ float *r_distance)
{
MovieTrackingTrack *track = NULL, *cur;
float mindist = 0.0f;
@@ -231,15 +239,15 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc,
cur = cur->next;
}
- *distance_r = mindist;
+ *r_distance = mindist;
return track;
}
static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc,
ListBase *plane_tracks_base,
- float co[2],
- float *distance_r)
+ const float co[2],
+ float *r_distance)
{
MovieTrackingPlaneTrack *plane_track = NULL, *current_plane_track;
float min_distance = 0.0f;
@@ -259,7 +267,7 @@ static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc,
}
}
- *distance_r = min_distance;
+ *r_distance = min_distance;
return plane_track;
}
@@ -281,7 +289,7 @@ void ed_tracking_deselect_all_plane_tracks(ListBase *plane_tracks_base)
}
}
-static int mouse_select(bContext *C, float co[2], const bool extend, const bool deselect_all)
+static int mouse_select(bContext *C, const float co[2], const bool extend, const bool deselect_all)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -379,7 +387,8 @@ static int mouse_select(bContext *C, float co[2], const bool extend, const bool
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
- return OPERATOR_FINISHED;
+ /* Pass-through + finished to allow tweak to transform. */
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
static bool select_poll(bContext *C)
@@ -407,7 +416,7 @@ static int select_exec(bContext *C, wmOperator *op)
static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float co[2];
const bool extend = RNA_boolean_get(op->ptr, "extend");
@@ -427,7 +436,7 @@ static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
}
- ED_clip_mouse_pos(sc, ar, event->mval, co);
+ ED_clip_mouse_pos(sc, region, event->mval, co);
RNA_float_set_array(op->ptr, "location", co);
return select_exec(C, op);
@@ -486,7 +495,7 @@ bool ED_clip_can_select(bContext *C)
static int box_select_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@@ -502,8 +511,8 @@ static int box_select_exec(bContext *C, wmOperator *op)
/* get rectangle from operator */
WM_operator_properties_border_to_rcti(op, &rect);
- ED_clip_point_stable_pos(sc, ar, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
- ED_clip_point_stable_pos(sc, ar, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
+ ED_clip_point_stable_pos(sc, region, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
+ ED_clip_point_stable_pos(sc, region, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
const bool select = (sel_op != SEL_OP_SUB);
@@ -589,12 +598,12 @@ void CLIP_OT_select_box(wmOperatorType *ot)
/********************** lasso select operator *********************/
static int do_lasso_select_marker(bContext *C,
- const int mcords[][2],
- const short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
bool select)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@@ -607,7 +616,7 @@ static int do_lasso_select_marker(bContext *C,
int framenr = ED_space_clip_get_clip_frame_number(sc);
/* get rectangle from operator */
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
/* do actual selection */
track = tracksbase->first;
@@ -619,10 +628,11 @@ static int do_lasso_select_marker(bContext *C,
float screen_co[2];
/* marker in screen coords */
- ED_clip_point_stable_pos__reverse(sc, ar, marker->pos, screen_co);
+ ED_clip_point_stable_pos__reverse(sc, region, marker->pos, screen_co);
if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
- BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) {
+ BLI_lasso_is_point_inside(
+ mcoords, mcoords_len, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) {
if (select) {
BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
}
@@ -647,10 +657,11 @@ static int do_lasso_select_marker(bContext *C,
float screen_co[2];
/* marker in screen coords */
- ED_clip_point_stable_pos__reverse(sc, ar, plane_marker->corners[i], screen_co);
+ ED_clip_point_stable_pos__reverse(sc, region, plane_marker->corners[i], screen_co);
if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
- BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) {
+ BLI_lasso_is_point_inside(
+ mcoords, mcoords_len, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) {
if (select) {
plane_track->flag |= SELECT;
}
@@ -676,10 +687,10 @@ static int do_lasso_select_marker(bContext *C,
static int clip_lasso_select_exec(bContext *C, wmOperator *op)
{
- int mcords_tot;
- const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+ int mcoords_len;
+ const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len);
- if (mcords) {
+ if (mcoords) {
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
const bool select = (sel_op != SEL_OP_SUB);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
@@ -687,9 +698,9 @@ static int clip_lasso_select_exec(bContext *C, wmOperator *op)
ED_clip_select_all(sc, SEL_DESELECT, NULL);
}
- do_lasso_select_marker(C, mcords, mcords_tot, select);
+ do_lasso_select_marker(C, mcoords, mcoords_len, select);
- MEM_freeN((void *)mcords);
+ MEM_freeN((void *)mcoords);
return OPERATOR_FINISHED;
}
@@ -739,7 +750,7 @@ static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], f
static int circle_select_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@@ -767,12 +778,12 @@ static int circle_select_exec(bContext *C, wmOperator *op)
/* compute ellipse and position in unified coordinates */
ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+ ED_space_clip_get_zoom(sc, region, &zoomx, &zoomy);
ellipse[0] = width * zoomx / radius;
ellipse[1] = height * zoomy / radius;
- ED_clip_point_stable_pos(sc, ar, x, y, &offset[0], &offset[1]);
+ ED_clip_point_stable_pos(sc, region, x, y, &offset[0], &offset[1]);
/* do selection */
track = tracksbase->first;
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index c9dde11cbeb..6c56e8dfb79 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -18,17 +18,13 @@
* \ingroup spconsole
*/
-#include <math.h>
-#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
-#include <limits.h>
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "MEM_guardedalloc.h"
@@ -42,14 +38,14 @@
#include "../space_info/textview.h"
-static int console_line_data(struct TextViewContext *tvc,
- unsigned char fg[4],
- unsigned char UNUSED(bg[4]),
- int *UNUSED(icon),
- unsigned char UNUSED(icon_fg[4]),
- unsigned char UNUSED(icon_bg[4]))
+static enum eTextViewContext_LineFlag console_line_data(TextViewContext *tvc,
+ uchar fg[4],
+ uchar UNUSED(bg[4]),
+ int *UNUSED(icon),
+ uchar UNUSED(icon_fg[4]),
+ uchar UNUSED(icon_bg[4]))
{
- ConsoleLine *cl_iter = (ConsoleLine *)tvc->iter;
+ const ConsoleLine *cl_iter = tvc->iter;
int fg_id = TH_TEXT;
switch (cl_iter->type) {
@@ -71,7 +67,7 @@ static int console_line_data(struct TextViewContext *tvc,
return TVC_LINE_FG;
}
-void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_dummy)
+void console_scrollback_prompt_begin(SpaceConsole *sc, ConsoleLine *cl_dummy)
{
/* fake the edit line being in the scroll buffer */
ConsoleLine *cl = sc->history.last;
@@ -85,7 +81,7 @@ void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_du
memcpy(cl_dummy->line + prompt_len, cl->line, cl->len + 1);
BLI_addtail(&sc->scrollback, cl_dummy);
}
-void console_scrollback_prompt_end(struct SpaceConsole *sc, ConsoleLine *cl_dummy)
+void console_scrollback_prompt_end(SpaceConsole *sc, ConsoleLine *cl_dummy)
{
MEM_freeN(cl_dummy->line);
BLI_remlink(&sc->scrollback, cl_dummy);
@@ -116,14 +112,13 @@ static int console_textview_step(TextViewContext *tvc)
return ((tvc->iter = (void *)((Link *)tvc->iter)->prev) != NULL);
}
-static int console_textview_line_get(struct TextViewContext *tvc, const char **line, int *len)
+static void console_textview_line_get(TextViewContext *tvc, const char **r_line, int *r_len)
{
- ConsoleLine *cl = (ConsoleLine *)tvc->iter;
- *line = cl->line;
- *len = cl->len;
+ const ConsoleLine *cl = tvc->iter;
+ *r_line = cl->line;
+ *r_len = cl->len;
// printf("'%s' %d\n", *line, cl->len);
BLI_assert(cl->line[cl->len] == '\0' && (cl->len == 0 || cl->line[cl->len - 1] != '\0'));
- return 1;
}
static void console_cursor_wrap_offset(
@@ -148,53 +143,65 @@ static void console_cursor_wrap_offset(
return;
}
-static void console_textview_draw_cursor(struct TextViewContext *tvc)
+static void console_textview_draw_cursor(TextViewContext *tvc,
+ int cwidth,
+ int columns,
+ int descender)
{
- const SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
- const ConsoleLine *cl = (ConsoleLine *)sc->history.last;
- int offl = 0, offc = 0;
- int xy[2] = {tvc->draw_rect.xmin, tvc->draw_rect.ymin};
int pen[2];
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- xy[1] += tvc->lheight * 0.35f;
+ {
+ const SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
+ const ConsoleLine *cl = (ConsoleLine *)sc->history.last;
+ int offl = 0, offc = 0;
- console_cursor_wrap_offset(sc->prompt, tvc->columns, &offl, &offc, NULL);
- console_cursor_wrap_offset(cl->line, tvc->columns, &offl, &offc, cl->line + cl->cursor);
- pen[0] = tvc->cwidth * (offc + tvc->margin_left_chars);
- pen[1] = -2 - tvc->lheight * offl;
+ console_cursor_wrap_offset(sc->prompt, columns, &offl, &offc, NULL);
+ console_cursor_wrap_offset(cl->line, columns, &offl, &offc, cl->line + cl->cursor);
+ pen[0] = cwidth * offc;
+ pen[1] = -2 - (tvc->lheight + descender) * offl;
- console_cursor_wrap_offset(cl->line + cl->cursor, tvc->columns, &offl, &offc, NULL);
- pen[1] += tvc->lheight * offl;
+ console_cursor_wrap_offset(cl->line + cl->cursor, columns, &offl, &offc, NULL);
+ pen[1] += (tvc->lheight + descender) * offl;
+
+ pen[0] += tvc->draw_rect.xmin;
+ pen[1] += tvc->draw_rect.ymin;
+ }
/* cursor */
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_CONSOLE_CURSOR);
- immRectf(pos,
- (xy[0] + pen[0]) - U.pixelsize,
- (xy[1] + pen[1]),
- (xy[0] + pen[0]) + U.pixelsize,
- (xy[1] + pen[1] + tvc->lheight));
+ immRectf(
+ pos, pen[0] - U.pixelsize, pen[1], pen[0] + U.pixelsize, pen[1] + tvc->lheight + descender);
immUnbindProgram();
}
-static void console_textview_const_colors(TextViewContext *UNUSED(tvc), unsigned char bg_sel[4])
+static void console_textview_const_colors(TextViewContext *UNUSED(tvc), uchar bg_sel[4])
{
UI_GetThemeColor4ubv(TH_CONSOLE_SELECT, bg_sel);
}
-static void console_textview_draw_rect_calc(const ARegion *ar, rcti *draw_rect)
+static void console_textview_draw_rect_calc(const ARegion *region,
+ rcti *r_draw_rect,
+ rcti *r_draw_rect_outer)
{
- draw_rect->xmin = 0;
- draw_rect->xmax = ar->winx;
- draw_rect->ymin = 0;
- draw_rect->ymax = ar->winy;
+ const int margin = 4 * UI_DPI_FAC;
+ r_draw_rect->xmin = margin;
+ r_draw_rect->xmax = region->winx - V2D_SCROLL_WIDTH;
+ r_draw_rect->ymin = margin;
+ /* No margin at the top (allow text to scroll off the window). */
+ r_draw_rect->ymax = region->winy;
+
+ r_draw_rect_outer->xmin = 0;
+ r_draw_rect_outer->xmax = region->winx;
+ r_draw_rect_outer->ymin = 0;
+ r_draw_rect_outer->ymax = region->winy;
}
-static int console_textview_main__internal(struct SpaceConsole *sc,
- const ARegion *ar,
+static int console_textview_main__internal(SpaceConsole *sc,
+ const ARegion *region,
const bool do_draw,
const int mval[2],
void **r_mval_pick_item,
@@ -203,7 +210,7 @@ static int console_textview_main__internal(struct SpaceConsole *sc,
ConsoleLine cl_dummy = {NULL};
int ret = 0;
- const View2D *v2d = &ar->v2d;
+ const View2D *v2d = &region->v2d;
TextViewContext tvc = {0};
@@ -223,12 +230,10 @@ static int console_textview_main__internal(struct SpaceConsole *sc,
tvc.sel_start = sc->sel_start;
tvc.sel_end = sc->sel_end;
tvc.lheight = sc->lheight * 1.2f * UI_DPI_FAC;
- tvc.margin_left_chars = 1;
- tvc.margin_right_chars = 2;
tvc.scroll_ymin = v2d->cur.ymin;
tvc.scroll_ymax = v2d->cur.ymax;
- console_textview_draw_rect_calc(ar, &tvc.draw_rect);
+ console_textview_draw_rect_calc(region, &tvc.draw_rect, &tvc.draw_rect_outer);
console_scrollback_prompt_begin(sc, &cl_dummy);
ret = textview_draw(&tvc, do_draw, mval, r_mval_pick_item, r_mval_pick_offset);
@@ -237,26 +242,23 @@ static int console_textview_main__internal(struct SpaceConsole *sc,
return ret;
}
-void console_textview_main(struct SpaceConsole *sc, const ARegion *ar)
+void console_textview_main(SpaceConsole *sc, const ARegion *region)
{
const int mval[2] = {INT_MAX, INT_MAX};
- console_textview_main__internal(sc, ar, true, mval, NULL, NULL);
+ console_textview_main__internal(sc, region, true, mval, NULL, NULL);
}
-int console_textview_height(struct SpaceConsole *sc, const ARegion *ar)
+int console_textview_height(SpaceConsole *sc, const ARegion *region)
{
const int mval[2] = {INT_MAX, INT_MAX};
- return console_textview_main__internal(sc, ar, false, mval, NULL, NULL);
+ return console_textview_main__internal(sc, region, false, mval, NULL, NULL);
}
-int console_char_pick(struct SpaceConsole *sc, const ARegion *ar, const int mval[2])
+int console_char_pick(SpaceConsole *sc, const ARegion *region, const int mval[2])
{
int r_mval_pick_offset = 0;
void *mval_pick_item = NULL;
- rcti draw_rect;
- console_textview_draw_rect_calc(ar, &draw_rect);
-
- console_textview_main__internal(sc, ar, false, mval, &mval_pick_item, &r_mval_pick_offset);
+ console_textview_main__internal(sc, region, false, mval, &mval_pick_item, &r_mval_pick_offset);
return r_mval_pick_offset;
}
diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h
index def7fbc193b..d051e351f3e 100644
--- a/source/blender/editors/space_console/console_intern.h
+++ b/source/blender/editors/space_console/console_intern.h
@@ -28,10 +28,10 @@ struct bContext;
struct wmOperatorType;
/* console_draw.c */
-void console_textview_main(struct SpaceConsole *sc, const struct ARegion *ar);
+void console_textview_main(struct SpaceConsole *sc, const struct ARegion *region);
/* needed to calculate the scrollbar */
-int console_textview_height(struct SpaceConsole *sc, const struct ARegion *ar);
-int console_char_pick(struct SpaceConsole *sc, const struct ARegion *ar, const int mval[2]);
+int console_textview_height(struct SpaceConsole *sc, const struct ARegion *region);
+int console_char_pick(struct SpaceConsole *sc, const struct ARegion *region, const int mval[2]);
void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_dummy);
void console_scrollback_prompt_end(struct SpaceConsole *sc, ConsoleLine *cl_dummy);
@@ -44,7 +44,7 @@ ConsoleLine *console_scrollback_add_str(struct SpaceConsole *sc, char *str, bool
ConsoleLine *console_history_verify(const struct bContext *C);
-void console_textview_update_rect(SpaceConsole *sc, ARegion *ar);
+void console_textview_update_rect(SpaceConsole *sc, ARegion *region);
void CONSOLE_OT_move(struct wmOperatorType *ot);
void CONSOLE_OT_delete(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index 278981d2091..981e056fa63 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -18,30 +18,30 @@
* \ingroup spconsole
*/
+#include <ctype.h> /* ispunct */
#include <stdlib.h>
#include <string.h>
-#include <ctype.h> /* ispunct */
#include <sys/stat.h>
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
-#include "BLI_utildefines.h"
+#include "BLI_dynstr.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLI_string_cursor_utf8.h"
#include "BLI_string_utf8.h"
-#include "BLI_string.h"
-#include "BLI_dynstr.h"
-#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_view2d.h"
#include "ED_screen.h"
+#include "UI_view2d.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -49,18 +49,18 @@
#include "console_intern.h"
/* so when we type - the view scrolls to the bottom */
-static void console_scroll_bottom(ARegion *ar)
+static void console_scroll_bottom(ARegion *region)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
v2d->cur.ymin = 0.0;
v2d->cur.ymax = (float)v2d->winy;
}
-void console_textview_update_rect(SpaceConsole *sc, ARegion *ar)
+void console_textview_update_rect(SpaceConsole *sc, ARegion *region)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
- UI_view2d_totRect_set(v2d, ar->winx - 1, console_textview_height(sc, ar));
+ UI_view2d_totRect_set(v2d, region->winx - 1, console_textview_height(sc, region));
}
static void console_select_offset(SpaceConsole *sc, const int offset)
@@ -233,11 +233,7 @@ static void console_line_verify_length(ConsoleLine *ci, int len)
#else
int new_len = (len + 1) * 2;
#endif
- char *new_line = MEM_callocN(new_len, "console line");
- memcpy(new_line, ci->line, ci->len);
- MEM_freeN(ci->line);
-
- ci->line = new_line;
+ ci->line = MEM_recallocN_id(ci->line, new_len, "console line");
ci->len_alloc = new_len;
}
}
@@ -357,11 +353,11 @@ static int console_move_exec(bContext *C, wmOperator *op)
}
if (done) {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
- ED_area_tag_redraw(sa);
- console_scroll_bottom(ar);
+ ED_area_tag_redraw(area);
+ console_scroll_bottom(region);
}
return OPERATOR_FINISHED;
@@ -387,7 +383,7 @@ void CONSOLE_OT_move(wmOperatorType *ot)
static int console_insert_exec(bContext *C, wmOperator *op)
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ConsoleLine *ci = console_history_verify(C);
char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
int len;
@@ -411,10 +407,10 @@ static int console_insert_exec(bContext *C, wmOperator *op)
console_select_offset(sc, len);
}
- console_textview_update_rect(sc, ar);
+ console_textview_update_rect(sc, region);
ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(region);
return OPERATOR_FINISHED;
}
@@ -510,7 +506,7 @@ void CONSOLE_OT_indent_or_autocomplete(wmOperatorType *ot)
static int console_indent_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ConsoleLine *ci = console_history_verify(C);
int spaces;
int len;
@@ -532,10 +528,10 @@ static int console_indent_exec(bContext *C, wmOperator *UNUSED(op))
console_line_cursor_set(ci, ci->cursor + len);
console_select_offset(sc, len);
- console_textview_update_rect(sc, ar);
+ console_textview_update_rect(sc, region);
ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(region);
return OPERATOR_FINISHED;
}
@@ -557,7 +553,7 @@ void CONSOLE_OT_indent(wmOperatorType *ot)
static int console_unindent_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ConsoleLine *ci = console_history_verify(C);
int spaces;
int len;
@@ -586,10 +582,10 @@ static int console_unindent_exec(bContext *C, wmOperator *UNUSED(op))
console_line_cursor_set(ci, ci->cursor - len);
console_select_offset(sc, -len);
- console_textview_update_rect(sc, ar);
+ console_textview_update_rect(sc, region);
ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(region);
return OPERATOR_FINISHED;
}
@@ -617,7 +613,7 @@ static const EnumPropertyItem console_delete_type_items[] = {
static int console_delete_exec(bContext *C, wmOperator *op)
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ConsoleLine *ci = console_history_verify(C);
int pos;
int stride;
@@ -682,10 +678,10 @@ static int console_delete_exec(bContext *C, wmOperator *op)
console_select_offset(sc, -stride);
}
- console_textview_update_rect(sc, ar);
+ console_textview_update_rect(sc, region);
ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(region);
return OPERATOR_FINISHED;
}
@@ -713,7 +709,7 @@ void CONSOLE_OT_delete(wmOperatorType *ot)
static int console_clear_line_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ConsoleLine *ci = console_history_verify(C);
if (ci->len == 0) {
@@ -724,11 +720,11 @@ static int console_clear_line_exec(bContext *C, wmOperator *UNUSED(op))
console_history_add(sc, NULL);
console_select_offset(sc, -ci->len);
- console_textview_update_rect(sc, ar);
+ console_textview_update_rect(sc, region);
ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(region);
return OPERATOR_FINISHED;
}
@@ -749,7 +745,7 @@ void CONSOLE_OT_clear_line(wmOperatorType *ot)
static int console_clear_exec(bContext *C, wmOperator *op)
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
const bool scrollback = RNA_boolean_get(op->ptr, "scrollback");
const bool history = RNA_boolean_get(op->ptr, "history");
@@ -769,7 +765,7 @@ static int console_clear_exec(bContext *C, wmOperator *op)
console_history_verify(C);
}
- console_textview_update_rect(sc, ar);
+ console_textview_update_rect(sc, region);
ED_area_tag_redraw(CTX_wm_area(C));
return OPERATOR_FINISHED;
@@ -795,7 +791,7 @@ void CONSOLE_OT_clear(wmOperatorType *ot)
static int console_history_cycle_exec(bContext *C, wmOperator *op)
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* TODO - stupid, just prevents crashes when no command line */
ConsoleLine *ci = console_history_verify(C);
@@ -836,10 +832,10 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op)
console_select_offset(sc, ci->len - prev_len);
/* could be wrapped so update scroll rect */
- console_textview_update_rect(sc, ar);
+ console_textview_update_rect(sc, region);
ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(region);
return OPERATOR_FINISHED;
}
@@ -863,8 +859,8 @@ void CONSOLE_OT_history_cycle(wmOperatorType *ot)
static int console_history_append_exec(bContext *C, wmOperator *op)
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
- ScrArea *sa = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
ConsoleLine *ci = console_history_verify(C);
/* own this text in the new line, don't free */
char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
@@ -889,12 +885,12 @@ static int console_history_append_exec(bContext *C, wmOperator *op)
console_select_offset(sc, ci->len - prev_len);
console_line_cursor_set(ci, cursor);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
/* when calling render modally this can be NULL when calling:
* bpy.ops.render.render('INVOKE_DEFAULT') */
- if (ar) {
- console_scroll_bottom(ar);
+ if (region) {
+ console_scroll_bottom(region);
}
return OPERATOR_FINISHED;
@@ -926,7 +922,7 @@ void CONSOLE_OT_history_append(wmOperatorType *ot)
static int console_scrollback_append_exec(bContext *C, wmOperator *op)
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ConsoleLine *ci;
/* own this text in the new line, don't free */
@@ -940,10 +936,10 @@ static int console_scrollback_append_exec(bContext *C, wmOperator *op)
console_scrollback_limit(sc);
- /* 'ar' can be null depending on the operator that runs
+ /* 'region' can be null depending on the operator that runs
* rendering with invoke default for eg causes this */
- if (ar) {
- console_textview_update_rect(sc, ar);
+ if (region) {
+ console_textview_update_rect(sc, region);
}
ED_area_tag_redraw(CTX_wm_area(C));
@@ -1059,7 +1055,7 @@ void CONSOLE_OT_copy(wmOperatorType *ot)
static int console_paste_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ConsoleLine *ci = console_history_verify(C);
int buf_len;
@@ -1089,10 +1085,10 @@ static int console_paste_exec(bContext *C, wmOperator *UNUSED(op))
MEM_freeN(buf_str);
- console_textview_update_rect(sc, ar);
+ console_textview_update_rect(sc, region);
ED_area_tag_redraw(CTX_wm_area(C));
- console_scroll_bottom(ar);
+ console_scroll_bottom(region);
return OPERATOR_FINISHED;
}
@@ -1118,10 +1114,10 @@ typedef struct SetConsoleCursor {
// TODO, cursor placement without selection
static void console_cursor_set_to_pos(
- SpaceConsole *sc, ARegion *ar, SetConsoleCursor *scu, const int mval[2], int UNUSED(sel))
+ SpaceConsole *sc, ARegion *region, SetConsoleCursor *scu, const int mval[2], int UNUSED(sel))
{
int pos;
- pos = console_char_pick(sc, ar, mval);
+ pos = console_char_pick(sc, region, mval);
if (scu->sel_init == INT_MAX) {
scu->sel_init = pos;
@@ -1145,7 +1141,7 @@ static void console_cursor_set_to_pos(
static void console_modal_select_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SetConsoleCursor *scu = op->customdata;
int mval[2];
int sel_prev[2];
@@ -1156,7 +1152,7 @@ static void console_modal_select_apply(bContext *C, wmOperator *op, const wmEven
sel_prev[0] = sc->sel_start;
sel_prev[1] = sc->sel_end;
- console_cursor_set_to_pos(sc, ar, scu, mval, true);
+ console_cursor_set_to_pos(sc, region, scu, mval, true);
/* only redraw if the selection changed */
if (sel_prev[0] != sc->sel_start || sel_prev[1] != sc->sel_end) {
@@ -1183,7 +1179,7 @@ static void console_cursor_set_exit(bContext *UNUSED(C), wmOperator *op)
static int console_modal_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceConsole *sc = CTX_wm_space_console(C);
- // ARegion *ar = CTX_wm_region(C);
+ // ARegion *region = CTX_wm_region(C);
SetConsoleCursor *scu;
op->customdata = MEM_callocN(sizeof(SetConsoleCursor), "SetConsoleCursor");
@@ -1242,14 +1238,14 @@ void CONSOLE_OT_select_set(wmOperatorType *ot)
static int console_selectword_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
SpaceConsole *sc = CTX_wm_space_console(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ConsoleLine cl_dummy = {NULL};
ConsoleLine *cl;
int ret = OPERATOR_CANCELLED;
int pos, offset, n;
- pos = console_char_pick(sc, ar, event->mval);
+ pos = console_char_pick(sc, region, event->mval);
console_scrollback_prompt_begin(sc, &cl_dummy);
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index 207f508d4ee..d8c097cad37 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -18,20 +18,20 @@
* \ingroup spconsole
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BKE_global.h"
#include "BKE_context.h"
+#include "BKE_global.h"
#include "BKE_screen.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "RNA_access.h"
@@ -41,14 +41,14 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "console_intern.h" // own include
#include "GPU_framebuffer.h"
+#include "console_intern.h" // own include
/* ******************** default callbacks for console space ***************** */
static SpaceLink *console_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceConsole *sconsole;
sconsole = MEM_callocN(sizeof(SpaceConsole), "initconsole");
@@ -57,28 +57,28 @@ static SpaceLink *console_new(const ScrArea *UNUSED(area), const Scene *UNUSED(s
sconsole->lheight = 14;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for console");
+ region = MEM_callocN(sizeof(ARegion), "header for console");
- BLI_addtail(&sconsole->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&sconsole->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for text");
+ region = MEM_callocN(sizeof(ARegion), "main region for text");
- BLI_addtail(&sconsole->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sconsole->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
/* keep in sync with info */
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
- ar->v2d.align |= V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y; /* align bottom left */
- ar->v2d.keepofs |= V2D_LOCKOFS_X;
- ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- ar->v2d.keeptot = V2D_KEEPTOT_BOUNDS;
- ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
+ region->v2d.scroll |= (V2D_SCROLL_RIGHT);
+ region->v2d.align |= V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y; /* align bottom left */
+ region->v2d.keepofs |= V2D_LOCKOFS_X;
+ region->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ region->v2d.keeptot = V2D_KEEPTOT_BOUNDS;
+ region->v2d.minzoom = region->v2d.maxzoom = 1.0f;
/* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- // ar->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM);
+ // region->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM);
return (SpaceLink *)sconsole;
}
@@ -98,7 +98,7 @@ static void console_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void console_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void console_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -116,41 +116,41 @@ static SpaceLink *console_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void console_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void console_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
ListBase *lb;
- const float prev_y_min = ar->v2d.cur.ymin; /* so re-sizing keeps the cursor visible */
+ const float prev_y_min = region->v2d.cur.ymin; /* so re-sizing keeps the cursor visible */
/* force it on init, for old files, until it becomes config */
- ar->v2d.scroll = (V2D_SCROLL_RIGHT);
+ region->v2d.scroll = (V2D_SCROLL_RIGHT);
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
/* always keep the bottom part of the view aligned, less annoying */
- if (prev_y_min != ar->v2d.cur.ymin) {
- const float cur_y_range = BLI_rctf_size_y(&ar->v2d.cur);
- ar->v2d.cur.ymin = prev_y_min;
- ar->v2d.cur.ymax = prev_y_min + cur_y_range;
+ if (prev_y_min != region->v2d.cur.ymin) {
+ const float cur_y_range = BLI_rctf_size_y(&region->v2d.cur);
+ region->v2d.cur.ymin = prev_y_min;
+ region->v2d.cur.ymax = prev_y_min + cur_y_range;
}
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Console", SPACE_CONSOLE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
/* add drop boxes */
lb = WM_dropboxmap_find("Console", SPACE_CONSOLE, RGN_TYPE_WINDOW);
- WM_event_add_dropbox_handler(&ar->handlers, lb);
+ WM_event_add_dropbox_handler(&region->handlers, lb);
}
/* same as 'text_cursor' */
-static void console_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *ar)
+static void console_cursor(wmWindow *win, ScrArea *UNUSED(area), ARegion *region)
{
int wmcursor = WM_CURSOR_TEXT_EDIT;
const wmEvent *event = win->eventstate;
- if (UI_view2d_mouse_in_scrollers(ar, &ar->v2d, event->x, event->y)) {
+ if (UI_view2d_mouse_in_scrollers(region, &region->v2d, event->x, event->y)) {
wmcursor = WM_CURSOR_DEFAULT;
}
@@ -203,11 +203,11 @@ static void console_dropboxes(void)
/* ************* end drop *********** */
-static void console_main_region_draw(const bContext *C, ARegion *ar)
+static void console_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceConsole *sc = CTX_wm_space_console(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
if (BLI_listbase_is_empty(&sc->scrollback)) {
@@ -224,7 +224,7 @@ static void console_main_region_draw(const bContext *C, ARegion *ar)
/* data... */
console_history_verify(C); /* make sure we have some command line */
- console_textview_main(sc, ar);
+ console_textview_main(sc, region);
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -267,35 +267,38 @@ static void console_keymap(struct wmKeyConfig *keyconf)
/****************** header region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void console_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void console_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void console_header_region_draw(const bContext *C, ARegion *ar)
+static void console_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
-static void console_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
+static void console_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *area,
+ ARegion *region,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
- // SpaceInfo *sinfo = sa->spacedata.first;
+ // SpaceInfo *sinfo = area->spacedata.first;
/* context changes */
switch (wmn->category) {
case NC_SPACE: {
if (wmn->data == ND_SPACE_CONSOLE) {
if (wmn->action == NA_EDITED) {
- if ((wmn->reference && sa) && (wmn->reference == sa->spacedata.first)) {
+ if ((wmn->reference && area) && (wmn->reference == area->spacedata.first)) {
/* we've modified the geometry (font size), re-calculate rect */
- console_textview_update_rect(wmn->reference, ar);
- ED_region_tag_redraw(ar);
+ console_textview_update_rect(wmn->reference, region);
+ ED_region_tag_redraw(region);
}
}
else {
/* generic redraw request */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
break;
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 0aec6d5e6a0..226e7ae6b22 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -21,14 +21,14 @@
* \ingroup spfile
*/
+#include <errno.h>
#include <math.h>
#include <string.h>
-#include <errno.h>
#include "BLI_blenlib.h"
#include "BLI_fileops_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#ifdef WIN32
# include "BLI_winstuff.h"
@@ -133,8 +133,15 @@ static void draw_tile(int sx, int sy, int width, int height, int colorid, int sh
true, (float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f, color);
}
-static void file_draw_icon(
- uiBlock *block, const char *path, int sx, int sy, int icon, int width, int height, bool drag)
+static void file_draw_icon(uiBlock *block,
+ const char *path,
+ int sx,
+ int sy,
+ int icon,
+ int width,
+ int height,
+ bool drag,
+ bool dimmed)
{
uiBut *but;
int x, y;
@@ -142,8 +149,11 @@ static void file_draw_icon(
x = sx;
y = sy - height;
+ /* For uiDefIconBut(), if a1==1.0 then a2 is alpha 0.0 - 1.0 */
+ const float a1 = dimmed ? 1.0f : 0.0f;
+ const float a2 = dimmed ? 0.3f : 0.0f;
but = uiDefIconBut(
- block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, 0.0f, 0.0f, NULL);
+ block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, a1, a2, NULL);
UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
if (drag) {
@@ -160,7 +170,6 @@ static void file_draw_string(int sx,
eFontStyle_Align align,
const uchar col[4])
{
- uiStyle *style;
uiFontStyle fs;
rcti rect;
char fname[FILE_MAXFILE];
@@ -169,7 +178,7 @@ static void file_draw_string(int sx,
return;
}
- style = UI_style_get();
+ const uiStyle *style = UI_style_get();
fs = style->widgetlabel;
BLI_strncpy(fname, string, FILE_MAXFILE);
@@ -191,12 +200,12 @@ static void file_draw_string(int sx,
});
}
-void file_calc_previews(const bContext *C, ARegion *ar)
+void file_calc_previews(const bContext *C, ARegion *region)
{
SpaceFile *sfile = CTX_wm_space_file(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
- ED_fileselect_init_layout(sfile, ar);
+ ED_fileselect_init_layout(sfile, region);
UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
}
@@ -210,7 +219,8 @@ static void file_draw_preview(uiBlock *block,
FileLayout *layout,
const bool is_icon,
const int typeflags,
- const bool drag)
+ const bool drag,
+ const bool dimmed)
{
uiBut *but;
float fx, fy;
@@ -273,6 +283,10 @@ static void file_draw_preview(uiBlock *block,
UI_GetThemeColor4fv(TH_TEXT, col);
}
+ if (dimmed) {
+ col[3] *= 0.3f;
+ }
+
if (!is_icon && typeflags & FILE_TYPE_BLENDERLIB) {
/* Datablock preview images use premultiplied alpha. */
GPU_blend_set_func_separate(
@@ -298,7 +312,7 @@ static void file_draw_preview(uiBlock *block,
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- if (icon && (icon != ICON_FILE_FONT)) {
+ if (icon && !(typeflags & FILE_TYPE_FTFONT)) {
/* size of center icon is scaled to fit container and UI scale */
float icon_x, icon_y;
@@ -362,20 +376,17 @@ static void file_draw_preview(uiBlock *block,
static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
{
- Main *bmain = CTX_data_main(C);
char newname[FILE_MAX + 12];
char orgname[FILE_MAX + 12];
char filename[FILE_MAX + 12];
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- const char *blendfile_path = BKE_main_blendfile_path(bmain);
- BLI_make_file_string(blendfile_path, orgname, sfile->params->dir, oldname);
+ BLI_join_dirfile(orgname, sizeof(orgname), sfile->params->dir, oldname);
BLI_strncpy(filename, sfile->params->renamefile, sizeof(filename));
BLI_filename_make_safe(filename);
- BLI_make_file_string(blendfile_path, newname, sfile->params->dir, filename);
+ BLI_join_dirfile(newname, sizeof(newname), sfile->params->dir, filename);
if (!STREQ(orgname, newname)) {
if (!BLI_exists(newname)) {
@@ -397,10 +408,10 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
}
/* to make sure we show what is on disk */
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
@@ -437,7 +448,7 @@ static void draw_dividers(FileLayout *layout, View2D *v2d)
const int step = (layout->tile_w + 2 * layout->tile_border_x);
- unsigned int vertex_len = 0;
+ uint vertex_len = 0;
int sx = (int)v2d->tot.xmin;
while (sx < v2d->cur.xmax) {
sx += step;
@@ -446,7 +457,7 @@ static void draw_dividers(FileLayout *layout, View2D *v2d)
if (vertex_len > 0) {
int v1[2], v2[2];
- unsigned char col_hi[3], col_lo[3];
+ uchar col_hi[3], col_lo[3];
UI_GetThemeColorShade3ubv(TH_BACK, 30, col_hi);
UI_GetThemeColorShade3ubv(TH_BACK, -30, col_lo);
@@ -654,17 +665,17 @@ static void draw_details_columns(const FileSelectParams *params,
}
}
-void file_draw_list(const bContext *C, ARegion *ar)
+void file_draw_list(const bContext *C, ARegion *region)
{
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
- FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
- View2D *v2d = &ar->v2d;
+ FileLayout *layout = ED_fileselect_get_layout(sfile, region);
+ View2D *v2d = &region->v2d;
struct FileList *files = sfile->files;
struct FileDirEntry *file;
const char *root = filelist_dir(files);
ImBuf *imb;
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
int numfiles;
int numfiles_layout;
int sx, sy;
@@ -674,7 +685,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
bool is_icon;
eFontStyle_Align align;
bool do_drag;
- unsigned char text_col[4];
+ uchar text_col[4];
const bool draw_columnheader = (params->display == FILE_VERTICALDISPLAY);
const float thumb_icon_aspect = MIN2(64.0f / (float)(params->thumbnail_size), 1.0f);
@@ -685,12 +696,13 @@ void file_draw_list(const bContext *C, ARegion *ar)
draw_dividers(layout, v2d);
}
- offset = ED_fileselect_layout_offset(layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax);
+ offset = ED_fileselect_layout_offset(
+ layout, (int)region->v2d.cur.xmin, (int)-region->v2d.cur.ymax);
if (offset < 0) {
offset = 0;
}
- numfiles_layout = ED_fileselect_layout_numfiles(layout, ar);
+ numfiles_layout = ED_fileselect_layout_numfiles(layout, region);
/* adjust, so the next row is already drawn when scrolling */
if (layout->flag & FILE_LAYOUT_HOR) {
@@ -741,7 +753,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
UI_GetThemeColor4ubv(TH_TEXT, text_col);
for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
- unsigned int file_selflag;
+ uint file_selflag;
char path[FILE_MAX_LIBEXTRA];
int padx = 0.1f * UI_UNIT_X;
int icon_ofs = 0;
@@ -775,6 +787,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
/* don't drag parent or refresh items */
do_drag = !(FILENAME_IS_CURRPAR(file->relpath));
+ const bool is_hidden = (file->attributes & FILE_ATTR_HIDDEN);
if (FILE_IMGDISPLAY == params->display) {
const int icon = filelist_geticon(files, i, false);
@@ -795,7 +808,8 @@ void file_draw_list(const bContext *C, ARegion *ar)
layout,
is_icon,
file->typeflag,
- do_drag);
+ do_drag,
+ is_hidden);
}
else {
file_draw_icon(block,
@@ -805,7 +819,8 @@ void file_draw_list(const bContext *C, ARegion *ar)
filelist_geticon(files, i, true),
ICON_DEFAULT_WIDTH_SCALE,
ICON_DEFAULT_HEIGHT_SCALE,
- do_drag);
+ do_drag,
+ is_hidden);
icon_ofs += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
}
@@ -833,7 +848,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
UI_but_func_rename_set(but, renamebutton_cb, file);
UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */
UI_but_flag_disable(but, UI_BUT_UNDO);
- if (false == UI_but_active_only(C, ar, block, but)) {
+ if (false == UI_but_active_only(C, region, block, but)) {
file_selflag = filelist_entry_select_set(
sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
}
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index b0ff67844d8..b7e8d35ffee 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -33,19 +33,12 @@ struct SpaceFile;
struct View2D;
/* file_draw.c */
-#define TILE_BORDER_X (UI_UNIT_X / 4)
-#define TILE_BORDER_Y (UI_UNIT_Y / 4)
-
-/* ui geometry */
-#define IMASEL_BUTTONS_HEIGHT (UI_UNIT_Y * 2)
-#define IMASEL_BUTTONS_MARGIN (UI_UNIT_Y / 6)
-
#define ATTRIBUTE_COLUMN_PADDING (0.5f * UI_UNIT_X)
#define SMALL_SIZE_CHECK(_size) ((_size) < 64) /* Related to FileSelectParams.thumbnail_size. */
-void file_calc_previews(const bContext *C, ARegion *ar);
-void file_draw_list(const bContext *C, ARegion *ar);
+void file_calc_previews(const bContext *C, ARegion *region);
+void file_draw_list(const bContext *C, ARegion *region);
void file_draw_check(bContext *C);
void file_draw_check_cb(bContext *C, void *arg1, void *arg2);
@@ -55,13 +48,6 @@ bool file_draw_check_exists(SpaceFile *sfile);
struct wmOperator;
struct wmOperatorType;
-typedef enum WalkSelectDirection {
- FILE_SELECT_WALK_UP,
- FILE_SELECT_WALK_DOWN,
- FILE_SELECT_WALK_LEFT,
- FILE_SELECT_WALK_RIGHT,
-} WalkSelectDirections;
-
void FILE_OT_highlight(struct wmOperatorType *ot);
void FILE_OT_sort_column_ui_context(struct wmOperatorType *ot);
void FILE_OT_select(struct wmOperatorType *ot);
@@ -87,19 +73,12 @@ void FILE_OT_delete(struct wmOperatorType *ot);
void FILE_OT_rename(struct wmOperatorType *ot);
void FILE_OT_smoothscroll(struct wmOperatorType *ot);
void FILE_OT_filepath_drop(struct wmOperatorType *ot);
-
-int file_exec(bContext *C, struct wmOperator *exec_op);
-int file_cancel_exec(bContext *C, struct wmOperator *unused);
-int file_parent_exec(bContext *C, struct wmOperator *unused);
-int file_previous_exec(bContext *C, struct wmOperator *unused);
-int file_next_exec(bContext *C, struct wmOperator *unused);
-int file_directory_new_exec(bContext *C, struct wmOperator *unused);
-int file_delete_exec(bContext *C, struct wmOperator *unused);
+void FILE_OT_start_filter(struct wmOperatorType *ot);
void file_directory_enter_handle(bContext *C, void *arg_unused, void *arg_but);
void file_filename_enter_handle(bContext *C, void *arg_unused, void *arg_but);
-int file_highlight_set(struct SpaceFile *sfile, struct ARegion *ar, int mx, int my);
+int file_highlight_set(struct SpaceFile *sfile, struct ARegion *region, int mx, int my);
void file_sfile_filepath_set(struct SpaceFile *sfile, const char *filepath);
void file_sfile_to_operator_ex(bContext *C,
@@ -136,6 +115,6 @@ void file_tool_props_region_panels_register(struct ARegionType *art);
void file_execute_region_panels_register(struct ARegionType *art);
/* file_utils.c */
-void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, rcti *r_bounds);
+void file_tile_boundbox(const ARegion *region, FileLayout *layout, const int file, rcti *r_bounds);
#endif /* __FILE_INTERN_H__ */
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 61eb4db8300..a5263378850 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -40,8 +40,8 @@
# include "BLI_winstuff.h"
#endif
-#include "ED_screen.h"
#include "ED_fileselect.h"
+#include "ED_screen.h"
#include "ED_select_utils.h"
#include "UI_interface.h"
@@ -62,18 +62,23 @@
#include "filelist.h"
#include "fsmenu.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
#include <ctype.h>
#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* -------------------------------------------------------------------- */
+/** \name File Selection Utilities
+ * \{ */
-/* ---------- FILE SELECTION ------------ */
-static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const rcti *rect_region)
+static FileSelection find_file_mouse_rect(SpaceFile *sfile,
+ ARegion *region,
+ const rcti *rect_region)
{
FileSelection sel;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
rcti rect_view;
rctf rect_view_fl;
rctf rect_region_fl;
@@ -98,7 +103,7 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const r
return sel;
}
-static void file_deselect_all(SpaceFile *sfile, unsigned int flag)
+static void file_deselect_all(SpaceFile *sfile, uint flag)
{
FileSelection sel;
sel.first = 0;
@@ -141,12 +146,12 @@ static void clamp_to_filelist(int numfiles, FileSelection *sel)
static FileSelection file_selection_get(bContext *C, const rcti *rect, bool fill)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
int numfiles = filelist_files_ensure(sfile->files);
FileSelection sel;
- sel = find_file_mouse_rect(sfile, ar, rect);
+ sel = find_file_mouse_rect(sfile, region, rect);
if (!((sel.first == -1) && (sel.last == -1))) {
clamp_to_filelist(numfiles, &sel);
}
@@ -206,7 +211,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
else {
if (is_parent_dir) {
/* avoids /../../ */
- BLI_parent_dir(params->dir);
+ BLI_path_parent_dir(params->dir);
if (params->recursion_level > 1) {
/* Disable 'dirtree' recursion when going up in tree. */
@@ -215,9 +220,9 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
}
}
else {
- BLI_cleanup_dir(BKE_main_blendfile_path(bmain), params->dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir);
strcat(params->dir, file->relpath);
- BLI_add_slash(params->dir);
+ BLI_path_slash_ensure(params->dir);
}
ED_file_change_dir(C);
@@ -253,34 +258,34 @@ static bool file_is_any_selected(struct FileList *files)
/**
* If \a file is outside viewbounds, this adjusts view to make sure it's inside
*/
-static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const int file)
+static void file_ensure_inside_viewbounds(ARegion *region, SpaceFile *sfile, const int file)
{
- FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
- rctf *cur = &ar->v2d.cur;
+ FileLayout *layout = ED_fileselect_get_layout(sfile, region);
+ rctf *cur = &region->v2d.cur;
rcti rect;
bool changed = true;
- file_tile_boundbox(ar, layout, file, &rect);
+ file_tile_boundbox(region, layout, file, &rect);
/* down - also use if tile is higher than viewbounds so view is aligned to file name */
- if (cur->ymin > rect.ymin || layout->tile_h > ar->winy) {
+ if (cur->ymin > rect.ymin || layout->tile_h > region->winy) {
cur->ymin = rect.ymin - (2 * layout->tile_border_y);
- cur->ymax = cur->ymin + ar->winy;
+ cur->ymax = cur->ymin + region->winy;
}
/* up */
else if ((cur->ymax - layout->offset_top) < rect.ymax) {
cur->ymax = rect.ymax + layout->tile_border_y + layout->offset_top;
- cur->ymin = cur->ymax - ar->winy;
+ cur->ymin = cur->ymax - region->winy;
}
/* left - also use if tile is wider than viewbounds so view is aligned to file name */
- else if (cur->xmin > rect.xmin || layout->tile_w > ar->winx) {
+ else if (cur->xmin > rect.xmin || layout->tile_w > region->winx) {
cur->xmin = rect.xmin - layout->tile_border_x;
- cur->xmax = cur->xmin + ar->winx;
+ cur->xmax = cur->xmin + region->winx;
}
/* right */
else if (cur->xmax < rect.xmax) {
cur->xmax = rect.xmax + (2 * layout->tile_border_x);
- cur->xmin = cur->xmax - ar->winx;
+ cur->xmin = cur->xmax - region->winx;
}
else {
BLI_assert(cur->xmin <= rect.xmin && cur->xmax >= rect.xmax && cur->ymin <= rect.ymin &&
@@ -289,7 +294,7 @@ static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const i
}
if (changed) {
- UI_view2d_curRect_validate(&ar->v2d);
+ UI_view2d_curRect_validate(&region->v2d);
}
}
@@ -323,16 +328,16 @@ static FileSelect file_select(
sfile->params->active_file = -1;
}
else if (sel.last >= 0) {
- ARegion *ar = CTX_wm_region(C);
- const FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ ARegion *region = CTX_wm_region(C);
+ const FileLayout *layout = ED_fileselect_get_layout(sfile, region);
/* Adjust view to display selection. Doing iterations for first and last
* selected item makes view showing as much of the selection possible.
* Not really useful if tiles are (almost) bigger than viewbounds though. */
- if (((layout->flag & FILE_LAYOUT_HOR) && ar->winx > (1.2f * layout->tile_w)) ||
- ((layout->flag & FILE_LAYOUT_VER) && ar->winy > (2.0f * layout->tile_h))) {
- file_ensure_inside_viewbounds(ar, sfile, sel.last);
- file_ensure_inside_viewbounds(ar, sfile, sel.first);
+ if (((layout->flag & FILE_LAYOUT_HOR) && region->winx > (1.2f * layout->tile_w)) ||
+ ((layout->flag & FILE_LAYOUT_VER) && region->winy > (2.0f * layout->tile_h))) {
+ file_ensure_inside_viewbounds(region, sfile, sel.last);
+ file_ensure_inside_viewbounds(region, sfile, sel.first);
}
}
@@ -342,20 +347,26 @@ static FileSelect file_select(
return retval;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Box Select Operator
+ * \{ */
+
static int file_box_select_find_last_selected(SpaceFile *sfile,
- ARegion *ar,
+ ARegion *region,
const FileSelection *sel,
const int mouse_xy[2])
{
- FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ FileLayout *layout = ED_fileselect_get_layout(sfile, region);
rcti bounds_first, bounds_last;
int dist_first, dist_last;
float mouseco_view[2];
- UI_view2d_region_to_view(&ar->v2d, UNPACK2(mouse_xy), &mouseco_view[0], &mouseco_view[1]);
+ UI_view2d_region_to_view(&region->v2d, UNPACK2(mouse_xy), &mouseco_view[0], &mouseco_view[1]);
- file_tile_boundbox(ar, layout, sel->first, &bounds_first);
- file_tile_boundbox(ar, layout, sel->last, &bounds_last);
+ file_tile_boundbox(region, layout, sel->first, &bounds_first);
+ file_tile_boundbox(region, layout, sel->last, &bounds_last);
/* are first and last in the same column (horizontal layout)/row (vertical layout)? */
if ((layout->flag & FILE_LAYOUT_HOR && bounds_first.xmin == bounds_last.xmin) ||
@@ -377,7 +388,7 @@ static int file_box_select_find_last_selected(SpaceFile *sfile,
static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
FileSelection sel;
@@ -390,7 +401,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve
if (result == OPERATOR_RUNNING_MODAL) {
WM_operator_properties_border_to_rcti(op, &rect);
- ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect);
+ ED_fileselect_layout_isect_rect(sfile->layout, &region->v2d, &rect, &rect);
sel = file_selection_get(C, &rect, 0);
if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) {
@@ -418,7 +429,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve
}
params->sel_first = sel.first;
params->sel_last = sel.last;
- params->active_file = file_box_select_find_last_selected(sfile, ar, &sel, event->mval);
+ params->active_file = file_box_select_find_last_selected(sfile, region, &sel, event->mval);
}
else {
params->highlight_file = -1;
@@ -433,7 +444,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve
static int file_box_select_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
rcti rect;
FileSelect ret;
@@ -446,7 +457,7 @@ static int file_box_select_exec(bContext *C, wmOperator *op)
file_deselect_all(sfile, FILE_SEL_SELECTED);
}
- ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect);
+ ED_fileselect_layout_isect_rect(sfile->layout, &region->v2d, &rect, &rect);
ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, false, false);
@@ -482,9 +493,15 @@ void FILE_OT_select_box(wmOperatorType *ot)
WM_operator_properties_select_operation_simple(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Pick Operator
+ * \{ */
+
static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelect ret;
rcti rect;
@@ -493,14 +510,14 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool do_diropen = RNA_boolean_get(op->ptr, "open");
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
- if (ar->regiontype != RGN_TYPE_WINDOW) {
+ if (region->regiontype != RGN_TYPE_WINDOW) {
return OPERATOR_CANCELLED;
}
rect.xmin = rect.xmax = event->mval[0];
rect.ymin = rect.ymax = event->mval[1];
- if (!ED_fileselect_layout_is_inside_pt(sfile->layout, &ar->v2d, rect.xmin, rect.ymin)) {
+ if (!ED_fileselect_layout_is_inside_pt(sfile->layout, &region->v2d, rect.xmin, rect.ymin)) {
return OPERATOR_CANCELLED;
}
@@ -536,7 +553,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
}
- WM_event_add_mousemove(C); /* for directory changes */
+ WM_event_add_mousemove(CTX_wm_window(C)); /* for directory changes */
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
return OPERATOR_FINISHED;
@@ -575,10 +592,17 @@ void FILE_OT_select(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Walk Operator
+ * \{ */
+
/**
* \returns true if selection has changed
*/
-static bool file_walk_select_selection_set(bContext *C,
+static bool file_walk_select_selection_set(wmWindow *win,
+ ARegion *region,
SpaceFile *sfile,
const int direction,
const int numfiles,
@@ -626,11 +650,11 @@ static bool file_walk_select_selection_set(bContext *C,
}
else {
/* select last file */
- if (ELEM(direction, FILE_SELECT_WALK_UP, FILE_SELECT_WALK_LEFT)) {
+ if (ELEM(direction, UI_SELECT_WALK_UP, UI_SELECT_WALK_LEFT)) {
params->active_file = active = numfiles - 1;
}
/* select first file */
- else if (ELEM(direction, FILE_SELECT_WALK_DOWN, FILE_SELECT_WALK_RIGHT)) {
+ else if (ELEM(direction, UI_SELECT_WALK_DOWN, UI_SELECT_WALK_RIGHT)) {
params->active_file = active = 0;
}
else {
@@ -656,7 +680,7 @@ static bool file_walk_select_selection_set(bContext *C,
/* highlight file under mouse pos */
params->highlight_file = -1;
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(win);
}
/* do the actual selection */
@@ -686,7 +710,7 @@ static bool file_walk_select_selection_set(bContext *C,
fileselect_file_set(sfile, params->active_file);
/* ensure newly selected file is inside viewbounds */
- file_ensure_inside_viewbounds(CTX_wm_region(C), sfile, params->active_file);
+ file_ensure_inside_viewbounds(region, sfile, params->active_file);
/* selection changed */
return true;
@@ -702,6 +726,8 @@ static bool file_walk_select_do(bContext *C,
const bool extend,
const bool fill)
{
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *region = CTX_wm_region(C);
struct FileList *files = sfile->files;
const int numfiles = filelist_files_ensure(files);
const bool has_selection = file_is_any_selected(files);
@@ -717,27 +743,26 @@ static bool file_walk_select_do(bContext *C,
}
if (has_selection) {
- ARegion *ar = CTX_wm_region(C);
- FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ FileLayout *layout = ED_fileselect_get_layout(sfile, region);
const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->flow_columns;
- if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_UP) ||
- (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_LEFT)) {
+ if ((layout->flag & FILE_LAYOUT_HOR && direction == UI_SELECT_WALK_UP) ||
+ (layout->flag & FILE_LAYOUT_VER && direction == UI_SELECT_WALK_LEFT)) {
active_new = active_old - 1;
other_site = active_old + 1;
}
- else if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_DOWN) ||
- (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_RIGHT)) {
+ else if ((layout->flag & FILE_LAYOUT_HOR && direction == UI_SELECT_WALK_DOWN) ||
+ (layout->flag & FILE_LAYOUT_VER && direction == UI_SELECT_WALK_RIGHT)) {
active_new = active_old + 1;
other_site = active_old - 1;
}
- else if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_LEFT) ||
- (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_UP)) {
+ else if ((layout->flag & FILE_LAYOUT_HOR && direction == UI_SELECT_WALK_LEFT) ||
+ (layout->flag & FILE_LAYOUT_VER && direction == UI_SELECT_WALK_UP)) {
active_new = active_old - idx_shift;
other_site = active_old + idx_shift;
}
- else if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_RIGHT) ||
- (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_DOWN)) {
+ else if ((layout->flag & FILE_LAYOUT_HOR && direction == UI_SELECT_WALK_RIGHT) ||
+ (layout->flag & FILE_LAYOUT_VER && direction == UI_SELECT_WALK_DOWN)) {
active_new = active_old + idx_shift;
other_site = active_old - idx_shift;
@@ -763,7 +788,8 @@ static bool file_walk_select_do(bContext *C,
}
}
- return file_walk_select_selection_set(C,
+ return file_walk_select_selection_set(win,
+ region,
sfile,
direction,
numfiles,
@@ -793,13 +819,6 @@ static int file_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *U
void FILE_OT_select_walk(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {FILE_SELECT_WALK_UP, "UP", 0, "Prev", ""},
- {FILE_SELECT_WALK_DOWN, "DOWN", 0, "Next", ""},
- {FILE_SELECT_WALK_LEFT, "LEFT", 0, "Left", ""},
- {FILE_SELECT_WALK_RIGHT, "RIGHT", 0, "Right", ""},
- {0, NULL, 0, NULL, NULL},
- };
PropertyRNA *prop;
/* identifiers */
@@ -812,13 +831,7 @@ void FILE_OT_select_walk(wmOperatorType *ot)
ot->poll = ED_operator_file_active;
/* properties */
- prop = RNA_def_enum(ot->srna,
- "direction",
- direction_items,
- 0,
- "Walk Direction",
- "Select/Deselect file in this direction");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ WM_operator_properties_select_walk_direction(ot);
prop = RNA_def_boolean(ot->srna,
"extend",
false,
@@ -830,9 +843,15 @@ void FILE_OT_select_walk(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select All Operator
+ * \{ */
+
static int file_select_all_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelection sel;
const int numfiles = filelist_files_ensure(sfile->files);
@@ -880,8 +899,8 @@ static int file_select_all_exec(bContext *C, wmOperator *op)
}
file_draw_check(C);
- WM_event_add_mousemove(C);
- ED_area_tag_redraw(sa);
+ WM_event_add_mousemove(CTX_wm_window(C));
+ ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
@@ -901,7 +920,11 @@ void FILE_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-/* ---------- BOOKMARKS ----------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Bookmark Operator
+ * \{ */
/* Note we could get rid of this one, but it's used by some addon so...
* Does not hurt keeping it around for now. */
@@ -917,7 +940,7 @@ static int bookmark_select_exec(bContext *C, wmOperator *op)
RNA_property_string_get(op->ptr, prop, entry);
BLI_strncpy(params->dir, entry, sizeof(params->dir));
- BLI_cleanup_dir(BKE_main_blendfile_path(bmain), params->dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir);
ED_file_change_dir(C);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -944,9 +967,15 @@ void FILE_OT_select_bookmark(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Bookmark Operator
+ * \{ */
+
static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
struct FSMenu *fsmenu = ED_fsmenu_get();
struct FileSelectParams *params = ED_fileselect_get_params(sfile);
@@ -956,13 +985,15 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
fsmenu_insert_entry(
fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, NULL, ICON_FILE_FOLDER, FS_INSERT_SAVE);
- BLI_make_file_string(
- "/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_join_dirfile(name,
+ sizeof(name),
+ BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
}
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(area);
+ ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
@@ -978,9 +1009,15 @@ void FILE_OT_bookmark_add(wmOperatorType *ot)
ot->poll = ED_operator_file_active;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Bookmark Operator
+ * \{ */
+
static int bookmark_delete_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
struct FSMenu *fsmenu = ED_fsmenu_get();
int nentries = ED_fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
@@ -999,13 +1036,13 @@ static int bookmark_delete_exec(bContext *C, wmOperator *op)
char name[FILE_MAX];
fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
- BLI_make_file_string("/",
- name,
- BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
- BLENDER_BOOKMARK_FILE);
+ BLI_join_dirfile(name,
+ sizeof(name),
+ BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(area);
+ ED_area_tag_redraw(area);
}
}
@@ -1030,9 +1067,15 @@ void FILE_OT_bookmark_delete(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cleanup Bookmark Operator
+ * \{ */
+
static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
struct FSMenu *fsmenu = ED_fsmenu_get();
struct FSMenuEntry *fsme_next, *fsme = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS);
int index;
@@ -1053,12 +1096,14 @@ static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op))
if (changed) {
char name[FILE_MAX];
- BLI_make_file_string(
- "/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_join_dirfile(name,
+ sizeof(name),
+ BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
fsmenu_refresh_bookmarks_status(CTX_wm_manager(C), fsmenu);
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(area);
+ ED_area_tag_redraw(area);
}
return OPERATOR_FINISHED;
@@ -1078,6 +1123,12 @@ void FILE_OT_bookmark_cleanup(wmOperatorType *ot)
/* properties */
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Reorder Bookmark Operator
+ * \{ */
+
enum {
FILE_BOOKMARK_MOVE_TOP = -2,
FILE_BOOKMARK_MOVE_UP = -1,
@@ -1087,7 +1138,7 @@ enum {
static int bookmark_move_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
struct FSMenu *fsmenu = ED_fsmenu_get();
struct FSMenuEntry *fsmentry = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS);
@@ -1130,11 +1181,13 @@ static int bookmark_move_exec(bContext *C, wmOperator *op)
/* Need to update active bookmark number. */
sfile->bookmarknr = new_index;
- BLI_make_file_string(
- "/", fname, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_join_dirfile(fname,
+ sizeof(fname),
+ BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, fname);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
@@ -1167,19 +1220,27 @@ void FILE_OT_bookmark_move(wmOperatorType *ot)
"Direction to move the active bookmark towards");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Reset Recent Blend Files Operator
+ * \{ */
+
static int reset_recent_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
char name[FILE_MAX];
struct FSMenu *fsmenu = ED_fsmenu_get();
while (ED_fsmenu_get_entry(fsmenu, FS_CATEGORY_RECENT, 0) != NULL) {
fsmenu_remove_entry(fsmenu, FS_CATEGORY_RECENT, 0);
}
- BLI_make_file_string(
- "/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
+ BLI_join_dirfile(name,
+ sizeof(name),
+ BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
@@ -1196,9 +1257,15 @@ void FILE_OT_reset_recent(wmOperatorType *ot)
ot->poll = ED_operator_file_active;
}
-int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Highlight File Operator
+ * \{ */
+
+int file_highlight_set(SpaceFile *sfile, ARegion *region, int mx, int my)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
FileSelectParams *params;
int numfiles, origfile;
@@ -1211,8 +1278,8 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
origfile = params->highlight_file;
- mx -= ar->winrct.xmin;
- my -= ar->winrct.ymin;
+ mx -= region->winrct.xmin;
+ my -= region->winrct.ymin;
if (ED_fileselect_layout_is_inside_pt(sfile->layout, v2d, mx, my)) {
float fx, fy;
@@ -1239,10 +1306,10 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- if (!file_highlight_set(sfile, ar, event->x, event->y)) {
+ if (!file_highlight_set(sfile, region, event->x, event->y)) {
return OPERATOR_PASS_THROUGH;
}
@@ -1263,17 +1330,23 @@ void FILE_OT_highlight(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sort from Column Operator
+ * \{ */
+
static int file_column_sort_ui_context_invoke(bContext *C,
wmOperator *UNUSED(op),
const wmEvent *event)
{
- const ARegion *ar = CTX_wm_region(C);
+ const ARegion *region = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
if (file_attribute_column_header_is_inside(
- &ar->v2d, sfile->layout, event->mval[0], event->mval[1])) {
+ &region->v2d, sfile->layout, event->mval[0], event->mval[1])) {
const FileAttributeColumnType column_type = file_attribute_column_type_find_isect(
- &ar->v2d, sfile->params, sfile->layout, event->mval[0]);
+ &region->v2d, sfile->params, sfile->layout, event->mval[0]);
if (column_type != COLUMN_NONE) {
const FileAttributeColumn *column = &sfile->layout->attribute_columns[column_type];
@@ -1310,18 +1383,11 @@ void FILE_OT_sort_column_ui_context(wmOperatorType *ot)
ot->flag = OPTYPE_INTERNAL;
}
-int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
- wmOperator *op = sfile->op;
-
- sfile->op = NULL;
+/** \} */
- WM_event_fileselect_event(wm, op, EVT_FILESELECT_CANCEL);
-
- return OPERATOR_FINISHED;
-}
+/* -------------------------------------------------------------------- */
+/** \name Cancel File Selector Operator
+ * \{ */
static bool file_operator_poll(bContext *C)
{
@@ -1335,6 +1401,19 @@ static bool file_operator_poll(bContext *C)
return poll;
}
+static int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ wmOperator *op = sfile->op;
+
+ sfile->op = NULL;
+
+ WM_event_fileselect_event(wm, op, EVT_FILESELECT_CANCEL);
+
+ return OPERATOR_FINISHED;
+}
+
void FILE_OT_cancel(struct wmOperatorType *ot)
{
/* identifiers */
@@ -1347,6 +1426,12 @@ void FILE_OT_cancel(struct wmOperatorType *ot)
ot->poll = file_operator_poll;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Operator Utilities
+ * \{ */
+
void file_sfile_to_operator_ex(bContext *C, wmOperator *op, SpaceFile *sfile, char *filepath)
{
Main *bmain = CTX_data_main(C);
@@ -1521,7 +1606,13 @@ bool file_draw_check_exists(SpaceFile *sfile)
return false;
}
-int file_exec(bContext *C, wmOperator *exec_op)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Execute File Window Operator
+ * \{ */
+
+static int file_exec(bContext *C, wmOperator *exec_op)
{
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
@@ -1536,14 +1627,16 @@ int file_exec(bContext *C, wmOperator *exec_op)
}
if (FILENAME_IS_PARENT(file->relpath)) {
- BLI_parent_dir(sfile->params->dir);
+ BLI_path_parent_dir(sfile->params->dir);
}
else {
- BLI_cleanup_path(BKE_main_blendfile_path(bmain), sfile->params->dir);
+ BLI_path_normalize(BKE_main_blendfile_path(bmain), sfile->params->dir);
BLI_path_append(sfile->params->dir, sizeof(sfile->params->dir) - 1, file->relpath);
- BLI_add_slash(sfile->params->dir);
+ BLI_path_slash_ensure(sfile->params->dir);
+ }
+ if (file->redirection_path) {
+ STRNCPY(sfile->params->dir, file->redirection_path);
}
-
ED_file_change_dir(C);
}
/* opening file - sends events now, so things get handled on windowqueue level */
@@ -1579,10 +1672,10 @@ int file_exec(bContext *C, wmOperator *exec_op)
FS_INSERT_SAVE | FS_INSERT_FIRST);
}
- BLI_make_file_string(BKE_main_blendfile_path(bmain),
- filepath,
- BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
- BLENDER_BOOKMARK_FILE);
+ BLI_join_dirfile(filepath,
+ sizeof(filepath),
+ BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
fsmenu_write_file(ED_fsmenu_get(), filepath);
WM_event_fileselect_event(wm, op, EVT_FILESELECT_EXEC);
}
@@ -1612,14 +1705,57 @@ void FILE_OT_execute(struct wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-int file_parent_exec(bContext *C, wmOperator *UNUSED(unused))
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Refresh File List Operator
+ * \{ */
+
+static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ struct FSMenu *fsmenu = ED_fsmenu_get();
+
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
+
+ /* refresh system directory menu */
+ fsmenu_refresh_system_category(fsmenu);
+
+ /* Update bookmarks 'valid' state. */
+ fsmenu_refresh_bookmarks_status(wm, fsmenu);
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_refresh(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Refresh Filelist";
+ ot->description = "Refresh the file list";
+ ot->idname = "FILE_OT_refresh";
+
+ /* api callbacks */
+ ot->exec = file_refresh_exec;
+ ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Navigate Parent Operator
+ * \{ */
+
+static int file_parent_exec(bContext *C, wmOperator *UNUSED(unused))
{
Main *bmain = CTX_data_main(C);
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile->params) {
- if (BLI_parent_dir(sfile->params->dir)) {
- BLI_cleanup_dir(BKE_main_blendfile_path(bmain), sfile->params->dir);
+ if (BLI_path_parent_dir(sfile->params->dir)) {
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), sfile->params->dir);
ED_file_change_dir(C);
if (sfile->params->recursion_level > 1) {
/* Disable 'dirtree' recursion when going up in tree. */
@@ -1645,21 +1781,27 @@ void FILE_OT_parent(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
-static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Navigate Previous Operator
+ * \{ */
+
+static int file_previous_exec(bContext *C, wmOperator *UNUSED(op))
{
- wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
- struct FSMenu *fsmenu = ED_fsmenu_get();
-
- ED_fileselect_clear(wm, sa, sfile);
- /* refresh system directory menu */
- fsmenu_refresh_system_category(fsmenu);
+ if (sfile->params) {
+ if (!sfile->folders_next) {
+ sfile->folders_next = folderlist_new();
+ }
- /* Update bookmarks 'valid' state. */
- fsmenu_refresh_bookmarks_status(wm, fsmenu);
+ folderlist_pushdir(sfile->folders_next, sfile->params->dir);
+ folderlist_popdir(sfile->folders_prev, sfile->params->dir);
+ folderlist_pushdir(sfile->folders_next, sfile->params->dir);
+ ED_file_change_dir(C);
+ }
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
return OPERATOR_FINISHED;
@@ -1677,18 +1819,25 @@ void FILE_OT_previous(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
-int file_previous_exec(bContext *C, wmOperator *UNUSED(unused))
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Navigate Next Operator
+ * \{ */
+
+static int file_next_exec(bContext *C, wmOperator *UNUSED(unused))
{
SpaceFile *sfile = CTX_wm_space_file(C);
-
if (sfile->params) {
if (!sfile->folders_next) {
sfile->folders_next = folderlist_new();
}
- folderlist_pushdir(sfile->folders_next, sfile->params->dir);
- folderlist_popdir(sfile->folders_prev, sfile->params->dir);
- folderlist_pushdir(sfile->folders_next, sfile->params->dir);
+ folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
+ folderlist_popdir(sfile->folders_next, sfile->params->dir);
+
+ // update folders_prev so we can check for it in folderlist_clear_next()
+ folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
ED_file_change_dir(C);
}
@@ -1709,33 +1858,18 @@ void FILE_OT_next(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
-int file_next_exec(bContext *C, wmOperator *UNUSED(unused))
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
- if (sfile->params) {
- if (!sfile->folders_next) {
- sfile->folders_next = folderlist_new();
- }
-
- folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
- folderlist_popdir(sfile->folders_next, sfile->params->dir);
+/** \} */
- // update folders_prev so we can check for it in folderlist_clear_next()
- folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
-
- ED_file_change_dir(C);
- }
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
-
- return OPERATOR_FINISHED;
-}
+/* -------------------------------------------------------------------- */
+/** \name Smooth Scroll Operator
+ * \{ */
/* only meant for timer usage */
static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ARegion *ar, *oldar = CTX_wm_region(C);
+ ARegion *region, *region_ctx = CTX_wm_region(C);
const bool is_horizontal = (sfile->layout->flag & FILE_LAYOUT_HOR) != 0;
int i;
@@ -1777,8 +1911,8 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
}
/* we need the correct area for scrolling */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (!ar || ar->regiontype != RGN_TYPE_WINDOW) {
+ region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+ if (!region || region->regiontype != RGN_TYPE_WINDOW) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
sfile->smoothscroll_timer = NULL;
return OPERATOR_PASS_THROUGH;
@@ -1794,9 +1928,9 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
sfile->scroll_offset = (edit_idx / items_block_size) * items_block_size;
}
- const int numfiles_layout = ED_fileselect_layout_numfiles(sfile->layout, ar);
+ const int numfiles_layout = ED_fileselect_layout_numfiles(sfile->layout, region);
const int first_visible_item = ED_fileselect_layout_offset(
- sfile->layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax);
+ sfile->layout, (int)region->v2d.cur.xmin, (int)-region->v2d.cur.ymax);
const int last_visible_item = first_visible_item + numfiles_layout + 1;
/* Note: the special case for vertical layout is because filename is at the bottom of items then,
@@ -1813,10 +1947,10 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
* 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;
- const float max_tot_scroll = is_horizontal ? ar->v2d.tot.xmax : -ar->v2d.tot.ymin;
- const float min_curr_scroll = is_horizontal ? ar->v2d.cur.xmin : -ar->v2d.cur.ymax;
- const float max_curr_scroll = is_horizontal ? ar->v2d.cur.xmax : -ar->v2d.cur.ymin;
+ const float min_tot_scroll = is_horizontal ? region->v2d.tot.xmin : -region->v2d.tot.ymax;
+ const float max_tot_scroll = is_horizontal ? region->v2d.tot.xmax : -region->v2d.tot.ymin;
+ const float min_curr_scroll = is_horizontal ? region->v2d.cur.xmin : -region->v2d.cur.ymax;
+ const float max_curr_scroll = is_horizontal ? region->v2d.cur.xmax : -region->v2d.cur.ymin;
/* Check if we have reached our final scroll position. */
/* Filelist has to be ready, otherwise it makes no sense to stop scrolling yet. */
@@ -1850,7 +1984,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
/* Temporarily set context to the main window region,
* so that the pan operator works. */
- CTX_wm_region_set(C, ar);
+ CTX_wm_region_set(C, region);
/* scroll one step in the desired direction */
PointerRNA op_ptr;
@@ -1896,10 +2030,10 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
WM_operator_name_call(C, "VIEW2D_OT_pan", WM_OP_EXEC_DEFAULT, &op_ptr);
WM_operator_properties_free(&op_ptr);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
/* and restore context */
- CTX_wm_region_set(C, oldar);
+ CTX_wm_region_set(C, region_ctx);
return OPERATOR_FINISHED;
}
@@ -1917,6 +2051,12 @@ void FILE_OT_smoothscroll(wmOperatorType *ot)
ot->poll = ED_operator_file_active;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name File Selector Drop Operator
+ * \{ */
+
static int filepath_drop_exec(bContext *C, wmOperator *op)
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -1955,6 +2095,12 @@ void FILE_OT_filepath_drop(wmOperatorType *ot)
RNA_def_string_file_path(ot->srna, "filepath", "Path", FILE_MAX, "", "");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name New Directory Operator
+ * \{ */
+
/**
* Create a new, non-existing folder name, returns 1 if successful, 0 if name couldn't be created.
* The actual name is returned in 'name', 'folder' contains the complete path,
@@ -1979,7 +2125,7 @@ static int new_folder_path(const char *parent, char *folder, char *name)
return (len < FILE_MAXFILE);
}
-int file_directory_new_exec(bContext *C, wmOperator *op)
+static int file_directory_new_exec(bContext *C, wmOperator *op)
{
char name[FILE_MAXFILE];
char path[FILE_MAX];
@@ -1988,7 +2134,6 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
const bool do_diropen = RNA_boolean_get(op->ptr, "open");
if (!sfile->params) {
@@ -2047,13 +2192,13 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
/* set timer to smoothly view newly generated file */
/* max 30 frs/sec */
if (sfile->smoothscroll_timer != NULL) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
+ WM_event_remove_timer(wm, CTX_wm_window(C), sfile->smoothscroll_timer);
}
sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0);
sfile->scroll_offset = 0;
/* reload dir to make sure we're seeing what's in the directory */
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
if (do_diropen) {
BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir));
@@ -2087,6 +2232,12 @@ void FILE_OT_directory_new(struct wmOperatorType *ot)
WM_operator_properties_confirm_or_exec(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Refresh File List Operator
+ * \{ */
+
/* TODO This should go to BLI_path_utils. */
static void file_expand_directory(bContext *C)
{
@@ -2123,7 +2274,7 @@ static void file_expand_directory(bContext *C)
sfile->params->dir[3] = '\0';
}
else if (BLI_path_is_unc(sfile->params->dir)) {
- BLI_cleanup_unc(sfile->params->dir, FILE_MAX_LIBEXTRA);
+ BLI_path_normalize_unc(sfile->params->dir, FILE_MAX_LIBEXTRA);
}
#endif
}
@@ -2140,7 +2291,7 @@ static bool can_create_dir(const char *dir)
if (BLI_path_is_unc(dir)) {
char parent[PATH_MAX];
BLI_strncpy(parent, dir, PATH_MAX);
- BLI_parent_dir(parent);
+ BLI_path_parent_dir(parent);
return BLI_is_dir(parent);
}
return true;
@@ -2187,7 +2338,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
}
}
- BLI_cleanup_dir(BKE_main_blendfile_path(bmain), sfile->params->dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), sfile->params->dir);
if (filelist_is_dir(sfile->files, sfile->params->dir)) {
if (!STREQ(sfile->params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */
@@ -2272,7 +2423,7 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
/* if directory, open it and empty filename field */
if (filelist_is_dir(sfile->files, filepath)) {
- BLI_cleanup_dir(BKE_main_blendfile_path(bmain), filepath);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), filepath);
BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
sfile->params->file[0] = '\0';
ED_file_change_dir(C);
@@ -2286,27 +2437,20 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
}
}
-void FILE_OT_refresh(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Refresh Filelist";
- ot->description = "Refresh the file list";
- ot->idname = "FILE_OT_refresh";
+/** \} */
- /* api callbacks */
- ot->exec = file_refresh_exec;
- ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
-}
+/* -------------------------------------------------------------------- */
+/** \name Toggle Show Hidden Files Operator
+ * \{ */
static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
if (sfile->params) {
sfile->params->flag ^= FILE_HIDE_DOT;
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -2325,6 +2469,12 @@ void FILE_OT_hidedot(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Increment Filename Operator
+ * \{ */
+
static bool file_filenum_poll(bContext *C)
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -2337,16 +2487,16 @@ static bool file_filenum_poll(bContext *C)
}
/**
- * Looks for a string of digits within name (using BLI_stringdec) and adjusts it by add.
+ * Looks for a string of digits within name (using BLI_path_sequence_decode) and adjusts it by add.
*/
static void filenum_newname(char *name, size_t name_size, int add)
{
char head[FILE_MAXFILE], tail[FILE_MAXFILE];
char name_temp[FILE_MAXFILE];
int pic;
- unsigned short digits;
+ ushort digits;
- pic = BLI_stringdec(name, head, tail, &digits);
+ pic = BLI_path_sequence_decode(name, head, tail, &digits);
/* are we going from 100 -> 99 or from 10 -> 9 */
if (add < 0 && digits > 0) {
@@ -2364,19 +2514,19 @@ static void filenum_newname(char *name, size_t name_size, int add)
if (pic < 0) {
pic = 0;
}
- BLI_stringenc(name_temp, head, tail, digits, pic);
+ BLI_path_sequence_encode(name_temp, head, tail, digits, pic);
BLI_strncpy(name, name_temp, name_size);
}
static int file_filenum_exec(bContext *C, wmOperator *op)
{
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
int inc = RNA_int_get(op->ptr, "increment");
if (sfile->params && (inc != 0)) {
filenum_newname(sfile->params->file, sizeof(sfile->params->file), inc);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
file_draw_check(C);
// WM_event_add_notifier(C, NC_WINDOW, NULL);
}
@@ -2399,6 +2549,12 @@ void FILE_OT_filenum(struct wmOperatorType *ot)
RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Rename File/Directory Operator
+ * \{ */
+
static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool require_selected)
{
const int numfiles = filelist_files_ensure(sfile->files);
@@ -2420,12 +2576,12 @@ static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool requ
static int file_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
if (sfile->params) {
file_rename_state_activate(sfile, sfile->params->active_file, true);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
return OPERATOR_FINISHED;
@@ -2433,12 +2589,12 @@ static int file_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
if (sfile->params) {
file_rename_state_activate(sfile, sfile->params->highlight_file, false);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
return OPERATOR_FINISHED;
@@ -2457,6 +2613,12 @@ void FILE_OT_rename(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete File Operator
+ * \{ */
+
static bool file_delete_poll(bContext *C)
{
bool poll = ED_operator_file_active(C);
@@ -2487,24 +2649,20 @@ static bool file_delete_poll(bContext *C)
return poll;
}
-int file_delete_exec(bContext *C, wmOperator *op)
+static int file_delete_exec(bContext *C, wmOperator *op)
{
- char str[FILE_MAX];
- Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
- FileDirEntry *file;
int numfiles = filelist_files_ensure(sfile->files);
- int i;
const char *error_message = NULL;
bool report_error = false;
errno = 0;
- for (i = 0; i < numfiles; i++) {
+ for (int i = 0; i < numfiles; i++) {
if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) {
- file = filelist_file(sfile->files, i);
- BLI_make_file_string(BKE_main_blendfile_path(bmain), str, sfile->params->dir, file->relpath);
+ FileDirEntry *file = filelist_file(sfile->files, i);
+ char str[FILE_MAX];
+ BLI_join_dirfile(str, sizeof(str), sfile->params->dir, file->relpath);
if (BLI_delete_soft(str, &error_message) != 0 || BLI_exists(str)) {
report_error = true;
}
@@ -2523,7 +2681,7 @@ int file_delete_exec(bContext *C, wmOperator *op)
}
}
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
return OPERATOR_FINISHED;
@@ -2542,6 +2700,40 @@ void FILE_OT_delete(struct wmOperatorType *ot)
ot->poll = file_delete_poll; /* <- important, handler is on window level */
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Enter Filter Text Operator
+ * \{ */
+
+static int file_start_filter_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_UI);
+ SpaceFile *sf = CTX_wm_space_file(C);
+
+ UI_textbutton_activate_rna(C, region, sf->params, "filter_search");
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_start_filter(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Filter";
+ ot->description = "Start entering filter text";
+ ot->idname = "FILE_OT_start_filter";
+
+ /* api callbacks */
+ ot->exec = file_start_filter_exec;
+ ot->poll = ED_operator_file_active;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Macro Operators
+ * \{ */
+
void ED_operatormacros_file(void)
{
// wmOperatorType *ot;
@@ -2549,3 +2741,5 @@ void ED_operatormacros_file(void)
/* future macros */
}
+
+/** \} */
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 9ba098fcf45..ff9454cd922 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -57,20 +57,20 @@ static bool file_panel_operator_poll(const bContext *C, PanelType *UNUSED(pt))
return (sfile && sfile->op);
}
-static void file_panel_operator_header(const bContext *C, Panel *pa)
+static void file_panel_operator_header(const bContext *C, Panel *panel)
{
SpaceFile *sfile = CTX_wm_space_file(C);
wmOperator *op = sfile->op;
- BLI_strncpy(pa->drawname, WM_operatortype_name(op->type, op->ptr), sizeof(pa->drawname));
+ BLI_strncpy(panel->drawname, WM_operatortype_name(op->type, op->ptr), sizeof(panel->drawname));
}
-static void file_panel_operator(const bContext *C, Panel *pa)
+static void file_panel_operator(const bContext *C, Panel *panel)
{
SpaceFile *sfile = CTX_wm_space_file(C);
wmOperator *op = sfile->op;
- UI_block_func_set(uiLayoutGetBlock(pa->layout), file_draw_check_cb, NULL, NULL);
+ UI_block_func_set(uiLayoutGetBlock(panel->layout), file_draw_check_cb, NULL, NULL);
/* Hack: temporary hide.*/
const char *hide[] = {"filepath", "files", "directory", "filename"};
@@ -82,7 +82,7 @@ static void file_panel_operator(const bContext *C, Panel *pa)
}
uiTemplateOperatorPropertyButs(
- C, pa->layout, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_EMPTY);
+ C, panel->layout, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_EMPTY);
/* Hack: temporary hide.*/
for (int i = 0; i < ARRAY_SIZE(hide); i++) {
@@ -92,7 +92,7 @@ static void file_panel_operator(const bContext *C, Panel *pa)
}
}
- UI_block_func_set(uiLayoutGetBlock(pa->layout), NULL, NULL, NULL);
+ UI_block_func_set(uiLayoutGetBlock(panel->layout), NULL, NULL, NULL);
}
void file_tool_props_region_panels_register(ARegionType *art)
@@ -128,12 +128,12 @@ static void file_panel_execution_execute_button(uiLayout *layout, const char *ti
uiItemO(row, title, ICON_NONE, "FILE_OT_execute");
}
-static void file_panel_execution_buttons_draw(const bContext *C, Panel *pa)
+static void file_panel_execution_buttons_draw(const bContext *C, Panel *panel)
{
bScreen *screen = CTX_wm_screen(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
- uiBlock *block = uiLayoutGetBlock(pa->layout);
+ uiBlock *block = uiLayoutGetBlock(panel->layout);
uiBut *but;
uiLayout *row;
PointerRNA params_rna_ptr, *but_extra_rna_ptr;
@@ -148,7 +148,7 @@ static void file_panel_execution_buttons_draw(const bContext *C, Panel *pa)
RNA_pointer_create(&screen->id, &RNA_FileSelectParams, params, &params_rna_ptr);
- row = uiLayoutRow(pa->layout, false);
+ row = uiLayoutRow(panel->layout, false);
uiLayoutSetScaleY(row, 1.3f);
/* callbacks for operator check functions */
diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c
index a432afc4d99..452f2f704cf 100644
--- a/source/blender/editors/space_file/file_utils.c
+++ b/source/blender/editors/space_file/file_utils.c
@@ -18,26 +18,26 @@
* \ingroup spfile
*/
-#include "BLI_rect.h"
#include "BLI_listbase.h"
+#include "BLI_rect.h"
#include "BLO_readfile.h"
#include "BKE_context.h"
-#include "ED_screen.h"
#include "ED_fileselect.h"
+#include "ED_screen.h"
#include "WM_types.h"
#include "file_intern.h"
-void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, rcti *r_bounds)
+void file_tile_boundbox(const ARegion *region, FileLayout *layout, const int file, rcti *r_bounds)
{
int xmin, ymax;
ED_fileselect_layout_tilepos(layout, file, &xmin, &ymax);
- ymax = (int)ar->v2d.tot.ymax - ymax; /* real, view space ymax */
+ ymax = (int)region->v2d.tot.ymax - ymax; /* real, view space ymax */
BLI_rcti_init(r_bounds,
xmin,
xmin + layout->tile_w + layout->tile_border_x,
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index fa904e0934b..7f6d0658ec8 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -23,8 +23,8 @@
/* global includes */
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
@@ -32,8 +32,8 @@
#ifndef WIN32
# include <unistd.h>
#else
-# include <io.h>
# include <direct.h>
+# include <io.h>
#endif
#include "MEM_guardedalloc.h"
@@ -56,7 +56,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_icons.h"
-#include "BKE_idcode.h"
+#include "BKE_idtype.h"
#include "BKE_main.h"
#include "BLO_readfile.h"
@@ -75,8 +75,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_resources.h"
#include "UI_interface_icons.h"
+#include "UI_resources.h"
#include "atomic_ops.h"
@@ -210,9 +210,13 @@ typedef struct FileListInternEntry {
int blentype;
char *relpath;
+ /** Optional argument for shortcuts, aliases etc. */
+ char *redirection_path;
/** not strictly needed, but used during sorting, avoids to have to recompute it there... */
char *name;
+ /** Defined in BLI_fileops.h */
+ eFileAttributes attributes;
BLI_stat_t st;
} FileListInternEntry;
@@ -260,14 +264,20 @@ enum {
typedef struct FileListEntryPreview {
char path[FILE_MAX];
- unsigned int flags;
+ uint flags;
int index;
ImBuf *img;
} FileListEntryPreview;
+/* Dummy wrapper around FileListEntryPreview to ensure we do not access freed memory when freeing
+ * tasks' data (see T74609). */
+typedef struct FileListEntryPreviewTaskData {
+ FileListEntryPreview *preview;
+} FileListEntryPreviewTaskData;
+
typedef struct FileListFilter {
- unsigned int filter;
- unsigned int filter_id;
+ uint64_t filter;
+ uint64_t filter_id;
char filter_glob[FILE_MAXFILE];
char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
short flags;
@@ -358,7 +368,7 @@ static void filelist_readjob_dir(
/* helper, could probably go in BKE actually? */
static int groupname_to_code(const char *group);
-static unsigned int groupname_to_filter_id(const char *group);
+static uint64_t groupname_to_filter_id(const char *group);
static void filelist_filter_clear(FileList *filelist);
static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size);
@@ -609,54 +619,81 @@ void filelist_setsorting(struct FileList *filelist, const short sort, bool inver
/* ********** Filter helpers ********** */
-static bool is_hidden_file(const char *filename, FileListFilter *filter)
+/* True if filename is meant to be hidden, eg. starting with period. */
+static bool is_hidden_dot_filename(const char *filename, FileListInternEntry *file)
{
- char *sep = (char *)BLI_last_slash(filename);
- bool is_hidden = false;
-
- if (filter->flags & FLF_HIDE_DOT) {
- if (filename[0] == '.' && filename[1] != '.' && filename[1] != '\0') {
- is_hidden = true; /* ignore .file */
- }
- else {
- int len = strlen(filename);
- if ((len > 0) && (filename[len - 1] == '~')) {
- is_hidden = true; /* ignore file~ */
- }
- }
+ if (filename[0] == '.' && !ELEM(filename[1], '.', '\0')) {
+ return true; /* ignore .file */
}
- if (!is_hidden && (filter->flags & FLF_HIDE_PARENT)) {
- if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') {
- is_hidden = true; /* ignore .. */
+ else {
+ int len = strlen(filename);
+ if ((len > 0) && (filename[len - 1] == '~')) {
+ return true; /* ignore file~ */
}
}
- if (!is_hidden && ((filename[0] == '.') && (filename[1] == '\0'))) {
- is_hidden = true; /* ignore . */
- }
+
/* filename might actually be a piece of path, in which case we have to check all its parts. */
- if (!is_hidden && sep) {
+
+ bool hidden = false;
+ char *sep = (char *)BLI_path_slash_rfind(filename);
+
+ if (!hidden && sep) {
char tmp_filename[FILE_MAX_LIBEXTRA];
BLI_strncpy(tmp_filename, filename, sizeof(tmp_filename));
sep = tmp_filename + (sep - filename);
while (sep) {
+ /* This happens when a path contains 'ALTSEP', '\' on Unix for e.g.
+ * Supporting alternate slashes in paths is a bigger task involving changes
+ * in many parts of the code, for now just prevent an assert, see T74579. */
+#if 0
BLI_assert(sep[1] != '\0');
- if (is_hidden_file(sep + 1, filter)) {
- is_hidden = true;
+#endif
+ if (is_hidden_dot_filename(sep + 1, file)) {
+ hidden = true;
break;
}
*sep = '\0';
- sep = (char *)BLI_last_slash(tmp_filename);
+ sep = (char *)BLI_path_slash_rfind(tmp_filename);
+ }
+ }
+ return hidden;
+}
+
+/* True if should be hidden, based on current filtering. */
+static bool is_filtered_hidden(const char *filename,
+ FileListFilter *filter,
+ FileListInternEntry *file)
+{
+ if ((filename[0] == '.') && (filename[1] == '\0')) {
+ return true; /* Ignore . */
+ }
+
+ if (filter->flags & FLF_HIDE_PARENT) {
+ if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') {
+ return true; /* Ignore .. */
}
}
- return is_hidden;
+
+ if ((filter->flags & FLF_HIDE_DOT) && (file->attributes & FILE_ATTR_HIDDEN)) {
+ return true; /* Ignore files with Hidden attribute. */
+ }
+
+#ifndef WIN32
+ /* Check for unix-style names starting with period. */
+ if ((filter->flags & FLF_HIDE_DOT) && is_hidden_dot_filename(filename, file)) {
+ return true;
+ }
+#endif
+
+ return false;
}
static bool is_filtered_file(FileListInternEntry *file,
const char *UNUSED(root),
FileListFilter *filter)
{
- bool is_filtered = !is_hidden_file(file->relpath, filter);
+ bool is_filtered = !is_filtered_hidden(file->relpath, filter, file);
if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) {
/* We only check for types if some type are enabled in filtering. */
@@ -699,7 +736,7 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis
BLI_join_dirfile(path, sizeof(path), root, file->relpath);
if (BLO_library_path_explode(path, dir, &group, &name)) {
- is_filtered = !is_hidden_file(file->relpath, filter);
+ is_filtered = !is_filtered_hidden(file->relpath, filter, file);
if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) {
/* We only check for types if some type are enabled in filtering. */
if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) {
@@ -721,7 +758,7 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis
is_filtered = false;
}
else {
- unsigned int filter_id = groupname_to_filter_id(group);
+ uint64_t filter_id = groupname_to_filter_id(group);
if (!(filter_id & filter->filter_id)) {
is_filtered = false;
}
@@ -747,7 +784,7 @@ static bool is_filtered_main(FileListInternEntry *file,
const char *UNUSED(dir),
FileListFilter *filter)
{
- return !is_hidden_file(file->relpath, filter);
+ return !is_filtered_hidden(file->relpath, filter, file);
}
static void filelist_filter_clear(FileList *filelist)
@@ -810,8 +847,8 @@ void filelist_setfilter_options(FileList *filelist,
const bool do_filter,
const bool hide_dot,
const bool hide_parent,
- const unsigned int filter,
- const unsigned int filter_id,
+ const uint64_t filter,
+ const uint64_t filter_id,
const char *filter_glob,
const char *filter_search)
{
@@ -829,9 +866,13 @@ void filelist_setfilter_options(FileList *filelist,
filelist->filter_data.flags ^= FLF_HIDE_PARENT;
update = true;
}
- if ((filelist->filter_data.filter != filter) || (filelist->filter_data.filter_id != filter_id)) {
+ if (filelist->filter_data.filter != filter) {
filelist->filter_data.filter = filter;
- filelist->filter_data.filter_id = (filter & FILE_TYPE_BLENDERLIB) ? filter_id : FILTER_ID_ALL;
+ update = true;
+ }
+ const uint64_t new_filter_id = (filter & FILE_TYPE_BLENDERLIB) ? filter_id : FILTER_ID_ALL;
+ if (filelist->filter_data.filter_id != new_filter_id) {
+ filelist->filter_data.filter_id = new_filter_id;
update = true;
}
if (!STREQ(filelist->filter_data.filter_glob, filter_glob)) {
@@ -921,12 +962,12 @@ ImBuf *filelist_getimage(struct FileList *filelist, const int index)
return file->image;
}
-static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char *relpath)
+static ImBuf *filelist_geticon_image_ex(FileDirEntry *file)
{
ImBuf *ibuf = NULL;
- if (typeflag & FILE_TYPE_DIR) {
- if (FILENAME_IS_PARENT(relpath)) {
+ if (file->typeflag & FILE_TYPE_DIR) {
+ if (FILENAME_IS_PARENT(file->relpath)) {
ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
}
else {
@@ -943,11 +984,13 @@ static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char
ImBuf *filelist_geticon_image(struct FileList *filelist, const int index)
{
FileDirEntry *file = filelist_geticon_get_file(filelist, index);
-
- return filelist_geticon_image_ex(file->typeflag, file->relpath);
+ return filelist_geticon_image_ex(file);
}
-static int filelist_geticon_ex(FileDirEntry *file, const char *root, const bool is_main, const bool ignore_libdir)
+static int filelist_geticon_ex(FileDirEntry *file,
+ const char *root,
+ const bool is_main,
+ const bool ignore_libdir)
{
const int typeflag = file->typeflag;
@@ -965,22 +1008,43 @@ static int filelist_geticon_ex(FileDirEntry *file, const char *root, const bool
else if (is_main) {
/* Do not return icon for folders if icons are not 'main' draw type
* (e.g. when used over previews). */
- return ICON_FILE_FOLDER;
+ return (file->attributes & FILE_ATTR_ANY_LINK) ? ICON_FOLDER_REDIRECT : ICON_FILE_FOLDER;
}
else {
- /* If this path is in System list then use that icon. */
+
+ /* If this path is in System list or path cache then use that icon. */
struct FSMenu *fsmenu = ED_fsmenu_get();
- FSMenuEntry *tfsm = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
- char fullpath[FILE_MAX_LIBEXTRA];
- BLI_join_dirfile(fullpath, sizeof(fullpath), root, file->relpath);
- BLI_add_slash(fullpath);
- for (; tfsm; tfsm = tfsm->next) {
- if (STREQ(tfsm->path, fullpath)) {
- /* Never want a little folder inside a large one. */
- return (tfsm->icon == ICON_FILE_FOLDER) ? ICON_NONE : tfsm->icon;
+ FSMenuCategory categories[] = {
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ FS_CATEGORY_OTHER,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(categories); i++) {
+ FSMenuEntry *tfsm = ED_fsmenu_get_category(fsmenu, categories[i]);
+ char fullpath[FILE_MAX_LIBEXTRA];
+ BLI_join_dirfile(fullpath, sizeof(fullpath), root, file->relpath);
+ BLI_path_slash_ensure(fullpath);
+ for (; tfsm; tfsm = tfsm->next) {
+ if (STREQ(tfsm->path, fullpath)) {
+ /* Never want a little folder inside a large one. */
+ return (tfsm->icon == ICON_FILE_FOLDER) ? ICON_NONE : tfsm->icon;
+ }
}
}
}
+
+ if (file->attributes & FILE_ATTR_ANY_LINK) {
+ return ICON_LOOP_FORWARDS;
+ }
+ else if (file->attributes & FILE_ATTR_OFFLINE) {
+ return ICON_ERROR;
+ }
+ else if (file->attributes & FILE_ATTR_TEMPORARY) {
+ return ICON_FILE_CACHE;
+ }
+ else if (file->attributes & FILE_ATTR_SYSTEM) {
+ return ICON_SYSTEM;
+ }
}
if (typeflag & FILE_TYPE_BLENDER) {
@@ -1016,6 +1080,9 @@ static int filelist_geticon_ex(FileDirEntry *file, const char *root, const bool
else if (typeflag & FILE_TYPE_USD) {
return ICON_FILE_3D;
}
+ else if (typeflag & FILE_TYPE_VOLUME) {
+ return ICON_FILE_VOLUME;
+ }
else if (typeflag & FILE_TYPE_OBJECT_IO) {
return ICON_FILE_3D;
}
@@ -1043,12 +1110,23 @@ int filelist_geticon(struct FileList *filelist, const int index, const bool is_m
/* ********** Main ********** */
+static void parent_dir_until_exists_or_default_root(char *dir)
+{
+ if (!BLI_path_parent_dir_until_exists(dir)) {
+#ifdef WIN32
+ get_default_root(dir);
+#else
+ strcpy(dir, "/");
+#endif
+ }
+}
+
static bool filelist_checkdir_dir(struct FileList *UNUSED(filelist),
char *r_dir,
const bool do_change)
{
if (do_change) {
- BLI_make_exist(r_dir);
+ parent_dir_until_exists_or_default_root(r_dir);
return true;
}
else {
@@ -1069,7 +1147,7 @@ static bool filelist_checkdir_lib(struct FileList *UNUSED(filelist),
if (do_change && !is_valid) {
/* if not a valid library, we need it to be a valid directory! */
- BLI_make_exist(r_dir);
+ parent_dir_until_exists_or_default_root(r_dir);
return true;
}
return is_valid;
@@ -1092,6 +1170,9 @@ static void filelist_entry_clear(FileDirEntry *entry)
if (entry->relpath) {
MEM_freeN(entry->relpath);
}
+ if (entry->redirection_path) {
+ MEM_freeN(entry->redirection_path);
+ }
if (entry->image) {
IMB_freeImBuf(entry->image);
}
@@ -1161,6 +1242,9 @@ static void filelist_intern_entry_free(FileListInternEntry *entry)
if (entry->relpath) {
MEM_freeN(entry->relpath);
}
+ if (entry->redirection_path) {
+ MEM_freeN(entry->redirection_path);
+ }
if (entry->name) {
MEM_freeN(entry->name);
}
@@ -1180,12 +1264,11 @@ static void filelist_intern_free(FileListIntern *filelist_intern)
MEM_SAFE_FREE(filelist_intern->filtered);
}
-static void filelist_cache_preview_runf(TaskPool *__restrict pool,
- void *taskdata,
- int UNUSED(threadid))
+static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdata)
{
- FileListEntryCache *cache = BLI_task_pool_userdata(pool);
- FileListEntryPreview *preview = taskdata;
+ FileListEntryCache *cache = BLI_task_pool_user_data(pool);
+ FileListEntryPreviewTaskData *preview_taskdata = taskdata;
+ FileListEntryPreview *preview = preview_taskdata->preview;
ThumbSource source = 0;
@@ -1214,37 +1297,33 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool,
preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source);
IMB_thumb_path_unlock(preview->path);
- /* Used to tell free func to not free anything.
- * Note that we do not care about cas result here,
- * we only want value attribution itself to be atomic (and memory barier).*/
- atomic_cas_uint32(&preview->flags, preview->flags, 0);
+ /* That way task freeing function won't free th preview, since it does not own it anymore. */
+ atomic_cas_ptr((void **)&preview_taskdata->preview, preview, NULL);
BLI_thread_queue_push(cache->previews_done, preview);
// printf("%s: End (%d)...\n", __func__, threadid);
}
-static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool),
- void *taskdata,
- int UNUSED(threadid))
+static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), void *taskdata)
{
- FileListEntryPreview *preview = taskdata;
+ FileListEntryPreviewTaskData *preview_taskdata = taskdata;
+ FileListEntryPreview *preview = preview_taskdata->preview;
- /* If preview->flag is empty, it means that preview has already been generated and
- * added to done queue, we do not own it anymore. */
- if (preview->flags) {
+ /* preview_taskdata->preview is atomically set to NULL once preview has been processed and sent
+ * to previews_done queue. */
+ if (preview != NULL) {
if (preview->img) {
IMB_freeImBuf(preview->img);
}
MEM_freeN(preview);
}
+ MEM_freeN(preview_taskdata);
}
static void filelist_cache_preview_ensure_running(FileListEntryCache *cache)
{
if (!cache->previews_pool) {
- TaskScheduler *scheduler = BLI_task_scheduler_get();
-
- cache->previews_pool = BLI_task_pool_create_background(scheduler, cache);
+ cache->previews_pool = BLI_task_pool_create_background(cache, TASK_PRIORITY_LOW);
cache->previews_done = BLI_thread_queue_init();
IMB_thumb_locks_acquire();
@@ -1253,11 +1332,10 @@ static void filelist_cache_preview_ensure_running(FileListEntryCache *cache)
static void filelist_cache_previews_clear(FileListEntryCache *cache)
{
- FileListEntryPreview *preview;
-
if (cache->previews_pool) {
BLI_task_pool_cancel(cache->previews_pool);
+ FileListEntryPreview *preview;
while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) {
// printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path,
// preview->img);
@@ -1305,12 +1383,15 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
filelist_cache_preview_ensure_running(cache);
- BLI_task_pool_push_ex(cache->previews_pool,
- filelist_cache_preview_runf,
- preview,
- true,
- filelist_cache_preview_freef,
- TASK_PRIORITY_LOW);
+
+ FileListEntryPreviewTaskData *preview_taskdata = MEM_mallocN(sizeof(*preview_taskdata),
+ __func__);
+ preview_taskdata->preview = preview;
+ BLI_task_pool_push(cache->previews_pool,
+ filelist_cache_preview_runf,
+ preview_taskdata,
+ true,
+ filelist_cache_preview_freef);
}
}
@@ -1536,7 +1617,7 @@ void filelist_setdir(struct FileList *filelist, char *r_dir)
{
BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
- BLI_cleanup_dir(BKE_main_blendfile_path_from_global(), r_dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path_from_global(), r_dir);
const bool is_valid_path = filelist->checkdirf(filelist, r_dir, true);
BLI_assert(is_valid_path);
UNUSED_VARS_NDEBUG(is_valid_path);
@@ -1607,7 +1688,10 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid));
ret->blentype = entry->blentype;
ret->typeflag = entry->typeflag;
-
+ ret->attributes = entry->attributes;
+ if (entry->redirection_path) {
+ ret->redirection_path = BLI_strdup(entry->redirection_path);
+ }
BLI_addtail(&cache->cached_entries, ret);
return ret;
}
@@ -2129,8 +2213,17 @@ int ED_path_extension_type(const char *path)
else if (BLI_path_extension_check(path, ".py")) {
return FILE_TYPE_PYSCRIPT;
}
- else if (BLI_path_extension_check_n(
- path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) {
+ else if (BLI_path_extension_check_n(path,
+ ".txt",
+ ".glsl",
+ ".osl",
+ ".data",
+ ".pov",
+ ".ini",
+ ".mcr",
+ ".inc",
+ ".fountain",
+ NULL)) {
return FILE_TYPE_TEXT;
}
else if (BLI_path_extension_check_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
@@ -2148,6 +2241,9 @@ int ED_path_extension_type(const char *path)
else if (BLI_path_extension_check_n(path, ".usd", ".usda", ".usdc", NULL)) {
return FILE_TYPE_USD;
}
+ else if (BLI_path_extension_check(path, ".vdb")) {
+ return FILE_TYPE_VOLUME;
+ }
else if (BLI_path_extension_check(path, ".zip")) {
return FILE_TYPE_ARCHIVE;
}
@@ -2210,6 +2306,8 @@ int ED_file_extension_icon(const char *path)
return ICON_FILE_TEXT;
case FILE_TYPE_ARCHIVE:
return ICON_FILE_ARCHIVE;
+ case FILE_TYPE_VOLUME:
+ return ICON_FILE_VOLUME;
default:
return ICON_FILE_BLANK;
}
@@ -2220,16 +2318,16 @@ int filelist_empty(struct FileList *filelist)
return (filelist->filelist.nbr_entries == 0);
}
-unsigned int filelist_entry_select_set(const FileList *filelist,
- const FileDirEntry *entry,
- FileSelType select,
- unsigned int flag,
- FileCheckType check)
+uint filelist_entry_select_set(const FileList *filelist,
+ const FileDirEntry *entry,
+ FileSelType select,
+ uint flag,
+ FileCheckType check)
{
/* Default NULL pointer if not found is fine here! */
void **es_p = BLI_ghash_lookup_p(filelist->selection_state, entry->uuid);
- unsigned int entry_flag = es_p ? POINTER_AS_UINT(*es_p) : 0;
- const unsigned int org_entry_flag = entry_flag;
+ uint entry_flag = es_p ? POINTER_AS_UINT(*es_p) : 0;
+ const uint org_entry_flag = entry_flag;
BLI_assert(entry);
BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
@@ -2268,11 +2366,8 @@ unsigned int filelist_entry_select_set(const FileList *filelist,
return entry_flag;
}
-void filelist_entry_select_index_set(FileList *filelist,
- const int index,
- FileSelType select,
- unsigned int flag,
- FileCheckType check)
+void filelist_entry_select_index_set(
+ FileList *filelist, const int index, FileSelType select, uint flag, FileCheckType check)
{
FileDirEntry *entry = filelist_file(filelist, index);
@@ -2281,11 +2376,8 @@ void filelist_entry_select_index_set(FileList *filelist,
}
}
-void filelist_entries_select_index_range_set(FileList *filelist,
- FileSelection *sel,
- FileSelType select,
- unsigned int flag,
- FileCheckType check)
+void filelist_entries_select_index_range_set(
+ FileList *filelist, FileSelection *sel, FileSelType select, uint flag, FileCheckType check)
{
/* select all valid files between first and last indicated */
if ((sel->first >= 0) && (sel->first < filelist->filelist.nbr_entries_filtered) &&
@@ -2297,9 +2389,7 @@ void filelist_entries_select_index_range_set(FileList *filelist,
}
}
-unsigned int filelist_entry_select_get(FileList *filelist,
- FileDirEntry *entry,
- FileCheckType check)
+uint filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileCheckType check)
{
BLI_assert(entry);
BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
@@ -2313,9 +2403,7 @@ unsigned int filelist_entry_select_get(FileList *filelist,
return 0;
}
-unsigned int filelist_entry_select_index_get(FileList *filelist,
- const int index,
- FileCheckType check)
+uint filelist_entry_select_index_get(FileList *filelist, const int index, FileCheckType check)
{
FileDirEntry *entry = filelist_file(filelist, index);
@@ -2331,7 +2419,7 @@ unsigned int filelist_entry_select_index_get(FileList *filelist,
*/
void filelist_entry_parent_select_set(FileList *filelist,
FileSelType select,
- unsigned int flag,
+ uint flag,
FileCheckType check)
{
if ((filelist->filter_data.flags & FLF_HIDE_PARENT) == 0) {
@@ -2340,9 +2428,9 @@ void filelist_entry_parent_select_set(FileList *filelist,
}
/* WARNING! dir must be FILE_MAX_LIBEXTRA long! */
-bool filelist_islibrary(struct FileList *filelist, char *dir, char **group)
+bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group)
{
- return BLO_library_path_explode(filelist->filelist.root, dir, group, NULL);
+ return BLO_library_path_explode(filelist->filelist.root, dir, r_group, NULL);
}
static int groupname_to_code(const char *group)
@@ -2353,19 +2441,19 @@ static int groupname_to_code(const char *group)
BLI_assert(group);
BLI_strncpy(buf, group, sizeof(buf));
- lslash = (char *)BLI_last_slash(buf);
+ lslash = (char *)BLI_path_slash_rfind(buf);
if (lslash) {
lslash[0] = '\0';
}
- return buf[0] ? BKE_idcode_from_name(buf) : 0;
+ return buf[0] ? BKE_idtype_idcode_from_name(buf) : 0;
}
-static unsigned int groupname_to_filter_id(const char *group)
+static uint64_t groupname_to_filter_id(const char *group)
{
int id_code = groupname_to_code(group);
- return BKE_idcode_to_idfilter(id_code);
+ return BKE_idtype_idcode_to_idfilter(id_code);
}
/**
@@ -2387,6 +2475,7 @@ static int filelist_readjob_list_dir(const char *root,
{
struct direntry *files;
int nbr_files, nbr_entries = 0;
+ char path[FILE_MAX];
nbr_files = BLI_filelist_dir_contents(root, &files);
if (files) {
@@ -2402,20 +2491,17 @@ static int filelist_readjob_list_dir(const char *root,
entry->relpath = MEM_dupallocN(files[i].relname);
entry->st = files[i].s;
+ BLI_join_dirfile(path, sizeof(path), root, entry->relpath);
+
/* Set file type. */
if (S_ISDIR(files[i].s.st_mode)) {
entry->typeflag = FILE_TYPE_DIR;
}
else if (do_lib && BLO_has_bfile_extension(entry->relpath)) {
/* If we are considering .blend files as libs, promote them to directory status. */
- char name[FILE_MAX];
-
entry->typeflag = FILE_TYPE_BLENDER;
-
- BLI_join_dirfile(name, sizeof(name), root, entry->relpath);
-
/* prevent current file being used as acceptable dir */
- if (BLI_path_cmp(main_name, name) != 0) {
+ if (BLI_path_cmp(main_name, path) != 0) {
entry->typeflag |= FILE_TYPE_DIR;
}
}
@@ -2427,6 +2513,26 @@ static int filelist_readjob_list_dir(const char *root,
}
}
+ /* Set file attributes. */
+ entry->attributes = BLI_file_attributes(path);
+ if (entry->attributes & FILE_ATTR_ALIAS) {
+ entry->redirection_path = MEM_callocN(FILE_MAXDIR, __func__);
+ if (BLI_file_alias_target(entry->redirection_path, path)) {
+ if (BLI_is_dir(entry->redirection_path)) {
+ entry->typeflag = FILE_TYPE_DIR;
+ }
+ else
+ entry->typeflag = ED_path_extension_type(entry->redirection_path);
+ }
+ }
+
+#ifndef WIN32
+ /* Set linux-style dot files hidden too. */
+ if (is_hidden_dot_filename(entry->relpath, entry)) {
+ entry->attributes |= FILE_ATTR_HIDDEN;
+ }
+#endif
+
BLI_addtail(entries, entry);
nbr_entries++;
}
@@ -2504,7 +2610,7 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const
/* Kept for reference here, in case we want to add back that feature later.
* We do not need it currently. */
/* Code ***NOT*** updated for job stuff! */
-static void filelist_readjob_main_rec(Main *bmain, FileList *filelist)
+static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist)
{
ID *id;
FileDirEntry *files, *firstlib = NULL;
@@ -2529,9 +2635,9 @@ static void filelist_readjob_main_rec(Main *bmain, FileList *filelist)
if (filelist->dir[0] == 0) {
/* make directories */
# ifdef WITH_FREESTYLE
- filelist->filelist.nbr_entries = 24;
+ filelist->filelist.nbr_entries = 27;
# else
- filelist->filelist.nbr_entries = 23;
+ filelist->filelist.nbr_entries = 26;
# endif
filelist_resize(filelist, filelist->filelist.nbr_entries);
@@ -2562,8 +2668,11 @@ static void filelist_readjob_main_rec(Main *bmain, FileList *filelist)
filelist->filelist.entries[20].entry->relpath = BLI_strdup("Action");
filelist->filelist.entries[21].entry->relpath = BLI_strdup("NodeTree");
filelist->filelist.entries[22].entry->relpath = BLI_strdup("Speaker");
+ filelist->filelist.entries[23].entry->relpath = BLI_strdup("Hair");
+ filelist->filelist.entries[24].entry->relpath = BLI_strdup("Point Cloud");
+ filelist->filelist.entries[25].entry->relpath = BLI_strdup("Volume");
# ifdef WITH_FREESTYLE
- filelist->filelist.entries[23].entry->relpath = BLI_strdup("FreestyleLineStyle");
+ filelist->filelist.entries[26].entry->relpath = BLI_strdup("FreestyleLineStyle");
# endif
}
else {
@@ -2700,7 +2809,7 @@ static void filelist_readjob_do(const bool do_lib,
BLI_strncpy(dir, filelist->filelist.root, sizeof(dir));
BLI_strncpy(filter_glob, filelist->filter_data.filter_glob, sizeof(filter_glob));
- BLI_cleanup_dir(main_name, dir);
+ BLI_path_normalize_dir(main_name, dir);
td_dir->dir = BLI_strdup(dir);
while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) {
@@ -2726,7 +2835,7 @@ static void filelist_readjob_do(const bool do_lib,
* Note that in the end, this means we 'cache' valid relative subdir once here,
* this is actually better. */
BLI_strncpy(rel_subdir, subdir, sizeof(rel_subdir));
- BLI_cleanup_dir(root, rel_subdir);
+ BLI_path_normalize_dir(root, rel_subdir);
BLI_path_rel(rel_subdir, root);
if (do_lib) {
@@ -2768,7 +2877,7 @@ static void filelist_readjob_do(const bool do_lib,
else {
/* We have a directory we want to list, add it to todo list! */
BLI_join_dirfile(dir, sizeof(dir), root, entry->relpath);
- BLI_cleanup_dir(main_name, dir);
+ BLI_path_normalize_dir(main_name, dir);
td_dir = BLI_stack_push_r(todo_dirs);
td_dir->level = recursion_level + 1;
td_dir->dir = BLI_strdup(dir);
@@ -2971,12 +3080,12 @@ void filelist_readjob_start(FileList *filelist, const bContext *C)
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-void filelist_readjob_stop(wmWindowManager *wm, ScrArea *sa)
+void filelist_readjob_stop(wmWindowManager *wm, Scene *owner_scene)
{
- WM_jobs_kill_type(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
+ WM_jobs_kill_type(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR);
}
-int filelist_readjob_running(wmWindowManager *wm, ScrArea *sa)
+int filelist_readjob_running(wmWindowManager *wm, Scene *owner_scene)
{
- return WM_jobs_test(wm, sa, WM_JOB_TYPE_FILESEL_READDIR);
+ return WM_jobs_test(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR);
}
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index 9b1107294ff..e90a8659417 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -62,8 +62,8 @@ void filelist_setfilter_options(struct FileList *filelist,
const bool do_filter,
const bool hide_dot,
const bool hide_parent,
- const unsigned int filter,
- const unsigned int filter_id,
+ const uint64_t filter,
+ const uint64_t filter_id,
const char *filter_glob,
const char *filter_search);
void filelist_filter(struct FileList *filelist);
@@ -125,12 +125,12 @@ void filelist_entry_parent_select_set(struct FileList *filelist,
void filelist_setrecursion(struct FileList *filelist, const int recursion_level);
struct BlendHandle *filelist_lib(struct FileList *filelist);
-bool filelist_islibrary(struct FileList *filelist, char *dir, char **group);
+bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group);
void filelist_freelib(struct FileList *filelist);
void filelist_readjob_start(struct FileList *filelist, const struct bContext *C);
-void filelist_readjob_stop(struct wmWindowManager *wm, struct ScrArea *sa);
-int filelist_readjob_running(struct wmWindowManager *wm, struct ScrArea *sa);
+void filelist_readjob_stop(struct wmWindowManager *wm, struct Scene *owner_scene);
+int filelist_readjob_running(struct wmWindowManager *wm, struct Scene *owner_scene);
bool filelist_cache_previews_update(struct FileList *filelist);
void filelist_cache_previews_set(struct FileList *filelist, const bool use_previews);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 02fb98aa7d7..3b62941af83 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -21,33 +21,34 @@
* \ingroup spfile
*/
-#include <string.h>
-#include <stdio.h>
#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
/* path/file handling stuff */
#ifdef WIN32
-# include <io.h>
-# include <direct.h>
# include "BLI_winstuff.h"
+# include <direct.h>
+# include <io.h>
#else
-# include <unistd.h>
-# include <sys/times.h>
# include <dirent.h>
+# include <sys/times.h>
+# include <unistd.h>
#endif
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_fnmatch.h"
+#include "BLI_math_base.h"
+#include "BLI_utildefines.h"
#include "BLO_readfile.h"
@@ -156,7 +157,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
}
if (params->dir[0]) {
- BLI_cleanup_dir(blendfile_path, params->dir);
+ BLI_path_normalize_dir(blendfile_path, params->dir);
BLI_path_abs(params->dir, blendfile_path);
}
@@ -218,6 +219,9 @@ short ED_fileselect_set_params(SpaceFile *sfile)
if ((prop = RNA_struct_find_property(op->ptr, "filter_usd"))) {
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_USD : 0;
}
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_volume"))) {
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_VOLUME : 0;
+ }
if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
/* Protection against pyscripts not setting proper size limit... */
char *tmp = RNA_property_string_get_alloc(
@@ -413,7 +417,7 @@ void fileselect_file_set(SpaceFile *sfile, const int index)
}
}
-int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar)
+int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *region)
{
int numfiles;
@@ -429,14 +433,14 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar)
*/
if (layout->flag & FILE_LAYOUT_HOR) {
const int x_item = layout->tile_w + (2 * layout->tile_border_x);
- const int x_view = (int)(BLI_rctf_size_x(&ar->v2d.cur));
+ const int x_view = (int)(BLI_rctf_size_x(&region->v2d.cur));
const int x_over = x_item - (x_view % x_item);
numfiles = (int)((float)(x_view + x_over) / (float)(x_item));
return numfiles * layout->rows;
}
else {
const int y_item = layout->tile_h + (2 * layout->tile_border_y);
- const int y_view = (int)(BLI_rctf_size_y(&ar->v2d.cur)) - layout->offset_top;
+ const int y_view = (int)(BLI_rctf_size_y(&region->v2d.cur)) - layout->offset_top;
const int y_over = y_item - (y_view % y_item);
numfiles = (int)((float)(y_view + y_over) / (float)(y_item));
return numfiles * layout->flow_columns;
@@ -639,7 +643,7 @@ FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d,
float file_string_width(const char *str)
{
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
float width;
UI_fontstyle_set(&style->widget);
@@ -661,12 +665,12 @@ float file_font_pointsize(void)
#if 0
float s;
char tmp[2] = "X";
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
UI_fontstyle_set(&style->widget);
s = BLF_height(style->widget.uifont_id, tmp);
return style->widget.points;
#else
- uiStyle *style = UI_style_get();
+ const uiStyle *style = UI_style_get();
UI_fontstyle_set(&style->widget);
return style->widget.points * UI_DPI_FAC;
#endif
@@ -720,11 +724,11 @@ static void file_attribute_columns_init(const FileSelectParams *params, FileLayo
layout->attribute_columns[COLUMN_SIZE].text_align = UI_STYLE_TEXT_RIGHT;
}
-void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
+void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *region)
{
FileSelectParams *params = ED_fileselect_get_params(sfile);
FileLayout *layout = NULL;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
int numfiles;
int textheight;
@@ -755,11 +759,11 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->attribute_column_header_h = 0;
layout->offset_top = 0;
if (layout->flow_columns > 0) {
- layout->rows = numfiles / layout->flow_columns + 1; // XXX dirty, modulo is zero
+ layout->rows = divide_ceil_u(numfiles, layout->flow_columns);
}
else {
layout->flow_columns = 1;
- layout->rows = numfiles + 1; // XXX dirty, modulo is zero
+ layout->rows = numfiles;
}
layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) +
layout->tile_border_y * 2 - layout->offset_top;
@@ -804,11 +808,11 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
file_attribute_columns_init(params, layout);
if (layout->rows > 0) {
- layout->flow_columns = numfiles / layout->rows + 1; // XXX dirty, modulo is zero
+ layout->flow_columns = divide_ceil_u(numfiles, layout->rows);
}
else {
layout->rows = 1;
- layout->flow_columns = numfiles + 1; // XXX dirty, modulo is zero
+ layout->flow_columns = numfiles;
}
layout->width = sfile->layout->flow_columns * (layout->tile_w + 2 * layout->tile_border_x) +
layout->tile_border_x * 2;
@@ -817,10 +821,10 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->dirty = false;
}
-FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *ar)
+FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *region)
{
if (!sfile->layout) {
- ED_fileselect_init_layout(sfile, ar);
+ ED_fileselect_init_layout(sfile, region);
}
return sfile->layout;
}
@@ -829,10 +833,9 @@ void ED_file_change_dir(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- ScrArea *sa = CTX_wm_area(C);
if (sfile->params) {
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
/* Clear search string, it is very rare to want to keep that filter while changing dir,
* and usually very annoying to keep it actually! */
@@ -922,7 +925,7 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
match = UI_autocomplete_end(autocpl, str);
if (match == AUTOCOMPLETE_FULL_MATCH) {
- BLI_add_slash(str);
+ BLI_path_slash_ensure(str);
}
}
}
@@ -951,11 +954,11 @@ int autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
return match;
}
-void ED_fileselect_clear(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
+void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile)
{
/* only NULL in rare cases - [#29734] */
if (sfile->files) {
- filelist_readjob_stop(wm, sa);
+ filelist_readjob_stop(wm, owner_scene);
filelist_freelib(sfile->files);
filelist_clear(sfile->files);
}
@@ -964,7 +967,7 @@ void ED_fileselect_clear(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
-void ED_fileselect_exit(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
+void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile)
{
if (!sfile) {
return;
@@ -990,7 +993,7 @@ void ED_fileselect_exit(wmWindowManager *wm, ScrArea *sa, SpaceFile *sfile)
folderlist_free(sfile->folders_next);
if (sfile->files) {
- ED_fileselect_clear(wm, sa, sfile);
+ ED_fileselect_clear(wm, owner_scene, sfile);
filelist_free(sfile->files);
MEM_freeN(sfile->files);
sfile->files = NULL;
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index eaabd907f23..66157296064 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -21,15 +21,16 @@
* \ingroup spfile
*/
+#include <math.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
-#include <math.h>
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -42,22 +43,22 @@
# include <windows.h>
/* For SHGetSpecialFolderPath, has to be done before BLI_winstuff
* because 'near' is disabled through BLI_windstuff. */
-# include <shlobj.h>
# include "BLI_winstuff.h"
+# include <shlobj.h>
#endif
-#include "WM_api.h"
-#include "WM_types.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "WM_api.h"
+#include "WM_types.h"
#ifdef __APPLE__
# include <Carbon/Carbon.h>
#endif /* __APPLE__ */
#ifdef __linux__
-# include <mntent.h>
# include "BLI_fileops_types.h"
+# include <mntent.h>
#endif
#include "fsmenu.h" /* include ourselves */
@@ -69,6 +70,7 @@ typedef struct FSMenu {
FSMenuEntry *fsmenu_system_bookmarks;
FSMenuEntry *fsmenu_bookmarks;
FSMenuEntry *fsmenu_recent;
+ FSMenuEntry *fsmenu_other;
} FSMenu;
static FSMenu *g_fsmenu = NULL;
@@ -98,10 +100,114 @@ struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory
case FS_CATEGORY_RECENT:
fsm_head = fsmenu->fsmenu_recent;
break;
+ case FS_CATEGORY_OTHER:
+ fsm_head = fsmenu->fsmenu_other;
+ break;
}
return fsm_head;
}
+/* -------------------------------------------------------------------- */
+/** \name XDG User Directory Support (Unix)
+ *
+ * Generic Unix, Use XDG when available, otherwise fallback to the home directory.
+ * \{ */
+
+/**
+ * Look for `user-dirs.dirs`, where localized or custom user folders are defined,
+ * and store their paths in a GHash.
+ */
+static GHash *fsmenu_xdg_user_dirs_parse(const char *home)
+{
+ /* Add to the default for variable, equals & quotes. */
+ char l[128 + FILE_MAXDIR];
+ FILE *fp;
+
+ /* Check if the config file exists. */
+ {
+ char filepath[FILE_MAX];
+ const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
+ if (xdg_config_home != NULL) {
+ BLI_path_join(filepath, sizeof(filepath), xdg_config_home, "user-dirs.dirs", NULL);
+ }
+ else {
+ BLI_path_join(filepath, sizeof(filepath), home, ".config", "user-dirs.dirs", NULL);
+ }
+ fp = BLI_fopen(filepath, "r");
+ if (!fp) {
+ return NULL;
+ }
+ }
+ /* By default there are 8 paths. */
+ GHash *xdg_map = BLI_ghash_str_new_ex(__func__, 8);
+ while (fgets(l, sizeof(l), fp) != NULL) { /* read a line */
+
+ /* Avoid inserting invalid values. */
+ if (STRPREFIX(l, "XDG_")) {
+ char *l_value = strchr(l, '=');
+ if (l_value != NULL) {
+ *l_value = '\0';
+ l_value++;
+
+ BLI_str_rstrip(l_value);
+ const uint l_value_len = strlen(l_value);
+ if ((l_value[0] == '"') && (l_value_len > 0) && (l_value[l_value_len - 1] == '"')) {
+ l_value[l_value_len - 1] = '\0';
+ l_value++;
+
+ char l_value_expanded[FILE_MAX];
+ char *l_value_final = l_value;
+
+ /* This is currently the only variable used.
+ * Based on the 'user-dirs.dirs' man page,
+ * there is no need to resolve arbitrary environment variables. */
+ if (STRPREFIX(l_value, "$HOME" SEP_STR)) {
+ BLI_path_join(l_value_expanded, sizeof(l_value_expanded), home, l_value + 6, NULL);
+ l_value_final = l_value_expanded;
+ }
+
+ BLI_ghash_insert(xdg_map, BLI_strdup(l), BLI_strdup(l_value_final));
+ }
+ }
+ }
+ }
+ return xdg_map;
+}
+
+static void fsmenu_xdg_user_dirs_free(GHash *xdg_map)
+{
+ if (xdg_map != NULL) {
+ BLI_ghash_free(xdg_map, MEM_freeN, MEM_freeN);
+ }
+}
+
+/**
+ * Add fsmenu entry for system folders on linux.
+ * - Check if a path is stored in the GHash generated from user-dirs.dirs
+ * - If not, check for a default path in $HOME
+ *
+ * \param key: Use `user-dirs.dirs` format "XDG_EXAMPLE_DIR"
+ * \param default_path: Directory name to check in $HOME, also used for the menu entry name.
+ */
+static void fsmenu_xdg_insert_entry(GHash *xdg_map,
+ struct FSMenu *fsmenu,
+ const char *key,
+ const char *default_path,
+ int icon,
+ const char *home)
+{
+ char xdg_path_buf[FILE_MAXDIR];
+ const char *xdg_path = xdg_map ? BLI_ghash_lookup(xdg_map, key) : NULL;
+ if (xdg_path == NULL) {
+ BLI_path_join(xdg_path_buf, sizeof(xdg_path_buf), home, default_path, NULL);
+ xdg_path = xdg_path_buf;
+ }
+ fsmenu_insert_entry(
+ fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, xdg_path, IFACE_(default_path), icon, FS_INSERT_LAST);
+}
+
+/** \} */
+
void ED_fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsm_head)
{
switch (category) {
@@ -117,6 +223,9 @@ void ED_fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMe
case FS_CATEGORY_RECENT:
fsmenu->fsmenu_recent = fsm_head;
break;
+ case FS_CATEGORY_OTHER:
+ fsmenu->fsmenu_other = fsm_head;
+ break;
}
}
@@ -158,10 +267,10 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *path)
fsentry->path = (path && path[0]) ? BLI_strdup(path) : NULL;
- BLI_make_file_string("/",
- tmp_name,
- BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
- BLENDER_BOOKMARK_FILE);
+ BLI_join_dirfile(tmp_name,
+ sizeof(tmp_name),
+ BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
fsmenu_write_file(ED_fsmenu_get(), tmp_name);
}
}
@@ -223,10 +332,10 @@ void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name)
BLI_strncpy(fsentry->name, name, sizeof(fsentry->name));
}
- BLI_make_file_string("/",
- tmp_name,
- BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
- BLENDER_BOOKMARK_FILE);
+ BLI_join_dirfile(tmp_name,
+ sizeof(tmp_name),
+ BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL),
+ BLENDER_BOOKMARK_FILE);
fsmenu_write_file(ED_fsmenu_get(), tmp_name);
}
}
@@ -275,6 +384,12 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu,
int icon,
FSMenuInsert flag)
{
+ const uint path_len = strlen(path);
+ BLI_assert(path_len > 0);
+ if (path_len == 0) {
+ return;
+ }
+ const bool has_trailing_slash = (path[path_len - 1] == SEP);
FSMenuEntry *fsm_prev;
FSMenuEntry *fsm_iter;
FSMenuEntry *fsm_head;
@@ -284,8 +399,9 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu,
for (fsm_iter = fsm_head; fsm_iter; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next) {
if (fsm_iter->path) {
- const int cmp_ret = BLI_path_cmp(path, fsm_iter->path);
- if (cmp_ret == 0) {
+ /* Compare, with/without the trailing slash in 'path'. */
+ const int cmp_ret = BLI_path_ncmp(path, fsm_iter->path, path_len);
+ if (cmp_ret == 0 && STREQ(fsm_iter->path + path_len, has_trailing_slash ? "" : SEP_STR)) {
if (flag & FS_INSERT_FIRST) {
if (fsm_iter != fsm_head) {
fsm_prev->next = fsm_iter->next;
@@ -310,14 +426,26 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu,
}
fsm_iter = MEM_mallocN(sizeof(*fsm_iter), "fsme");
- fsm_iter->path = BLI_strdup(path);
+ if (has_trailing_slash) {
+ fsm_iter->path = BLI_strdup(path);
+ }
+ else {
+ fsm_iter->path = BLI_strdupn(path, path_len + 1);
+ fsm_iter->path[path_len] = SEP;
+ fsm_iter->path[path_len + 1] = '\0';
+ }
fsm_iter->save = (flag & FS_INSERT_SAVE) != 0;
/* If entry is also in another list, use that icon and maybe name. */
- if (ELEM(category, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT)) {
-
- FSMenuCategory cats[] = {
- FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS};
+ /* On macOS we get icons and names for System Bookmarks from the FS_CATEGORY_OTHER list. */
+ if (ELEM(category, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT)) {
+
+ const FSMenuCategory cats[] = {
+ FS_CATEGORY_OTHER,
+ FS_CATEGORY_SYSTEM,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ FS_CATEGORY_BOOKMARKS,
+ };
int i = ARRAY_SIZE(cats);
if (category == FS_CATEGORY_BOOKMARKS) {
i--;
@@ -493,6 +621,7 @@ void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename)
#ifdef WIN32
/* Add a Windows known folder path to the System list. */
static void fsmenu_add_windows_folder(struct FSMenu *fsmenu,
+ FSMenuCategory category,
REFKNOWNFOLDERID rfid,
const char *name,
const int icon,
@@ -503,8 +632,7 @@ static void fsmenu_add_windows_folder(struct FSMenu *fsmenu,
if (SHGetKnownFolderPath(rfid, 0, NULL, &pPath) == S_OK) {
BLI_strncpy_wchar_as_utf8(line, pPath, FILE_MAXDIR);
CoTaskMemFree(pPath);
- BLI_add_slash(line);
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, name, icon, flag);
+ fsmenu_insert_entry(fsmenu, category, line, name, icon, flag);
}
}
#endif
@@ -567,27 +695,101 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
/* Get Special Folder Locations. */
if (read_bookmarks) {
+
+ /* These items are shown in System List. */
+ fsmenu_add_windows_folder(fsmenu,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ &FOLDERID_Profile,
+ IFACE_("Home"),
+ ICON_HOME,
+ FS_INSERT_LAST);
+ fsmenu_add_windows_folder(fsmenu,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ &FOLDERID_Desktop,
+ IFACE_("Desktop"),
+ ICON_DESKTOP,
+ FS_INSERT_LAST);
+ fsmenu_add_windows_folder(fsmenu,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ &FOLDERID_Documents,
+ IFACE_("Documents"),
+ ICON_DOCUMENTS,
+ FS_INSERT_LAST);
+ fsmenu_add_windows_folder(fsmenu,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ &FOLDERID_Downloads,
+ IFACE_("Downloads"),
+ ICON_IMPORT,
+ FS_INSERT_LAST);
+ fsmenu_add_windows_folder(fsmenu,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ &FOLDERID_Music,
+ IFACE_("Music"),
+ ICON_FILE_SOUND,
+ FS_INSERT_LAST);
+ fsmenu_add_windows_folder(fsmenu,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ &FOLDERID_Pictures,
+ IFACE_("Pictures"),
+ ICON_FILE_IMAGE,
+ FS_INSERT_LAST);
+ fsmenu_add_windows_folder(fsmenu,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ &FOLDERID_Videos,
+ IFACE_("Videos"),
+ ICON_FILE_MOVIE,
+ FS_INSERT_LAST);
+ fsmenu_add_windows_folder(fsmenu,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ &FOLDERID_Fonts,
+ IFACE_("Fonts"),
+ ICON_FILE_FONT,
+ FS_INSERT_LAST);
+
+ /* These items are just put in path cache for thumbnail views and if bookmarked. */
+
fsmenu_add_windows_folder(
- fsmenu, &FOLDERID_Profile, IFACE_("Home"), ICON_HOME, FS_INSERT_LAST);
- fsmenu_add_windows_folder(
- fsmenu, &FOLDERID_Desktop, IFACE_("Desktop"), ICON_DESKTOP, FS_INSERT_LAST);
- fsmenu_add_windows_folder(
- fsmenu, &FOLDERID_Documents, IFACE_("Documents"), ICON_DOCUMENTS, FS_INSERT_LAST);
- fsmenu_add_windows_folder(
- fsmenu, &FOLDERID_Downloads, IFACE_("Downloads"), ICON_IMPORT, FS_INSERT_LAST);
- fsmenu_add_windows_folder(
- fsmenu, &FOLDERID_Music, IFACE_("Music"), ICON_FILE_SOUND, FS_INSERT_LAST);
- fsmenu_add_windows_folder(
- fsmenu, &FOLDERID_Pictures, IFACE_("Pictures"), ICON_FILE_IMAGE, FS_INSERT_LAST);
- fsmenu_add_windows_folder(
- fsmenu, &FOLDERID_Videos, IFACE_("Videos"), ICON_FILE_MOVIE, FS_INSERT_LAST);
+ fsmenu, FS_CATEGORY_OTHER, &FOLDERID_UserProfiles, NULL, ICON_COMMUNITY, FS_INSERT_LAST);
+
fsmenu_add_windows_folder(
- fsmenu, &FOLDERID_Fonts, IFACE_("Fonts"), ICON_FONTPREVIEW, FS_INSERT_LAST);
+ fsmenu, FS_CATEGORY_OTHER, &FOLDERID_SkyDrive, NULL, ICON_URL, FS_INSERT_LAST);
}
}
#else
# ifdef __APPLE__
{
+ /* We store some known macOS system paths and corresponding icons
+ * and names in the FS_CATEGORY_OTHER (not displayed directly) category. */
+ fsmenu_insert_entry(fsmenu,
+ FS_CATEGORY_OTHER,
+ "/Library/Fonts/",
+ IFACE_("Fonts"),
+ ICON_FILE_FONT,
+ FS_INSERT_LAST);
+ fsmenu_insert_entry(fsmenu,
+ FS_CATEGORY_OTHER,
+ "/Applications/",
+ IFACE_("Applications"),
+ ICON_FILE_FOLDER,
+ FS_INSERT_LAST);
+
+ const char *home = BLI_getenv("HOME");
+
+# define FS_MACOS_PATH(path, name, icon) \
+ BLI_snprintf(line, sizeof(line), path, home); \
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_OTHER, line, name, icon, FS_INSERT_LAST);
+
+ FS_MACOS_PATH("%s/", NULL, ICON_HOME)
+ FS_MACOS_PATH("%s/Desktop/", IFACE_("Desktop"), ICON_DESKTOP)
+ FS_MACOS_PATH("%s/Documents/", IFACE_("Documents"), ICON_DOCUMENTS)
+ FS_MACOS_PATH("%s/Downloads/", IFACE_("Downloads"), ICON_IMPORT)
+ FS_MACOS_PATH("%s/Movies/", IFACE_("Movies"), ICON_FILE_MOVIE)
+ FS_MACOS_PATH("%s/Music/", IFACE_("Music"), ICON_FILE_SOUND)
+ FS_MACOS_PATH("%s/Pictures/", IFACE_("Pictures"), ICON_FILE_IMAGE)
+ FS_MACOS_PATH("%s/Library/Fonts/", IFACE_("Fonts"), ICON_FILE_FONT)
+
+# undef FS_MACOS_PATH
+
/* Get mounted volumes better method OSX 10.6 and higher, see:
* https://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFURLRef/Reference/reference.html
*/
@@ -640,9 +842,6 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
CFRelease(localKey);
}
- /* Add end slash for consistency with other platforms */
- BLI_add_slash(defPath);
-
fsmenu_insert_entry(
fsmenu, FS_CATEGORY_SYSTEM, defPath, name[0] ? name : NULL, icon, FS_INSERT_SORTED);
}
@@ -681,9 +880,6 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
/* Exclude "all my files" as it makes no sense in blender fileselector */
/* Exclude "airdrop" if wlan not active as it would show "" ) */
if (!strstr(line, "myDocuments.cannedSearch") && (*line != '\0')) {
- /* Add end slash for consistency with other platforms */
- BLI_add_slash(line);
-
fsmenu_insert_entry(
fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, ICON_FILE_FOLDER, FS_INSERT_LAST);
}
@@ -703,75 +899,31 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
if (read_bookmarks && home) {
- BLI_snprintf(line, sizeof(line), "%s/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(
- fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, IFACE_("Home"), ICON_HOME, FS_INSERT_LAST);
- }
+ fsmenu_insert_entry(
+ fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, home, IFACE_("Home"), ICON_HOME, FS_INSERT_LAST);
/* Follow the XDG spec, check if these are available. */
-
- /* TODO: parse "$XDG_CONFIG_HOME/user-dirs.dirs" for localized paths. */
-
- BLI_snprintf(line, sizeof(line), "%s/Desktop/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Desktop"),
- ICON_DESKTOP,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Documents/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Documents"),
- ICON_DOCUMENTS,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Downloads/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Downloads"),
- ICON_IMPORT,
- FS_INSERT_LAST);
+ GHash *xdg_map = fsmenu_xdg_user_dirs_parse(home);
+
+ struct {
+ const char *key;
+ const char *default_path;
+ BIFIconID icon;
+ } xdg_items[] = {
+ {"XDG_DESKTOP_DIR", "Desktop", ICON_DESKTOP},
+ {"XDG_DOCUMENTS_DIR", "Documents", ICON_DOCUMENTS},
+ {"XDG_DOWNLOAD_DIR", "Downloads", ICON_IMPORT},
+ {"XDG_VIDEOS_DIR", "Videos", ICON_FILE_MOVIE},
+ {"XDG_PICTURES_DIR", "Pictures", ICON_FILE_IMAGE},
+ {"XDG_MUSIC_DIR", "Music", ICON_FILE_SOUND},
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(xdg_items); i++) {
+ fsmenu_xdg_insert_entry(
+ xdg_map, fsmenu, xdg_items[i].key, xdg_items[i].default_path, xdg_items[i].icon, home);
}
- BLI_snprintf(line, sizeof(line), "%s/Videos/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Videos"),
- ICON_FILE_MOVIE,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Pictures/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Pictures"),
- ICON_FILE_IMAGE,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Music/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Music"),
- ICON_FILE_SOUND,
- FS_INSERT_LAST);
- }
+ fsmenu_xdg_user_dirs_free(xdg_map);
}
{
@@ -779,7 +931,6 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
# ifdef __linux__
/* loop over mount points */
struct mntent *mnt;
- int len;
FILE *fp;
fp = setmntent(MOUNTED, "r");
@@ -801,16 +952,8 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
continue;
}
- len = strlen(mnt->mnt_dir);
- if (len && mnt->mnt_dir[len - 1] != '/') {
- BLI_snprintf(line, sizeof(line), "%s/", mnt->mnt_dir);
- fsmenu_insert_entry(
- fsmenu, FS_CATEGORY_SYSTEM, line, NULL, ICON_DISK_DRIVE, FS_INSERT_SORTED);
- }
- else {
- fsmenu_insert_entry(
- fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, NULL, ICON_DISK_DRIVE, FS_INSERT_SORTED);
- }
+ fsmenu_insert_entry(
+ fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, NULL, ICON_DISK_DRIVE, FS_INSERT_SORTED);
found = 1;
}
@@ -838,7 +981,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
const char *label_test = label + 6;
label = *label_test ? label_test : dirname;
}
- BLI_snprintf(line, sizeof(line), "%s%s/", name, dirname);
+ BLI_snprintf(line, sizeof(line), "%s%s", name, dirname);
fsmenu_insert_entry(
fsmenu, FS_CATEGORY_SYSTEM, line, label, ICON_NETWORK_DRIVE, FS_INSERT_SORTED);
found = 1;
@@ -858,6 +1001,27 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
}
# endif
#endif
+
+#if defined(WIN32) || defined(__APPLE__)
+ /* Quiet warnings. */
+ UNUSED_VARS(fsmenu_xdg_insert_entry, fsmenu_xdg_user_dirs_parse, fsmenu_xdg_user_dirs_free);
+#endif
+
+ /* For all platforms, we add some directories from User Preferences to
+ * the FS_CATEGORY_OTHER category so that these directories
+ * have the appropriate icons when they are added to the Bookmarks. */
+#define FS_UDIR_PATH(dir, icon) \
+ if (BLI_strnlen(dir, 3) > 2) { \
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_OTHER, dir, NULL, icon, FS_INSERT_LAST); \
+ }
+
+ FS_UDIR_PATH(U.fontdir, ICON_FILE_FONT)
+ FS_UDIR_PATH(U.textudir, ICON_FILE_IMAGE)
+ FS_UDIR_PATH(U.pythondir, ICON_FILE_SCRIPT)
+ FS_UDIR_PATH(U.sounddir, ICON_FILE_SOUND)
+ FS_UDIR_PATH(U.tempdir, ICON_TEMP)
+
+#undef FS_UDIR_PATH
}
static void fsmenu_free_category(struct FSMenu *fsmenu, FSMenuCategory category)
@@ -895,6 +1059,7 @@ static void fsmenu_free_ex(FSMenu **fsmenu)
fsmenu_free_category(*fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
fsmenu_free_category(*fsmenu, FS_CATEGORY_BOOKMARKS);
fsmenu_free_category(*fsmenu, FS_CATEGORY_RECENT);
+ fsmenu_free_category(*fsmenu, FS_CATEGORY_OTHER);
MEM_freeN(*fsmenu);
}
@@ -939,6 +1104,7 @@ static FSMenu *fsmenu_copy(FSMenu *fsmenu)
fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_SYSTEM_BOOKMARKS);
fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_BOOKMARKS);
fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_RECENT);
+ fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_OTHER);
return fsmenu_copy;
}
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 17f5a5f7fa0..21b705cbb44 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -21,8 +21,8 @@
* \ingroup spfile
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -31,18 +31,18 @@
#include "BKE_appdir.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "BKE_global.h"
+#include "BKE_screen.h"
#include "RNA_access.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
-#include "ED_space_api.h"
-#include "ED_screen.h"
#include "ED_fileselect.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
#include "IMB_imbuf_types.h"
#include "IMB_thumbs.h"
@@ -50,86 +50,86 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "GPU_framebuffer.h"
#include "file_intern.h" // own include
-#include "fsmenu.h"
#include "filelist.h"
-#include "GPU_framebuffer.h"
+#include "fsmenu.h"
-static ARegion *file_execute_region_ensure(ScrArea *sa, ARegion *ar_prev)
+static ARegion *file_execute_region_ensure(ScrArea *area, ARegion *region_prev)
{
- ARegion *ar;
+ ARegion *region;
- if ((ar = BKE_area_find_region_type(sa, RGN_TYPE_EXECUTE)) != NULL) {
- return ar;
+ if ((region = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE)) != NULL) {
+ return region;
}
- ar = MEM_callocN(sizeof(ARegion), "execute region for file");
- BLI_insertlinkafter(&sa->regionbase, ar_prev, ar);
- ar->regiontype = RGN_TYPE_EXECUTE;
- ar->alignment = RGN_ALIGN_BOTTOM;
- ar->flag = RGN_FLAG_DYNAMIC_SIZE;
+ region = MEM_callocN(sizeof(ARegion), "execute region for file");
+ BLI_insertlinkafter(&area->regionbase, region_prev, region);
+ region->regiontype = RGN_TYPE_EXECUTE;
+ region->alignment = RGN_ALIGN_BOTTOM;
+ region->flag = RGN_FLAG_DYNAMIC_SIZE;
- return ar;
+ return region;
}
-static ARegion *file_tool_props_region_ensure(ScrArea *sa, ARegion *ar_prev)
+static ARegion *file_tool_props_region_ensure(ScrArea *area, ARegion *region_prev)
{
- ARegion *ar;
+ ARegion *region;
- if ((ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS)) != NULL) {
- return ar;
+ if ((region = BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS)) != NULL) {
+ return region;
}
/* add subdiv level; after execute region */
- ar = MEM_callocN(sizeof(ARegion), "tool props for file");
- BLI_insertlinkafter(&sa->regionbase, ar_prev, ar);
- ar->regiontype = RGN_TYPE_TOOL_PROPS;
- ar->alignment = RGN_ALIGN_RIGHT;
+ region = MEM_callocN(sizeof(ARegion), "tool props for file");
+ BLI_insertlinkafter(&area->regionbase, region_prev, region);
+ region->regiontype = RGN_TYPE_TOOL_PROPS;
+ region->alignment = RGN_ALIGN_RIGHT;
- return ar;
+ return region;
}
/* ******************** default callbacks for file space ***************** */
static SpaceLink *file_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceFile *sfile;
sfile = MEM_callocN(sizeof(SpaceFile), "initfile");
sfile->spacetype = SPACE_FILE;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for file");
- BLI_addtail(&sfile->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
+ region = MEM_callocN(sizeof(ARegion), "header for file");
+ BLI_addtail(&sfile->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
/* Ignore user preference "USER_HEADER_BOTTOM" here (always show top for new types). */
- ar->alignment = RGN_ALIGN_TOP;
+ region->alignment = RGN_ALIGN_TOP;
/* Tools region */
- ar = MEM_callocN(sizeof(ARegion), "tools region for file");
- BLI_addtail(&sfile->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOLS;
- ar->alignment = RGN_ALIGN_LEFT;
+ region = MEM_callocN(sizeof(ARegion), "tools region for file");
+ BLI_addtail(&sfile->regionbase, region);
+ region->regiontype = RGN_TYPE_TOOLS;
+ region->alignment = RGN_ALIGN_LEFT;
/* ui list region */
- ar = MEM_callocN(sizeof(ARegion), "ui region for file");
- BLI_addtail(&sfile->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_TOP;
- ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+ region = MEM_callocN(sizeof(ARegion), "ui region for file");
+ BLI_addtail(&sfile->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_TOP;
+ region->flag |= RGN_FLAG_DYNAMIC_SIZE;
/* Tool props and execute region are added as needed, see file_refresh(). */
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for file");
- BLI_addtail(&sfile->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
- ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
- ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
+ region = MEM_callocN(sizeof(ARegion), "main region for file");
+ BLI_addtail(&sfile->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
+ region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ region->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ region->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ region->v2d.keeptot = V2D_KEEPTOT_STRICT;
+ region->v2d.minzoom = region->v2d.maxzoom = 1.0f;
return (SpaceLink *)sfile;
}
@@ -173,25 +173,25 @@ static void file_free(SpaceLink *sl)
}
/* spacetype; init callback, area size changes, screen set, etc */
-static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void file_init(wmWindowManager *UNUSED(wm), ScrArea *area)
{
- SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
+ SpaceFile *sfile = (SpaceFile *)area->spacedata.first;
if (sfile->layout) {
sfile->layout->dirty = true;
}
}
-static void file_exit(wmWindowManager *wm, ScrArea *sa)
+static void file_exit(wmWindowManager *wm, ScrArea *area)
{
- SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
+ SpaceFile *sfile = (SpaceFile *)area->spacedata.first;
if (sfile->previews_timer) {
WM_event_remove_timer_notifier(wm, NULL, sfile->previews_timer);
sfile->previews_timer = NULL;
}
- ED_fileselect_exit(wm, sa, sfile);
+ ED_fileselect_exit(wm, NULL, sfile);
}
static SpaceLink *file_duplicate(SpaceLink *sl)
@@ -228,44 +228,44 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
static void file_ensure_valid_region_state(bContext *C,
wmWindowManager *wm,
wmWindow *win,
- ScrArea *sa,
+ ScrArea *area,
SpaceFile *sfile,
FileSelectParams *params)
{
- ARegion *ar_ui = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- ARegion *ar_props = BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS);
- ARegion *ar_execute = BKE_area_find_region_type(sa, RGN_TYPE_EXECUTE);
+ ARegion *region_ui = BKE_area_find_region_type(area, RGN_TYPE_UI);
+ ARegion *region_props = BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS);
+ ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE);
bool needs_init = false; /* To avoid multiple ED_area_initialize() calls. */
/* If there's an file-operation, ensure we have the option and execute region */
- if (sfile->op && (ar_props == NULL)) {
- ar_execute = file_execute_region_ensure(sa, ar_ui);
- ar_props = file_tool_props_region_ensure(sa, ar_execute);
+ if (sfile->op && (region_props == NULL)) {
+ region_execute = file_execute_region_ensure(area, region_ui);
+ region_props = file_tool_props_region_ensure(area, region_execute);
if (params->flag & FILE_HIDE_TOOL_PROPS) {
- ar_props->flag |= RGN_FLAG_HIDDEN;
+ region_props->flag |= RGN_FLAG_HIDDEN;
}
else {
- ar_props->flag &= ~RGN_FLAG_HIDDEN;
+ region_props->flag &= ~RGN_FLAG_HIDDEN;
}
needs_init = true;
}
/* If there's _no_ file-operation, ensure we _don't_ have the option and execute region */
- else if ((sfile->op == NULL) && (ar_props != NULL)) {
- BLI_assert(ar_execute != NULL);
+ else if ((sfile->op == NULL) && (region_props != NULL)) {
+ BLI_assert(region_execute != NULL);
- ED_region_remove(C, sa, ar_props);
- ED_region_remove(C, sa, ar_execute);
+ ED_region_remove(C, area, region_props);
+ ED_region_remove(C, area, region_execute);
needs_init = true;
}
if (needs_init) {
- ED_area_initialize(wm, win, sa);
+ ED_area_initialize(wm, win, area);
}
}
-static void file_refresh(const bContext *C, ScrArea *sa)
+static void file_refresh(const bContext *C, ScrArea *area)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
@@ -301,7 +301,7 @@ static void file_refresh(const bContext *C, ScrArea *sa)
sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir);
if (filelist_force_reset(sfile->files)) {
- filelist_readjob_stop(wm, sa);
+ filelist_readjob_stop(wm, CTX_data_scene(C));
filelist_clear(sfile->files);
}
@@ -333,34 +333,34 @@ static void file_refresh(const bContext *C, ScrArea *sa)
sfile->layout->dirty = true;
}
- /* Might be called with NULL sa, see file_main_region_draw() below. */
- if (sa) {
- file_ensure_valid_region_state((bContext *)C, wm, win, sa, sfile, params);
+ /* Might be called with NULL area, see file_main_region_draw() below. */
+ if (area) {
+ file_ensure_valid_region_state((bContext *)C, wm, win, area, sfile, params);
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
static void file_listener(wmWindow *UNUSED(win),
- ScrArea *sa,
+ ScrArea *area,
wmNotifier *wmn,
Scene *UNUSED(scene))
{
- SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
+ SpaceFile *sfile = (SpaceFile *)area->spacedata.first;
/* context changes */
switch (wmn->category) {
case NC_SPACE:
switch (wmn->data) {
case ND_SPACE_FILE_LIST:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case ND_SPACE_FILE_PARAMS:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case ND_SPACE_FILE_PREVIEW:
if (sfile->files && filelist_cache_previews_update(sfile->files)) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
break;
}
@@ -369,23 +369,23 @@ static void file_listener(wmWindow *UNUSED(win),
}
/* add handlers, stuff you only do once or on area/region changes */
-static void file_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void file_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
/* own keymaps */
keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "File Browser Main", SPACE_FILE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
static void file_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -394,10 +394,10 @@ static void file_main_region_listener(wmWindow *UNUSED(win),
case NC_SPACE:
switch (wmn->data) {
case ND_SPACE_FILE_LIST:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_SPACE_FILE_PARAMS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -408,18 +408,18 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C),
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
- SpaceFile *sfile = sa->spacedata.first;
+ SpaceFile *sfile = area->spacedata.first;
FileSelectParams *params = ED_fileselect_get_params(sfile);
/* This is a bit odd that a region owns the subscriber for an area,
* keep for now since all subscribers for WM are regions.
* May be worth re-visiting later. */
wmMsgSubscribeValue msg_sub_value_area_tag_refresh = {
- .owner = ar,
- .user_data = sa,
+ .owner = region,
+ .user_data = area,
.notify = ED_area_do_msg_notify_tag_refresh,
};
@@ -442,13 +442,13 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C),
}
}
-static void file_main_region_draw(const bContext *C, ARegion *ar)
+static void file_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
float col[3];
@@ -487,10 +487,10 @@ static void file_main_region_draw(const bContext *C, ARegion *ar)
}
}
/* v2d has initialized flag, so this call will only set the mask correct */
- UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
/* sets tile/border settings in sfile */
- file_calc_previews(C, ar);
+ file_calc_previews(C, region);
/* set view */
UI_view2d_view_ortho(v2d);
@@ -498,10 +498,10 @@ static void file_main_region_draw(const bContext *C, ARegion *ar)
/* on first read, find active file */
if (params->highlight_file == -1) {
wmEvent *event = CTX_wm_window(C)->eventstate;
- file_highlight_set(sfile, ar, event->x, event->y);
+ file_highlight_set(sfile, region, event->x, event->y);
}
- file_draw_list(C, ar);
+ file_draw_list(C, region);
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -541,6 +541,7 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_rename);
WM_operatortype_append(FILE_OT_smoothscroll);
WM_operatortype_append(FILE_OT_filepath_drop);
+ WM_operatortype_append(FILE_OT_start_filter);
}
/* NOTE: do not add .blend file reading on this level */
@@ -556,26 +557,26 @@ static void file_keymap(struct wmKeyConfig *keyconf)
WM_keymap_ensure(keyconf, "File Browser Buttons", SPACE_FILE, 0);
}
-static void file_tools_region_init(wmWindowManager *wm, ARegion *ar)
+static void file_tools_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ED_region_panels_init(wm, region);
/* own keymaps */
keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void file_tools_region_draw(const bContext *C, ARegion *ar)
+static void file_tools_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
static void file_tools_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *UNUSED(ar),
+ ScrArea *UNUSED(area),
+ ARegion *UNUSED(region),
wmNotifier *UNUSED(wmn),
const Scene *UNUSED(scene))
{
@@ -588,62 +589,62 @@ static void file_tools_region_listener(wmWindow *UNUSED(win),
}
/* add handlers, stuff you only do once or on area/region changes */
-static void file_header_region_init(wmWindowManager *wm, ARegion *ar)
+static void file_header_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_header_init(ar);
+ ED_region_header_init(region);
keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void file_header_region_draw(const bContext *C, ARegion *ar)
+static void file_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void file_ui_region_init(wmWindowManager *wm, ARegion *ar)
+static void file_ui_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
- ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
+ ED_region_panels_init(wm, region);
+ region->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "File Browser Buttons", SPACE_FILE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void file_ui_region_draw(const bContext *C, ARegion *ar)
+static void file_ui_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
-static void file_execution_region_init(wmWindowManager *wm, ARegion *ar)
+static void file_execution_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
- ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
+ ED_region_panels_init(wm, region);
+ region->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void file_execution_region_draw(const bContext *C, ARegion *ar)
+static void file_execution_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
static void file_ui_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -652,7 +653,7 @@ static void file_ui_region_listener(wmWindow *UNUSED(win),
case NC_SPACE:
switch (wmn->data) {
case ND_SPACE_FILE_LIST:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -662,7 +663,7 @@ static void file_ui_region_listener(wmWindow *UNUSED(win),
static bool filepath_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
if (drag->type == WM_DRAG_PATH) {
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -801,7 +802,7 @@ void ED_file_read_bookmarks(void)
if (cfgdir) {
char name[FILE_MAX];
- BLI_make_file_string("/", name, cfgdir, BLENDER_BOOKMARK_FILE);
+ BLI_join_dirfile(name, sizeof(name), cfgdir, BLENDER_BOOKMARK_FILE);
fsmenu_read_bookmarks(ED_fsmenu_get(), name);
}
}
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 0a3663372be..ca8919f51a6 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -21,10 +21,10 @@
* \ingroup spgraph
*/
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -32,18 +32,19 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_fcurve.h"
-#include "BKE_main.h"
+#include "BKE_fcurve_driver.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_unit.h"
@@ -111,51 +112,65 @@ static bool graph_panel_poll(const bContext *C, PanelType *UNUSED(pt))
/* -------------- */
-/* Graph Editor View Settings */
-static void graph_panel_view(const bContext *C, Panel *pa)
+static void graph_panel_cursor_header(const bContext *C, Panel *panel)
{
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
SpaceGraph *sipo = CTX_wm_space_graph(C);
Scene *scene = CTX_data_scene(C);
PointerRNA spaceptr, sceneptr;
- uiLayout *col, *sub, *row;
+ uiLayout *col;
/* get RNA pointers for use when creating the UI elements */
RNA_id_pointer_create(&scene->id, &sceneptr);
- RNA_pointer_create(&sc->id, &RNA_SpaceGraphEditor, sipo, &spaceptr);
+ RNA_pointer_create(&screen->id, &RNA_SpaceGraphEditor, sipo, &spaceptr);
/* 2D-Cursor */
- col = uiLayoutColumn(pa->layout, false);
- uiItemR(col, &spaceptr, "show_cursor", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(panel->layout, false);
+ uiItemR(col, &spaceptr, "show_cursor", 0, "", ICON_NONE);
+}
- sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor"));
- uiItemO(sub, IFACE_("Cursor from Selection"), ICON_NONE, "GRAPH_OT_frame_jump");
+static void graph_panel_cursor(const bContext *C, Panel *panel)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ SpaceGraph *sipo = CTX_wm_space_graph(C);
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA spaceptr, sceneptr;
+ uiLayout *layout = panel->layout;
+ uiLayout *col, *sub;
+
+ /* get RNA pointers for use when creating the UI elements */
+ RNA_id_pointer_create(&scene->id, &sceneptr);
+ RNA_pointer_create(&screen->id, &RNA_SpaceGraphEditor, sipo, &spaceptr);
+
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+
+ /* 2D-Cursor */
+ col = uiLayoutColumn(layout, false);
+ uiLayoutSetActive(col, RNA_boolean_get(&spaceptr, "show_cursor"));
sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor"));
- row = uiLayoutSplit(sub, 0.7f, true);
if (sipo->mode == SIPO_MODE_DRIVERS) {
- uiItemR(row, &spaceptr, "cursor_position_x", 0, IFACE_("Cursor X"), ICON_NONE);
+ uiItemR(sub, &spaceptr, "cursor_position_x", 0, IFACE_("Cursor X"), ICON_NONE);
}
else {
- uiItemR(row, &sceneptr, "frame_current", 0, IFACE_("Cursor X"), ICON_NONE);
+ uiItemR(sub, &sceneptr, "frame_current", 0, IFACE_("Cursor X"), ICON_NONE);
}
- uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_CFRA);
- row = uiLayoutSplit(sub, 0.7f, true);
- uiItemR(row, &spaceptr, "cursor_position_y", 0, IFACE_("Cursor Y"), ICON_NONE);
- uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_VALUE);
+ uiItemR(sub, &spaceptr, "cursor_position_y", 0, IFACE_("Y"), ICON_NONE);
+
+ sub = uiLayoutColumn(col, true);
+ uiItemO(sub, IFACE_("Cursor to Selection"), ICON_NONE, "GRAPH_OT_frame_jump");
}
/* ******************* active F-Curve ************** */
-static void graph_panel_properties(const bContext *C, Panel *pa)
+static void graph_panel_properties(const bContext *C, Panel *panel)
{
bAnimListElem *ale;
FCurve *fcu;
PointerRNA fcu_ptr;
- uiLayout *layout = pa->layout;
+ uiLayout *layout = panel->layout;
uiLayout *col;
char name[256];
int icon = 0;
@@ -280,7 +295,7 @@ static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bez
bezt->h2 = HD_ALIGN;
}
else {
- BKE_nurb_bezt_handle_test(bezt, SELECT, true);
+ BKE_nurb_bezt_handle_test(bezt, SELECT, true, false);
}
/* now call standard updates */
@@ -331,16 +346,16 @@ static void graphedit_activekey_right_handle_coord_cb(bContext *C, void *fcu_ptr
bezt->f3 = f3;
}
-static void graph_panel_key_properties(const bContext *C, Panel *pa)
+static void graph_panel_key_properties(const bContext *C, Panel *panel)
{
bAnimListElem *ale;
FCurve *fcu;
BezTriple *bezt, *prevbezt;
- uiLayout *layout = pa->layout;
- const ARegion *ar = CTX_wm_region(C);
+ uiLayout *layout = panel->layout;
+ const ARegion *region = CTX_wm_region(C);
/* Just a width big enough so buttons use entire layout width (will be clamped by it then). */
- const int but_max_width = ar->winx;
+ const int but_max_width = region->winx;
uiLayout *col;
uiBlock *block;
@@ -1213,7 +1228,7 @@ static void graph_draw_driver_settings_panel(uiLayout *layout,
/* Panel to show property driven by the driver (in Drivers Editor) - duplicates Active FCurve,
* but useful for clarity. */
-static void graph_panel_driven_property(const bContext *C, Panel *pa)
+static void graph_panel_driven_property(const bContext *C, Panel *panel)
{
bAnimListElem *ale;
FCurve *fcu;
@@ -1222,14 +1237,14 @@ static void graph_panel_driven_property(const bContext *C, Panel *pa)
return;
}
- graph_draw_driven_property_panel(pa->layout, ale->id, fcu);
+ graph_draw_driven_property_panel(panel->layout, ale->id, fcu);
MEM_freeN(ale);
}
/* driver settings for active F-Curve
* (only for 'Drivers' mode in Graph Editor, i.e. the full "Drivers Editor") */
-static void graph_panel_drivers(const bContext *C, Panel *pa)
+static void graph_panel_drivers(const bContext *C, Panel *panel)
{
bAnimListElem *ale;
FCurve *fcu;
@@ -1239,7 +1254,7 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
return;
}
- graph_draw_driver_settings_panel(pa->layout, ale->id, fcu, false);
+ graph_draw_driver_settings_panel(panel->layout, ale->id, fcu, false);
/* cleanup */
MEM_freeN(ale);
@@ -1255,9 +1270,9 @@ static bool graph_panel_drivers_popover_poll(const bContext *C, PanelType *UNUSE
}
/* popover panel for driver editing anywhere in ui */
-static void graph_panel_drivers_popover(const bContext *C, Panel *pa)
+static void graph_panel_drivers_popover(const bContext *C, Panel *panel)
{
- uiLayout *layout = pa->layout;
+ uiLayout *layout = panel->layout;
PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
@@ -1289,7 +1304,7 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *pa)
/* Driven Property Settings */
uiItemL(layout, IFACE_("Driven Property:"), ICON_NONE);
- graph_draw_driven_property_panel(pa->layout, id, fcu);
+ graph_draw_driven_property_panel(panel->layout, id, fcu);
/* TODO: All vs Single */
uiItemS(layout);
@@ -1297,7 +1312,7 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *pa)
/* Drivers Settings */
uiItemL(layout, IFACE_("Driver Settings:"), ICON_NONE);
- graph_draw_driver_settings_panel(pa->layout, id, fcu, true);
+ graph_draw_driver_settings_panel(panel->layout, id, fcu, true);
}
}
@@ -1320,7 +1335,7 @@ static void do_graph_region_modifier_buttons(bContext *C, void *UNUSED(arg), int
}
}
-static void graph_panel_modifiers(const bContext *C, Panel *pa)
+static void graph_panel_modifiers(const bContext *C, Panel *panel)
{
bAnimListElem *ale;
FCurve *fcu;
@@ -1333,12 +1348,12 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa)
return;
}
- block = uiLayoutGetBlock(pa->layout);
+ block = uiLayoutGetBlock(panel->layout);
UI_block_func_handle_set(block, do_graph_region_modifier_buttons, NULL);
/* 'add modifier' button at top of panel */
{
- row = uiLayoutRow(pa->layout, false);
+ row = uiLayoutRow(panel->layout, false);
/* this is an operator button which calls a 'add modifier' operator...
* a menu might be nicer but would be tricky as we need some custom filtering
@@ -1355,7 +1370,7 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa)
active = !(fcu->flag & FCURVE_MOD_OFF);
/* draw each modifier */
for (fcm = fcu->modifiers.first; fcm; fcm = fcm->next) {
- col = uiLayoutColumn(pa->layout, true);
+ col = uiLayoutColumn(panel->layout, true);
uiLayoutSetActive(col, active);
ANIM_uiTemplate_fmodifier_draw(col, ale->fcurve_owner_id, &fcu->modifiers, fcm);
@@ -1429,9 +1444,10 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view");
strcpy(pt->idname, "GRAPH_PT_view");
- strcpy(pt->label, N_("View Properties"));
+ strcpy(pt->label, N_("Show Cursor"));
strcpy(pt->category, "View");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = graph_panel_view;
+ pt->draw = graph_panel_cursor;
+ pt->draw_header = graph_panel_cursor_header;
BLI_addtail(&art->paneltypes, pt);
}
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 42a1566629a..68fef5e921f 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -20,10 +20,10 @@
* \ingroup spgraph
*/
-#include <stdio.h>
+#include <float.h>
#include <math.h>
+#include <stdio.h>
#include <string.h>
-#include <float.h>
#include "BLI_blenlib.h"
#include "BLI_math.h"
@@ -32,8 +32,8 @@
#include "DNA_anim_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "DNA_windowmanager_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -164,7 +164,7 @@ static void set_fcurve_vertex_color(FCurve *fcu, bool sel)
}
static void draw_fcurve_selected_keyframe_vertices(
- FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos)
+ FCurve *fcu, View2D *v2d, bool edit, bool sel, uint pos)
{
const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
@@ -200,7 +200,7 @@ static void draw_fcurve_selected_keyframe_vertices(
}
/* helper func - draw keyframe vertices only for an F-Curve */
-static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos)
+static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, uint pos)
{
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
@@ -214,7 +214,7 @@ static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, u
/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
static void draw_fcurve_selected_handle_vertices(
- FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos)
+ FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, uint pos)
{
(void)v2d; /* TODO: use this to draw only points in view */
@@ -259,10 +259,7 @@ static void draw_fcurve_selected_handle_vertices(
}
/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
-static void draw_fcurve_handle_vertices(FCurve *fcu,
- View2D *v2d,
- bool sel_handle_only,
- unsigned pos)
+static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, uint pos)
{
/* smooth outlines for more consistent appearance */
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
@@ -277,9 +274,12 @@ static void draw_fcurve_handle_vertices(FCurve *fcu,
immUnbindProgram();
}
-static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool sel_handle_only)
+static void draw_fcurve_vertices(ARegion *region,
+ FCurve *fcu,
+ bool do_handles,
+ bool sel_handle_only)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
/* only draw points if curve is visible
* - Draw unselected points before selected points as separate passes
@@ -343,6 +343,10 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
uint color = GPU_vertformat_attr_add(
format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ GPU_line_smooth(true);
+ }
+ GPU_blend(true);
immBeginAtMost(GPU_PRIM_LINES, 4 * 2 * fcu->totvert);
@@ -353,7 +357,7 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
BezTriple *bezt = fcu->bezt, *prevbezt = NULL;
int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE;
const float *fp;
- unsigned char col[4];
+ uchar col[4];
for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) {
/* if only selected keyframes can get their handles shown,
@@ -419,6 +423,10 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
immEnd();
immUnbindProgram();
+ GPU_blend(false);
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ GPU_line_smooth(false);
+ }
}
/* Samples ---------------- */
@@ -428,7 +436,7 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
* have a consistent appearance (due to off-pixel alignments)...
*/
static void draw_fcurve_sample_control(
- float x, float y, float xscale, float yscale, float hsize, unsigned int pos)
+ float x, float y, float xscale, float yscale, float hsize, uint pos)
{
/* adjust view transform before starting */
GPU_matrix_push();
@@ -449,14 +457,14 @@ static void draw_fcurve_sample_control(
}
/* helper func - draw keyframe vertices only for an F-Curve */
-static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *ar, FCurve *fcu)
+static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *region, FCurve *fcu)
{
FPoint *first, *last;
float hsize, xscale, yscale;
/* get view settings */
hsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
- UI_view2d_scale_get(&ar->v2d, &xscale, &yscale);
+ UI_view2d_scale_get(&region->v2d, &xscale, &yscale);
/* get verts */
first = fcu->fpt;
@@ -491,8 +499,7 @@ static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *ar, FCurve *fcu)
/* Helper func - just draw the F-Curve by sampling the visible region
* (for drawing curves with modifiers). */
-static void draw_fcurve_curve(
- bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, unsigned int pos)
+static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, uint pos)
{
SpaceGraph *sipo = (SpaceGraph *)ac->sl;
float samplefreq;
@@ -684,8 +691,7 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
}
/* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */
-static void draw_fcurve_curve_bezts(
- bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, unsigned int pos)
+static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos)
{
BezTriple *prevbezt = fcu->bezt;
BezTriple *bezt = prevbezt + 1;
@@ -874,7 +880,7 @@ static void draw_fcurve_curve_bezts(
static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
{
ChannelDriver *driver = fcu->driver;
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
short mapping_flag = ANIM_get_normalization_flags(ac);
float offset;
float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
@@ -987,7 +993,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
/* Draw the 'ghost' F-Curves (i.e. snapshots of the curve)
* NOTE: unit mapping has already been applied to the values, so do not try and apply again
*/
-void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar)
+void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region)
{
FCurve *fcu;
@@ -1022,7 +1028,7 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar)
immUniformColor3fvAlpha(fcu->color, 0.5f);
/* simply draw the stored samples */
- draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d, shdr_pos);
+ draw_fcurve_curve_samples(ac, NULL, fcu, &region->v2d, shdr_pos);
}
immUnbindProgram();
@@ -1036,7 +1042,7 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar)
/* This is called twice from space_graph.c -> graph_main_region_draw()
* Unselected then selected F-Curves are drawn so that they do not occlude each other.
*/
-void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, short sel)
+void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, short sel)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -1123,20 +1129,20 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, short se
/* draw a curve affected by modifiers or only allowed to have integer values
* by sampling it at various small-intervals over the visible region
*/
- draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, shdr_pos);
+ draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos);
}
else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
/* just draw curve based on defined data (i.e. no modifiers) */
if (fcu->bezt) {
if (fcurve_can_use_simple_bezt_drawing(fcu)) {
- draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d, shdr_pos);
+ draw_fcurve_curve_bezts(ac, ale->id, fcu, &region->v2d, shdr_pos);
}
else {
- draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, shdr_pos);
+ draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos);
}
}
else if (fcu->fpt) {
- draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d, shdr_pos);
+ draw_fcurve_curve_samples(ac, ale->id, fcu, &region->v2d, shdr_pos);
}
}
@@ -1158,7 +1164,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, short se
if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
switch (fcm->type) {
case FMODIFIER_TYPE_ENVELOPE: /* envelope */
- draw_fcurve_modifier_controls_envelope(fcm, &ar->v2d);
+ draw_fcurve_modifier_controls_envelope(fcm, &region->v2d);
break;
}
}
@@ -1183,16 +1189,14 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, short se
if (do_handles) {
/* only draw handles/vertices on keyframes */
- GPU_blend(true);
draw_fcurve_handles(sipo, fcu);
- GPU_blend(false);
}
- draw_fcurve_vertices(ar, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY));
+ draw_fcurve_vertices(region, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY));
}
else {
/* samples: only draw two indicators at either end as indicators */
- draw_fcurve_samples(sipo, ar, fcu);
+ draw_fcurve_samples(sipo, region, fcu);
}
GPU_matrix_pop();
@@ -1218,13 +1222,13 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, short se
/* Channel List */
/* left hand part */
-void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
+void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
float height;
size_t items;
@@ -1255,7 +1259,7 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
}
}
{ /* second pass: widgets */
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
size_t channel_index = 0;
float ymax = ACHANNEL_FIRST_TOP(ac);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 2060288bb0e..8ffd2844f1a 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -21,10 +21,10 @@
* \ingroup spgraph
*/
+#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <float.h>
#ifdef WITH_AUDASPACE
# include <AUD_Special.h>
@@ -54,16 +54,16 @@
#include "DEG_depsgraph_build.h"
-#include "UI_view2d.h"
#include "UI_interface.h"
+#include "UI_view2d.h"
#include "ED_anim_api.h"
-#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
+#include "ED_keyframing.h"
+#include "ED_markers.h"
#include "ED_numinput.h"
#include "ED_screen.h"
#include "ED_transform.h"
-#include "ED_markers.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -297,9 +297,9 @@ static int graphkeys_viewall(bContext *C,
float pad_top = UI_TIME_SCRUB_MARGIN_Y;
float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ? V2D_SCROLL_HANDLE_HEIGHT :
UI_MARKER_MARGIN_Y;
- BLI_rctf_pad_y(&cur_new, ac.ar->winy, pad_bottom, pad_top);
+ BLI_rctf_pad_y(&cur_new, ac.region->winy, pad_bottom, pad_top);
- UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx);
+ UI_view2d_smooth_view(C, ac.region, &cur_new, smooth_viewtx);
return OPERATOR_FINISHED;
}
@@ -328,7 +328,7 @@ static int graphkeys_view_selected_exec(bContext *C, wmOperator *op)
void GRAPH_OT_view_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->idname = "GRAPH_OT_view_all";
ot->description = "Reset viewable area to show full keyframe range";
@@ -351,7 +351,7 @@ void GRAPH_OT_view_all(wmOperatorType *ot)
void GRAPH_OT_view_selected(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Selected";
+ ot->name = "Frame Selected";
ot->idname = "GRAPH_OT_view_selected";
ot->description = "Reset viewable area to show selected keyframe range";
@@ -486,7 +486,7 @@ static int graphkeys_create_ghostcurves_exec(bContext *C, wmOperator *UNUSED(op)
/* Ghost curves are snapshots of the visible portions of the curves,
* so set range to be the visible range. */
- v2d = &ac.ar->v2d;
+ v2d = &ac.region->v2d;
start = (int)v2d->cur.xmin;
end = (int)v2d->cur.xmax;
@@ -610,7 +610,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
SpaceGraph *sipo = (SpaceGraph *)ac->sl;
Scene *scene = ac->scene;
ToolSettings *ts = scene->toolsettings;
- short flag = 0;
+ eInsertKeyFlags flag = 0;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
@@ -639,8 +639,8 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
return;
}
- /* init keyframing flag */
- flag = ANIM_get_keyframing_flags(scene, 1);
+ /* Init key-framing flag. */
+ flag = ANIM_get_keyframing_flags(scene, true);
/* insert keyframes */
if (mode & GRAPHKEYS_INSERTKEY_CURSOR) {
@@ -871,7 +871,7 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
- ARegion *ar;
+ ARegion *region;
View2D *v2d;
int mval[2];
float x, y;
@@ -882,11 +882,11 @@ static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, const wmEv
}
/* store mouse coordinates in View2D space, into the operator's properties */
- ar = ac.ar;
- v2d = &ar->v2d;
+ region = ac.region;
+ v2d = &region->v2d;
- mval[0] = (event->x - ar->winrct.xmin);
- mval[1] = (event->y - ar->winrct.ymin);
+ mval[0] = (event->x - region->winrct.xmin);
+ mval[1] = (event->y - region->winrct.ymin);
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
@@ -1336,8 +1336,8 @@ static void decimate_graph_keys(bAnimContext *ac, float remove_ratio, float erro
typedef struct tDecimateGraphOp {
bAnimContext ac;
Scene *scene;
- ScrArea *sa;
- ARegion *ar;
+ ScrArea *area;
+ ARegion *region;
/** A 0-1 value for determining how much we should decimate. */
PropertyRNA *percentage_prop;
@@ -1409,7 +1409,7 @@ static void decimate_exit(bContext *C, wmOperator *op)
return;
}
- ScrArea *sa = dgo->sa;
+ ScrArea *area = dgo->area;
LinkData *link;
for (link = dgo->bezt_arr_list.first; link != NULL; link = link->next) {
@@ -1423,7 +1423,7 @@ static void decimate_exit(bContext *C, wmOperator *op)
/* Return to normal cursor and header status. */
WM_cursor_modal_restore(win);
- ED_area_status_text(sa, NULL);
+ ED_area_status_text(area, NULL);
/* cleanup */
op->customdata = NULL;
@@ -1450,7 +1450,7 @@ static void decimate_draw_status_header(wmOperator *op, tDecimateGraphOp *dgo)
status_str, sizeof(status_str), "%s: %d %%", mode_str, (int)(percentage * 100.0f));
}
- ED_area_status_text(dgo->sa, status_str);
+ ED_area_status_text(dgo->area, status_str);
}
/* Calculate percentage based on position of mouse (we only use x-axis for now.
@@ -1460,7 +1460,7 @@ static void decimate_mouse_update_percentage(tDecimateGraphOp *dgo,
wmOperator *op,
const wmEvent *event)
{
- float percentage = (event->x - dgo->ar->winrct.xmin) / ((float)dgo->ar->winx);
+ float percentage = (event->x - dgo->region->winrct.xmin) / ((float)dgo->region->winx);
RNA_property_float_set(op->ptr, dgo->percentage_prop, percentage);
}
@@ -1482,8 +1482,8 @@ static int graphkeys_decimate_invoke(bContext *C, wmOperator *op, const wmEvent
dgo->percentage_prop = RNA_struct_find_property(op->ptr, "remove_ratio");
dgo->scene = CTX_data_scene(C);
- dgo->sa = CTX_wm_area(C);
- dgo->ar = CTX_wm_region(C);
+ dgo->area = CTX_wm_area(C);
+ dgo->region = CTX_wm_region(C);
/* initialise percentage so that it will have the correct value before the first mouse move. */
decimate_mouse_update_percentage(dgo, op, event);
@@ -1576,8 +1576,8 @@ static int graphkeys_decimate_modal(bContext *C, wmOperator *op, const wmEvent *
switch (event->type) {
case LEFTMOUSE: /* confirm */
- case RETKEY:
- case PADENTER: {
+ case EVT_RETKEY:
+ case EVT_PADENTER: {
if (event->val == KM_PRESS) {
decimate_exit(C, op);
@@ -1586,7 +1586,7 @@ static int graphkeys_decimate_modal(bContext *C, wmOperator *op, const wmEvent *
break;
}
- case ESCKEY: /* cancel */
+ case EVT_ESCKEY: /* cancel */
case RIGHTMOUSE: {
if (event->val == KM_PRESS) {
decimate_reset_bezts(dgo);
@@ -2647,7 +2647,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
for (f = 0; f < 3; f++) {
FCurve *fcu = euf->fcurves[f];
BezTriple *bezt, *prev;
- unsigned int i;
+ uint i;
/* skip if not enough vets to do a decent analysis of... */
if (fcu->totvert <= 2) {
@@ -3476,7 +3476,7 @@ static int graph_driver_vars_copy_exec(bContext *C, wmOperator *op)
PointerRNA ptr = CTX_data_pointer_get_type(C, "active_editable_fcurve", &RNA_FCurve);
/* if this exists, call the copy driver vars API function */
- FCurve *fcu = (FCurve *)ptr.data;
+ FCurve *fcu = ptr.data;
if (fcu) {
ok = ANIM_driver_vars_copy(op->reports, fcu);
@@ -3516,7 +3516,7 @@ static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op)
PointerRNA ptr = CTX_data_pointer_get_type(C, "active_editable_fcurve", &RNA_FCurve);
/* if this exists, call the paste driver vars API function */
- FCurve *fcu = (FCurve *)ptr.data;
+ FCurve *fcu = ptr.data;
if (fcu) {
ok = ANIM_driver_vars_paste(op->reports, fcu, replace);
@@ -3569,7 +3569,7 @@ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op)
bAnimListElem *ale;
int filter;
bool ok = false;
- unsigned int deleted = 0;
+ uint deleted = 0;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0) {
@@ -3623,10 +3623,10 @@ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op)
static bool graph_driver_delete_invalid_poll(bContext *C)
{
bAnimContext ac;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* firstly, check if in Graph Editor */
- if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) {
+ if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
return 0;
}
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index abd8d2db04a..3ec36e43278 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -35,13 +35,15 @@ struct bContext;
/* ***************************************** */
/* graph_draw.c */
-void graph_draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *ar);
+void graph_draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *region);
void graph_draw_curves(struct bAnimContext *ac,
struct SpaceGraph *sipo,
- struct ARegion *ar,
+ struct ARegion *region,
short sel);
-void graph_draw_ghost_curves(struct bAnimContext *ac, struct SpaceGraph *sipo, struct ARegion *ar);
+void graph_draw_ghost_curves(struct bAnimContext *ac,
+ struct SpaceGraph *sipo,
+ struct ARegion *region);
/* ***************************************** */
/* graph_select.c */
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 17cf5dca594..de25a2d990d 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -21,14 +21,14 @@
* \ingroup spgraph
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math_base.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -38,10 +38,10 @@
#include "ED_anim_api.h"
#include "ED_markers.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_transform.h"
-#include "ED_object.h"
#include "graph_intern.h"
@@ -129,16 +129,16 @@ static int graphview_cursor_exec(bContext *C, wmOperator *op)
/* set the operator properties from the initial event */
static void graphview_cursor_setprops(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float viewx, viewy;
/* abort if not active region (should not really be possible) */
- if (ar == NULL) {
+ if (region == NULL) {
return;
}
/* convert from region coordinates to View2D 'tot' space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
/* store the values in the operator properties */
/* NOTE: we don't clamp frame here, as it might be used for the drivers cursor */
@@ -176,7 +176,7 @@ static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *ev
/* execute the events */
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
if (screen) {
screen->scrubbing = false;
}
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 9c1d63ef68a..ae435b5624a 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -20,29 +20,29 @@
* \ingroup spgraph
*/
+#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <float.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_lasso_2d.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_lasso_2d.h"
#include "DNA_anim_types.h"
-#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
-#include "BKE_context.h"
#include "UI_view2d.h"
@@ -179,7 +179,7 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
int filter;
SpaceGraph *sipo = (SpaceGraph *)ac->sl;
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
short mapping_flag = 0;
/* get curves to search through
@@ -521,7 +521,7 @@ static void box_select_graphkeys(bAnimContext *ac,
SpaceGraph *sipo = (SpaceGraph *)ac->sl;
KeyframeEditData ked;
KeyframeEditFunc ok_cb, select_cb;
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
rctf rectf, scaled_rectf;
/* Convert mouse coordinates to frame ranges and
@@ -724,13 +724,17 @@ void GRAPH_OT_select_box(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
- RNA_def_boolean(ot->srna,
- "include_handles",
- true,
- "Include Handles",
- "Are handles tested individually against the selection criteria");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(ot->srna,
+ "include_handles",
+ true,
+ "Include Handles",
+ "Are handles tested individually against the selection criteria");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- PropertyRNA *prop = RNA_def_boolean(
+ prop = RNA_def_boolean(
ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a tweak event");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
@@ -756,8 +760,8 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
}
data_lasso.rectf_view = &rect_fl;
- data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot);
- if (data_lasso.mcords == NULL) {
+ data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len);
+ if (data_lasso.mcoords == NULL) {
return OPERATOR_CANCELLED;
}
@@ -778,13 +782,13 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
}
/* get settings from operator */
- BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
+ BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len);
BLI_rctf_rcti_copy(&rect_fl, &rect);
/* apply box_select action */
box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso);
- MEM_freeN((void *)data_lasso.mcords);
+ MEM_freeN((void *)data_lasso.mcoords);
/* send notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -1366,8 +1370,8 @@ static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const
/* handle mode-based testing */
if (leftright == GRAPHKEYS_LRSEL_TEST) {
Scene *scene = ac.scene;
- ARegion *ar = ac.ar;
- View2D *v2d = &ar->v2d;
+ ARegion *region = ac.region;
+ View2D *v2d = &region->v2d;
float x;
/* determine which side of the current frame mouse is on */
@@ -1481,7 +1485,7 @@ static int mouse_graph_keys(bAnimContext *ac,
if (!curves_only && ((nvi->fcu->flag & FCURVE_PROTECTED) == 0)) {
/* only if there's keyframe */
if (nvi->bezt) {
- bezt = nvi->bezt; /* used to check bezt seletion is set */
+ bezt = nvi->bezt; /* Used to check `bezt` selection is set. */
/* depends on selection mode */
if (select_mode == SELECT_INVERT) {
if (nvi->hpoint == NEAREST_HANDLE_KEY) {
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index b95ab48189c..575cba07f04 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -21,14 +21,14 @@
* \ingroup spgraph
*/
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_anim_types.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "MEM_guardedalloc.h"
@@ -54,40 +54,40 @@
/* Set up UI configuration for Drivers Editor */
/* NOTE: Currently called from windowmanager
* (new drivers editor window) and RNA (mode switching) */
-void ED_drivers_editor_init(bContext *C, ScrArea *sa)
+void ED_drivers_editor_init(bContext *C, ScrArea *area)
{
- SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first;
/* Set mode */
sipo->mode = SIPO_MODE_DRIVERS;
/* Show Properties Region (or else the settings can't be edited) */
- ARegion *ar_props = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar_props) {
- UI_panel_category_active_set(ar_props, "Drivers");
+ ARegion *region_props = BKE_area_find_region_type(area, RGN_TYPE_UI);
+ if (region_props) {
+ UI_panel_category_active_set(region_props, "Drivers");
- ar_props->flag &= ~RGN_FLAG_HIDDEN;
+ region_props->flag &= ~RGN_FLAG_HIDDEN;
/* XXX: Adjust width of this too? */
- ED_region_visibility_change_update(C, sa, ar_props);
+ ED_region_visibility_change_update(C, area, region_props);
}
else {
- printf("%s: Couldn't find properties region for Drivers Editor - %p\n", __func__, sa);
+ printf("%s: Couldn't find properties region for Drivers Editor - %p\n", __func__, area);
}
/* Adjust framing in graph region */
/* TODO: Have a way of not resetting this every time?
* (e.g. So that switching back and forth between editors doesn't keep jumping?)
*/
- ARegion *ar_main = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar_main) {
+ ARegion *region_main = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+ if (region_main) {
/* XXX: Ideally we recenter based on the range instead... */
- ar_main->v2d.tot.xmin = -2.0f;
- ar_main->v2d.tot.ymin = -2.0f;
- ar_main->v2d.tot.xmax = 2.0f;
- ar_main->v2d.tot.ymax = 2.0f;
+ region_main->v2d.tot.xmin = -2.0f;
+ region_main->v2d.tot.ymin = -2.0f;
+ region_main->v2d.tot.xmax = 2.0f;
+ region_main->v2d.tot.ymax = 2.0f;
- ar_main->v2d.cur = ar_main->v2d.tot;
+ region_main->v2d.cur = region_main->v2d.tot;
}
}
@@ -135,14 +135,14 @@ bool graphop_visible_keyframes_poll(bContext *C)
bAnimContext ac;
bAnimListElem *ale;
ListBase anim_data = {NULL, NULL};
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
size_t items;
int filter;
short found = 0;
/* firstly, check if in Graph Editor */
// TODO: also check for region?
- if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) {
+ if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
return 0;
}
@@ -188,14 +188,14 @@ bool graphop_editable_keyframes_poll(bContext *C)
bAnimContext ac;
bAnimListElem *ale;
ListBase anim_data = {NULL, NULL};
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
size_t items;
int filter;
short found = 0;
/* firstly, check if in Graph Editor */
// TODO: also check for region?
- if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) {
+ if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
return 0;
}
@@ -241,12 +241,12 @@ bool graphop_active_fcurve_poll(bContext *C)
{
bAnimContext ac;
bAnimListElem *ale;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
bool has_fcurve = 0;
/* firstly, check if in Graph Editor */
// TODO: also check for region?
- if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) {
+ if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
return 0;
}
@@ -293,13 +293,13 @@ bool graphop_selected_fcurve_poll(bContext *C)
{
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
size_t items;
int filter;
/* firstly, check if in Graph Editor */
// TODO: also check for region?
- if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) {
+ if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
return 0;
}
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index d01e4112fd0..bd82b8ecf2e 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -21,8 +21,8 @@
* \ingroup spgraph
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "DNA_anim_types.h"
#include "DNA_collection_types.h"
@@ -38,35 +38,35 @@
#include "BKE_fcurve.h"
#include "BKE_screen.h"
-#include "ED_space_api.h"
-#include "ED_screen.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
#include "ED_time_scrub_ui.h"
+#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_state.h"
-#include "GPU_framebuffer.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "UI_interface.h"
#include "graph_intern.h" // own include
/* ******************** default callbacks for ipo space ***************** */
-static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene)
+static SpaceLink *graph_new(const ScrArea *UNUSED(area), const Scene *scene)
{
- ARegion *ar;
+ ARegion *region;
SpaceGraph *sipo;
/* Graph Editor - general stuff */
@@ -84,52 +84,52 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene)
sipo->flag |= SIPO_SELVHANDLESONLY | SIPO_SHOW_MARKERS;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for graphedit");
+ region = MEM_callocN(sizeof(ARegion), "header for graphedit");
- BLI_addtail(&sipo->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&sipo->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* channels */
- ar = MEM_callocN(sizeof(ARegion), "channels region for graphedit");
+ region = MEM_callocN(sizeof(ARegion), "channels region for graphedit");
- BLI_addtail(&sipo->regionbase, ar);
- ar->regiontype = RGN_TYPE_CHANNELS;
- ar->alignment = RGN_ALIGN_LEFT;
+ BLI_addtail(&sipo->regionbase, region);
+ region->regiontype = RGN_TYPE_CHANNELS;
+ region->alignment = RGN_ALIGN_LEFT;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
/* ui buttons */
- ar = MEM_callocN(sizeof(ARegion), "buttons region for graphedit");
+ region = MEM_callocN(sizeof(ARegion), "buttons region for graphedit");
- BLI_addtail(&sipo->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_RIGHT;
- ar->flag = RGN_FLAG_HIDDEN;
+ BLI_addtail(&sipo->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_RIGHT;
+ region->flag = RGN_FLAG_HIDDEN;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for graphedit");
+ region = MEM_callocN(sizeof(ARegion), "main region for graphedit");
- BLI_addtail(&sipo->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sipo->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.tot.xmin = 0.0f;
- ar->v2d.tot.ymin = (float)scene->r.sfra - 10.0f;
- ar->v2d.tot.xmax = (float)scene->r.efra;
- ar->v2d.tot.ymax = 10.0f;
+ region->v2d.tot.xmin = 0.0f;
+ region->v2d.tot.ymin = (float)scene->r.sfra - 10.0f;
+ region->v2d.tot.xmax = (float)scene->r.efra;
+ region->v2d.tot.ymax = 10.0f;
- ar->v2d.cur = ar->v2d.tot;
+ region->v2d.cur = region->v2d.tot;
- ar->v2d.min[0] = FLT_MIN;
- ar->v2d.min[1] = FLT_MIN;
+ region->v2d.min[0] = FLT_MIN;
+ region->v2d.min[1] = FLT_MIN;
- ar->v2d.max[0] = MAXFRAMEF;
- ar->v2d.max[1] = FLT_MAX;
+ region->v2d.max[0] = MAXFRAMEF;
+ region->v2d.max[1] = FLT_MAX;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
+ region->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ region->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
- ar->v2d.keeptot = 0;
+ region->v2d.keeptot = 0;
return (SpaceLink *)sipo;
}
@@ -150,9 +150,9 @@ static void graph_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void graph_init(struct wmWindowManager *wm, ScrArea *sa)
+static void graph_init(struct wmWindowManager *wm, ScrArea *area)
{
- SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first;
/* init dopesheet data if non-existent (i.e. for old files) */
if (sipo->ads == NULL) {
@@ -165,7 +165,7 @@ static void graph_init(struct wmWindowManager *wm, ScrArea *sa)
* as this is run on each region resize; setting this here will cause selection
* state to be lost on area/region resizing. [#35744]
*/
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
static SpaceLink *graph_duplicate(SpaceLink *sl)
@@ -180,26 +180,26 @@ static SpaceLink *graph_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void graph_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void graph_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor", SPACE_GRAPH, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void graph_main_region_draw(const bContext *C, ARegion *ar)
+static void graph_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceGraph *sipo = CTX_wm_space_graph(C);
Scene *scene = CTX_data_scene(C);
bAnimContext ac;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
float col[3];
short cfra_flag = 0;
@@ -216,7 +216,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_draw_lines_x__frames_or_seconds(v2d, scene, display_seconds);
UI_view2d_draw_lines_y__values(v2d);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
/* start and end frame (in F-Curve mode only) */
if (sipo->mode != SIPO_MODE_DRIVERS) {
@@ -226,11 +226,11 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
/* draw data */
if (ANIM_animdata_get_context(C, &ac)) {
/* draw ghost curves */
- graph_draw_ghost_curves(&ac, sipo, ar);
+ graph_draw_ghost_curves(&ac, sipo, region);
/* draw curves twice - unselected, then selected, so that the are fewer occlusion problems */
- graph_draw_curves(&ac, sipo, ar, 0);
- graph_draw_curves(&ac, sipo, ar, 1);
+ graph_draw_curves(&ac, sipo, region, 0);
+ graph_draw_curves(&ac, sipo, region, 1);
/* XXX the slow way to set tot rect... but for nice sliders needed (ton) */
get_graph_keyframe_extents(
@@ -294,7 +294,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
/* markers */
if (sipo->mode != SIPO_MODE_DRIVERS) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ UI_view2d_view_orthoSpecial(region, v2d, 1);
int marker_draw_flag = DRAW_MARKERS_MARGIN;
if (sipo->flag & SIPO_SHOW_MARKERS) {
ED_markers_draw(C, marker_draw_flag);
@@ -309,13 +309,13 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
/* callback */
UI_view2d_view_ortho(v2d);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
/* reset view matrix */
UI_view2d_view_restore(C);
/* time-scrubbing */
- ED_time_scrub_draw(ar, scene, display_seconds, false);
+ ED_time_scrub_draw(region, scene, display_seconds, false);
/* scrollers */
// FIXME: args for scrollers depend on the type of data being shown...
@@ -326,37 +326,38 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
/* scale numbers */
{
rcti rect;
- BLI_rcti_init(&rect, 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, ar->winy - UI_TIME_SCRUB_MARGIN_Y);
- UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_SCROLL_TEXT);
+ BLI_rcti_init(
+ &rect, 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, region->winy - UI_TIME_SCRUB_MARGIN_Y);
+ UI_view2d_draw_scale_y__values(region, v2d, &rect, TH_SCROLL_TEXT);
}
}
-static void graph_channel_region_init(wmWindowManager *wm, ARegion *ar)
+static void graph_channel_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
/* make sure we keep the hide flags */
- ar->v2d.scroll |= V2D_SCROLL_RIGHT;
+ region->v2d.scroll |= V2D_SCROLL_RIGHT;
/* prevent any noise of past */
- ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM);
+ region->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM);
- ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
+ region->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ region->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void graph_channel_region_draw(const bContext *C, ARegion *ar)
+static void graph_channel_region_draw(const bContext *C, ARegion *region)
{
bAnimContext ac;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
float col[3];
@@ -369,11 +370,11 @@ static void graph_channel_region_draw(const bContext *C, ARegion *ar)
/* draw channels */
if (ANIM_animdata_get_context(C, &ac)) {
- graph_draw_channel_names((bContext *)C, &ac, ar);
+ graph_draw_channel_names((bContext *)C, &ac, region);
}
/* channel filter next to scrubbing area */
- ED_time_scrub_channel_search_draw(C, ar, ac.ads);
+ ED_time_scrub_channel_search_draw(C, region, ac.ads);
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -385,42 +386,42 @@ static void graph_channel_region_draw(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void graph_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void graph_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void graph_header_region_draw(const bContext *C, ARegion *ar)
+static void graph_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar)
+static void graph_buttons_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void graph_buttons_region_draw(const bContext *C, ARegion *ar)
+static void graph_buttons_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
static void graph_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_SCENE:
switch (wmn->data) {
@@ -429,11 +430,11 @@ static void graph_region_listener(wmWindow *UNUSED(win),
case ND_FRAME:
case ND_FRAME_RANGE:
case ND_MARKERS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_SEQUENCER:
if (wmn->action == NA_SELECTED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -443,11 +444,11 @@ static void graph_region_listener(wmWindow *UNUSED(win),
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
case ND_KEYS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_MODIFIER:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -456,23 +457,23 @@ static void graph_region_listener(wmWindow *UNUSED(win),
switch (wmn->action) {
case NA_EDITED:
case NA_SELECTED:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
default:
if (wmn->data == ND_KEYS) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -482,16 +483,16 @@ static void graph_region_message_subscribe(const struct bContext *UNUSED(C),
struct WorkSpace *UNUSED(workspace),
struct Scene *scene,
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceGraphEditor, sa->spacedata.first, &ptr);
+ RNA_pointer_create(&screen->id, &RNA_SpaceGraphEditor, area->spacedata.first, &ptr);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -555,11 +556,11 @@ static void graph_region_message_subscribe(const struct bContext *UNUSED(C),
/* editor level listener */
static void graph_listener(wmWindow *UNUSED(win),
- ScrArea *sa,
+ ScrArea *area,
wmNotifier *wmn,
Scene *UNUSED(scene))
{
- SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first;
/* context changes */
switch (wmn->category) {
@@ -567,10 +568,10 @@ static void graph_listener(wmWindow *UNUSED(win),
/* for selection changes of animation data, we can just redraw...
* otherwise autocolor might need to be done again */
if (ELEM(wmn->data, ND_KEYFRAME, ND_ANIMCHAN) && (wmn->action == NA_SELECTED)) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
else {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
break;
case NC_SCENE:
@@ -579,11 +580,11 @@ static void graph_listener(wmWindow *UNUSED(win),
* (needs flag set to do syncing). */
case ND_OB_SELECT:
sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
default: /* just redrawing the view will do */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
break;
@@ -593,13 +594,13 @@ static void graph_listener(wmWindow *UNUSED(win),
* (needs flag set to do syncing). */
case ND_BONE_ACTIVE:
sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case ND_TRANSFORM:
break; /*do nothing*/
default: /* just redrawing the view will do */
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
break;
@@ -607,26 +608,26 @@ static void graph_listener(wmWindow *UNUSED(win),
if (wmn->action == NA_SELECTED) {
/* selection changed, so force refresh to flush (needs flag set to do syncing) */
sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_GRAPH) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
case NC_WINDOW:
if (sipo->runtime.flag &
(SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC | SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR)) {
/* force redraw/refresh after undo/redo - prevents "black curve" problem */
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
break;
// XXX: restore the case below if not enough updates occur...
// default:
// if (wmn->data == ND_KEYS)
- // ED_area_tag_redraw(sa);
+ // ED_area_tag_redraw(area);
}
}
@@ -753,9 +754,9 @@ static void graph_refresh_fcurve_colors(const bContext *C)
ANIM_animdata_freelist(&anim_data);
}
-static void graph_refresh(const bContext *C, ScrArea *sa)
+static void graph_refresh(const bContext *C, ScrArea *area)
{
- SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first;
/* updates to data needed depends on Graph Editor mode... */
switch (sipo->mode) {
@@ -779,7 +780,7 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC) {
ANIM_sync_animchannels_to_data(C);
sipo->runtime.flag &= ~SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC;
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
/* We could check 'SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR', but color is recalculated anyway. */
@@ -788,7 +789,7 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
#if 0 /* Done below. */
graph_refresh_fcurve_colors(C);
#endif
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
sipo->runtime.flag &= ~(SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT |
@@ -798,7 +799,7 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
graph_refresh_fcurve_colors(C);
}
-static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void graph_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceGraph *sgraph = (SpaceGraph *)slink;
@@ -812,15 +813,15 @@ static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
}
}
-static int graph_space_subtype_get(ScrArea *sa)
+static int graph_space_subtype_get(ScrArea *area)
{
- SpaceGraph *sgraph = sa->spacedata.first;
+ SpaceGraph *sgraph = area->spacedata.first;
return sgraph->mode;
}
-static void graph_space_subtype_set(ScrArea *sa, int value)
+static void graph_space_subtype_set(ScrArea *area, int value)
{
- SpaceGraph *sgraph = sa->spacedata.first;
+ SpaceGraph *sgraph = area->spacedata.first;
sgraph->mode = value;
}
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index 5abcff436f1..12de74c6ae7 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -43,6 +43,7 @@ set(SRC
image_draw.c
image_edit.c
image_ops.c
+ image_sequence.c
image_undo.c
space_image.c
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 270fe0c59dc..6f3ef44fe94 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -21,8 +21,8 @@
* \ingroup spimage
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
@@ -37,8 +37,8 @@
#include "BKE_context.h"
#include "BKE_image.h"
#include "BKE_node.h"
-#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "RE_pipeline.h"
@@ -47,8 +47,8 @@
#include "IMB_imbuf_types.h"
#include "ED_gpencil.h"
-#include "ED_screen.h"
#include "ED_image.h"
+#include "ED_screen.h"
#include "RNA_access.h"
@@ -656,8 +656,8 @@ static void uiblock_layer_pass_buttons(
/* pass */
rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass) : NULL);
- if (rpass && RE_passes_have_name(rl)) {
- display_name = rpass->name;
+ if (rl && RE_passes_have_name(rl)) {
+ display_name = rpass ? rpass->name : "";
rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
but = uiDefMenuBut(block,
ui_imageuser_pass_menu,
@@ -980,6 +980,16 @@ void uiTemplateImage(uiLayout *layout,
bool is_data = IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name);
uiLayoutSetActive(sub, !is_data);
}
+
+ if (ima && iuser) {
+ void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
+
+ if (ibuf && ibuf->rect_float && (ibuf->flags & IB_halffloat) == 0) {
+ uiItemR(col, &imaptr, "use_half_precision", 0, NULL, ICON_NONE);
+ }
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ }
}
uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
@@ -1266,7 +1276,7 @@ void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *i
}
else if (ima->source == IMA_SRC_SEQUENCE && ibuf) {
/* Image sequence frame number + filename */
- const char *filename = BLI_last_slash(ibuf->name);
+ const char *filename = BLI_path_slash_rfind(ibuf->name);
filename = (filename == NULL) ? ibuf->name : filename + 1;
BLI_snprintf(str, MAX_IMAGE_INFO_LEN, TIP_("Frame %d: %s"), framenr, filename);
}
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 3f563fe9033..6037c1d2ec8 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -27,26 +27,26 @@
#include "MEM_guardedalloc.h"
+#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
+#include "DNA_mask_types.h"
#include "DNA_object_types.h"
-#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_mask_types.h"
+#include "DNA_space_types.h"
#include "PIL_time.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_threads.h"
#include "BLI_string.h"
+#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "IMB_colormanagement.h"
#include "IMB_moviecache.h"
#include "BKE_context.h"
@@ -72,13 +72,13 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "RE_pipeline.h"
#include "RE_engine.h"
+#include "RE_pipeline.h"
#include "image_intern.h"
static void draw_render_info(
- const bContext *C, Scene *scene, Image *ima, ARegion *ar, float zoomx, float zoomy)
+ const bContext *C, Scene *scene, Image *ima, ARegion *region, float zoomx, float zoomy)
{
Render *re = RE_GetSceneRender(scene);
RenderData *rd = RE_engine_get_render_data(re);
@@ -91,7 +91,7 @@ static void draw_render_info(
if (rr && rr->text) {
float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
- ED_region_info_draw(ar, rr->text, fill_color, true);
+ ED_region_info_draw(region, rr->text, fill_color, true);
}
BKE_image_release_renderresult(stats_scene, ima);
@@ -104,7 +104,7 @@ static void draw_render_info(
if (total_tiles) {
/* find window pixel coordinates of origin */
int x, y;
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &x, &y);
GPU_matrix_push();
GPU_matrix_translate_2f(x, y);
@@ -141,13 +141,13 @@ static void draw_render_info(
/* used by node view too */
void ED_image_draw_info(Scene *scene,
- ARegion *ar,
+ ARegion *region,
bool color_manage,
bool use_default_view,
int channels,
int x,
int y,
- const unsigned char cp[4],
+ const uchar cp[4],
const float fp[4],
const float linearcol[4],
int *zp,
@@ -157,20 +157,20 @@ void ED_image_draw_info(Scene *scene,
char str[256];
int dx = 6;
/* local coordinate visible rect inside region, to accommodate overlapping ui */
- const rcti *rect = ED_region_visible_rect(ar);
+ const rcti *rect = ED_region_visible_rect(region);
const int ymin = rect->ymin;
const int dy = ymin + 0.3f * UI_UNIT_Y;
/* text colors */
/* XXX colored text not allowed in Blender UI */
#if 0
- unsigned char red[3] = {255, 50, 50};
- unsigned char green[3] = {0, 255, 0};
- unsigned char blue[3] = {100, 100, 255};
+ uchar red[3] = {255, 50, 50};
+ uchar green[3] = {0, 255, 0};
+ uchar blue[3] = {100, 100, 255};
#else
- unsigned char red[3] = {255, 255, 255};
- unsigned char green[3] = {255, 255, 255};
- unsigned char blue[3] = {255, 255, 255};
+ uchar red[3] = {255, 255, 255};
+ uchar green[3] = {255, 255, 255};
+ uchar blue[3] = {255, 255, 255};
#endif
float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0;
float col[4], finalcol[4];
@@ -185,7 +185,7 @@ void ED_image_draw_info(Scene *scene,
/* noisy, high contrast make impossible to read if lower alpha is used. */
immUniformColor4ub(0, 0, 0, 190);
- immRecti(pos, 0, ymin, BLI_rcti_size_x(&ar->winrct) + 1, ymin + UI_UNIT_Y);
+ immRecti(pos, 0, ymin, BLI_rcti_size_x(&region->winrct) + 1, ymin + UI_UNIT_Y);
immUnbindProgram();
@@ -532,7 +532,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene,
MEM_freeN(rectf);
}
-static void draw_udim_label(ARegion *ar, float fx, float fy, const char *label)
+static void draw_udim_label(ARegion *region, float fx, float fy, const char *label)
{
if (label == NULL || !label[0]) {
return;
@@ -540,14 +540,14 @@ static void draw_udim_label(ARegion *ar, float fx, float fy, const char *label)
/* find window pixel coordinates of origin */
int x, y;
- UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y);
+ UI_view2d_view_to_region(&region->v2d, fx, fy, &x, &y);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_blend(true);
int textwidth = BLF_width(blf_mono_font, label, strlen(label)) + 10;
- float stepx = BLI_rcti_size_x(&ar->v2d.mask) / BLI_rctf_size_x(&ar->v2d.cur);
+ float stepx = BLI_rcti_size_x(&region->v2d.mask) / BLI_rctf_size_x(&region->v2d.cur);
float opacity;
if (textwidth < 0.5f * (stepx - 10)) {
opacity = 1.0f;
@@ -567,7 +567,7 @@ static void draw_udim_label(ARegion *ar, float fx, float fy, const char *label)
static void draw_image_buffer(const bContext *C,
SpaceImage *sima,
- ARegion *ar,
+ ARegion *region,
Scene *scene,
ImBuf *ibuf,
float fx,
@@ -575,13 +575,17 @@ static void draw_image_buffer(const bContext *C,
float zoomx,
float zoomy)
{
+ /* Image are still drawn in display space. */
+ glDisable(GL_FRAMEBUFFER_SRGB);
+
int x, y;
+ int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf);
/* find window pixel coordinates of origin */
- UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y);
+ UI_view2d_view_to_region(&region->v2d, fx, fy, &x, &y);
/* this part is generic image display */
- if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
+ if (sima_flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
if (ibuf->zbuf) {
sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf, zoomx, zoomy);
}
@@ -595,9 +599,9 @@ static void draw_image_buffer(const bContext *C,
else {
int clip_max_x, clip_max_y;
UI_view2d_view_to_region(
- &ar->v2d, ar->v2d.cur.xmax, ar->v2d.cur.ymax, &clip_max_x, &clip_max_y);
+ &region->v2d, region->v2d.cur.xmax, region->v2d.cur.ymax, &clip_max_x, &clip_max_y);
- if (sima->flag & SI_USE_ALPHA) {
+ if (sima_flag & SI_USE_ALPHA) {
imm_draw_box_checker_2d(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
GPU_blend(true);
@@ -606,28 +610,28 @@ static void draw_image_buffer(const bContext *C,
}
/* If RGBA display with color management */
- if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
+ if ((sima_flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
ED_draw_imbuf_ctx_clipping(
C, ibuf, x, y, GL_NEAREST, 0, 0, clip_max_x, clip_max_y, zoomx, zoomy);
}
else {
float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- unsigned char *display_buffer;
+ uchar *display_buffer;
void *cache_handle;
ColorManagedViewSettings *view_settings;
ColorManagedDisplaySettings *display_settings;
- if (sima->flag & SI_SHOW_R) {
+ if (sima_flag & SI_SHOW_R) {
shuffle[0] = 1.0f;
}
- else if (sima->flag & SI_SHOW_G) {
+ else if (sima_flag & SI_SHOW_G) {
shuffle[1] = 1.0f;
}
- else if (sima->flag & SI_SHOW_B) {
+ else if (sima_flag & SI_SHOW_B) {
shuffle[2] = 1.0f;
}
- else if (sima->flag & SI_SHOW_ALPHA) {
+ else if (sima_flag & SI_SHOW_ALPHA) {
shuffle[3] = 1.0f;
}
@@ -661,15 +665,17 @@ static void draw_image_buffer(const bContext *C,
IMB_display_buffer_release(cache_handle);
}
- if (sima->flag & SI_USE_ALPHA) {
+ if (sima_flag & SI_USE_ALPHA) {
GPU_blend(false);
}
}
+
+ glEnable(GL_FRAMEBUFFER_SRGB);
}
static void draw_image_buffer_repeated(const bContext *C,
SpaceImage *sima,
- ARegion *ar,
+ ARegion *region,
Scene *scene,
ImBuf *ibuf,
float zoomx,
@@ -677,14 +683,14 @@ static void draw_image_buffer_repeated(const bContext *C,
{
const double time_current = PIL_check_seconds_timer();
- const int xmax = ceil(ar->v2d.cur.xmax);
- const int ymax = ceil(ar->v2d.cur.ymax);
- const int xmin = floor(ar->v2d.cur.xmin);
- const int ymin = floor(ar->v2d.cur.ymin);
+ const int xmax = ceil(region->v2d.cur.xmax);
+ const int ymax = ceil(region->v2d.cur.ymax);
+ const int xmin = floor(region->v2d.cur.xmin);
+ const int ymin = floor(region->v2d.cur.ymin);
for (int x = xmin; x < xmax; x++) {
for (int y = ymin; y < ymax; y++) {
- draw_image_buffer(C, sima, ar, scene, ibuf, x, y, zoomx, zoomy);
+ draw_image_buffer(C, sima, region, scene, ibuf, x, y, zoomx, zoomy);
/* only draw until running out of time */
if ((PIL_check_seconds_timer() - time_current) > 0.25) {
@@ -744,7 +750,7 @@ void draw_image_sample_line(SpaceImage *sima)
}
static void draw_image_paint_helpers(
- const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy)
+ const bContext *C, ARegion *region, Scene *scene, float zoomx, float zoomy)
{
Brush *brush;
int x, y;
@@ -758,9 +764,10 @@ static void draw_image_paint_helpers(
if (ibuf) {
void *cache_handle = NULL;
float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha};
- UI_view2d_view_to_region(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y);
+ UI_view2d_view_to_region(
+ &region->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y);
- unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+ uchar *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
if (!display_buffer) {
BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
@@ -794,9 +801,9 @@ static void draw_image_paint_helpers(
}
}
-static void draw_udim_tile_grid(unsigned int pos_attr,
- unsigned int color_attr,
- ARegion *ar,
+static void draw_udim_tile_grid(uint pos_attr,
+ uint color_attr,
+ ARegion *region,
int x,
int y,
float stepx,
@@ -804,7 +811,7 @@ static void draw_udim_tile_grid(unsigned int pos_attr,
const float color[3])
{
float x1, y1;
- UI_view2d_view_to_region_fl(&ar->v2d, x, y, &x1, &y1);
+ UI_view2d_view_to_region_fl(&region->v2d, x, y, &x1, &y1);
int gridpos[5][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}};
for (int i = 0; i < 4; i++) {
immAttr3fv(color_attr, color);
@@ -814,7 +821,7 @@ static void draw_udim_tile_grid(unsigned int pos_attr,
}
}
-static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima)
+static void draw_udim_tile_grids(ARegion *region, SpaceImage *sima, Image *ima)
{
int num_tiles;
if (ima != NULL) {
@@ -828,12 +835,12 @@ static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima)
num_tiles = sima->tile_grid_shape[0] * sima->tile_grid_shape[1];
}
- float stepx = BLI_rcti_size_x(&ar->v2d.mask) / BLI_rctf_size_x(&ar->v2d.cur);
- float stepy = BLI_rcti_size_y(&ar->v2d.mask) / BLI_rctf_size_y(&ar->v2d.cur);
+ float stepx = BLI_rcti_size_x(&region->v2d.mask) / BLI_rctf_size_x(&region->v2d.cur);
+ float stepy = BLI_rcti_size_y(&region->v2d.mask) / BLI_rctf_size_y(&region->v2d.cur);
GPUVertFormat *format = immVertexFormat();
- unsigned int pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- unsigned color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GPU_PRIM_LINES, 8 * num_tiles);
@@ -849,20 +856,20 @@ static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima)
if (tile != cur_tile) {
int x = (tile->tile_number - 1001) % 10;
int y = (tile->tile_number - 1001) / 10;
- draw_udim_tile_grid(pos, color, ar, x, y, stepx, stepy, theme_color);
+ draw_udim_tile_grid(pos, color, region, x, y, stepx, stepy, theme_color);
}
}
if (cur_tile != NULL) {
int cur_x = (cur_tile->tile_number - 1001) % 10;
int cur_y = (cur_tile->tile_number - 1001) / 10;
- draw_udim_tile_grid(pos, color, ar, cur_x, cur_y, stepx, stepy, selected_color);
+ draw_udim_tile_grid(pos, color, region, cur_x, cur_y, stepx, stepy, selected_color);
}
}
else {
for (int y = 0; y < sima->tile_grid_shape[1]; y++) {
for (int x = 0; x < sima->tile_grid_shape[0]; x++) {
- draw_udim_tile_grid(pos, color, ar, x, y, stepx, stepy, theme_color);
+ draw_udim_tile_grid(pos, color, region, x, y, stepx, stepy, theme_color);
}
}
}
@@ -873,7 +880,7 @@ static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima)
/* draw main image region */
-void draw_image_main(const bContext *C, ARegion *ar)
+void draw_image_main(const bContext *C, ARegion *region)
{
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
@@ -905,7 +912,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
/* retrieve the image and information about it */
ima = ED_space_image(sima);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
/* Tag image as in active use for garbage collector. */
if (ima) {
@@ -949,31 +956,31 @@ void draw_image_main(const bContext *C, ARegion *ar)
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
int x = (tile->tile_number - 1001) % 10;
int y = (tile->tile_number - 1001) / 10;
- ED_region_grid_draw(ar, zoomx, zoomy, x, y);
+ ED_region_grid_draw(region, zoomx, zoomy, x, y);
}
}
else {
for (int y = 0; y < sima->tile_grid_shape[1]; y++) {
for (int x = 0; x < sima->tile_grid_shape[0]; x++) {
- ED_region_grid_draw(ar, zoomx, zoomy, x, y);
+ ED_region_grid_draw(region, zoomx, zoomy, x, y);
}
}
}
}
else {
if (sima->flag & SI_DRAW_TILE) {
- draw_image_buffer_repeated(C, sima, ar, scene, ibuf, zoomx, zoomy);
+ draw_image_buffer_repeated(C, sima, region, scene, ibuf, zoomx, zoomy);
}
else {
main_w = ibuf->x;
main_h = ibuf->y;
- draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
+ draw_image_buffer(C, sima, region, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
if (ima->source == IMA_SRC_TILED) {
ImageTile *tile = BKE_image_get_tile(ima, 0);
char label[sizeof(tile->label)];
BKE_image_get_tile_label(ima, tile, label, sizeof(label));
- draw_udim_label(ar, 0.0f, 0.0f, label);
+ draw_udim_label(region, 0.0f, 0.0f, label);
}
}
@@ -982,7 +989,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
rctf frame;
BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &x, &y);
ED_region_image_metadata_draw(x, y, ibuf, &frame, zoomx, zoomy);
}
@@ -1005,18 +1012,18 @@ void draw_image_main(const bContext *C, ARegion *ar)
float tile_zoomx = (zoomx * main_w) / ibuf->x;
float tile_zoomy = (zoomy * main_h) / ibuf->y;
- draw_image_buffer(C, sima, ar, scene, ibuf, x_pos, y_pos, tile_zoomx, tile_zoomy);
- draw_udim_label(ar, x_pos, y_pos, label);
+ draw_image_buffer(C, sima, region, scene, ibuf, x_pos, y_pos, tile_zoomx, tile_zoomy);
+ draw_udim_label(region, x_pos, y_pos, label);
}
ED_space_image_release_buffer(sima, ibuf, lock);
}
}
- draw_udim_tile_grids(ar, sima, ima);
+ draw_udim_tile_grids(region, sima, ima);
/* paint helpers */
if (show_paint) {
- draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
+ draw_image_paint_helpers(C, region, scene, zoomx, zoomy);
}
if (show_viewer) {
@@ -1025,7 +1032,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
/* render info */
if (ima && show_render) {
- draw_render_info(C, sima->iuser.scene, ima, ar, zoomx, zoomy);
+ draw_render_info(C, sima->iuser.scene, ima, region, zoomx, zoomy);
}
}
@@ -1045,12 +1052,12 @@ bool ED_space_image_show_cache(SpaceImage *sima)
return true;
}
-void draw_image_cache(const bContext *C, ARegion *ar)
+void draw_image_cache(const bContext *C, ARegion *region)
{
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
Image *image = ED_space_image(sima);
- float x, cfra = CFRA, sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
+ float x, cfra = CFRA, sfra = SFRA, efra = EFRA, framelen = region->winx / (efra - sfra + 1);
Mask *mask = NULL;
if (!ED_space_image_show_cache(sima)) {
@@ -1062,7 +1069,7 @@ void draw_image_cache(const bContext *C, ARegion *ar)
}
/* Local coordinate visible rect inside region, to accommodate overlapping ui. */
- const rcti *rect_visible = ED_region_visible_rect(ar);
+ const rcti *rect_visible = ED_region_visible_rect(region);
const int region_bottom = rect_visible->ymin;
GPU_blend(true);
@@ -1070,7 +1077,7 @@ void draw_image_cache(const bContext *C, ARegion *ar)
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
/* Draw cache background. */
- ED_region_cache_draw_background(ar);
+ ED_region_cache_draw_background(region);
/* Draw cached segments. */
if (image != NULL && image->cache != NULL &&
@@ -1080,13 +1087,13 @@ void draw_image_cache(const bContext *C, ARegion *ar)
IMB_moviecache_get_cache_segments(image->cache, IMB_PROXY_NONE, 0, &num_segments, &points);
ED_region_cache_draw_cached_segments(
- ar, num_segments, points, sfra + sima->iuser.offset, efra + sima->iuser.offset);
+ region, num_segments, points, sfra + sima->iuser.offset, efra + sima->iuser.offset);
}
GPU_blend(false);
/* Draw current frame. */
- x = (cfra - sfra) / (efra - sfra + 1) * ar->winx;
+ x = (cfra - sfra) / (efra - sfra + 1) * region->winx;
uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
@@ -1098,6 +1105,6 @@ void draw_image_cache(const bContext *C, ARegion *ar)
ED_region_cache_draw_curfra_label(cfra, x, region_bottom + 8.0f * UI_DPI_FAC);
if (mask != NULL) {
- ED_mask_draw_frames(mask, ar, cfra, sfra, efra);
+ ED_mask_draw_frames(mask, region, cfra, sfra, efra);
}
}
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index c1ed049130e..c9f2ec38354 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -26,15 +26,15 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BLI_rect.h"
#include "BLI_listbase.h"
+#include "BLI_rect.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "IMB_imbuf_types.h"
@@ -175,6 +175,30 @@ void ED_space_image_release_buffer(SpaceImage *sima, ImBuf *ibuf, void *lock)
}
}
+/* Get the SpaceImage flag that is valid for the given ibuf. */
+int ED_space_image_get_display_channel_mask(ImBuf *ibuf)
+{
+ int result = (SI_USE_ALPHA | SI_SHOW_ALPHA | SI_SHOW_ZBUF | SI_SHOW_R | SI_SHOW_G | SI_SHOW_B);
+ if (!ibuf) {
+ return result;
+ }
+
+ const bool color = ibuf->channels >= 3;
+ const bool alpha = ibuf->channels == 4;
+ const bool zbuf = ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1);
+
+ if (!alpha) {
+ result &= ~(SI_USE_ALPHA | SI_SHOW_ALPHA);
+ }
+ if (!zbuf) {
+ result &= ~(SI_SHOW_ZBUF);
+ }
+ if (!color) {
+ result &= ~(SI_SHOW_R | SI_SHOW_G | SI_SHOW_B);
+ }
+ return result;
+}
+
bool ED_space_image_has_buffer(SpaceImage *sima)
{
ImBuf *ibuf;
@@ -188,7 +212,7 @@ bool ED_space_image_has_buffer(SpaceImage *sima)
return has_buffer;
}
-void ED_space_image_get_size(SpaceImage *sima, int *width, int *height)
+void ED_space_image_get_size(SpaceImage *sima, int *r_width, int *r_height)
{
Scene *scene = sima->iuser.scene;
ImBuf *ibuf;
@@ -198,107 +222,110 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height)
ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
if (ibuf && ibuf->x > 0 && ibuf->y > 0) {
- *width = ibuf->x;
- *height = ibuf->y;
+ *r_width = ibuf->x;
+ *r_height = ibuf->y;
}
else if (sima->image && sima->image->type == IMA_TYPE_R_RESULT && scene) {
/* not very important, just nice */
- *width = (scene->r.xsch * scene->r.size) / 100;
- *height = (scene->r.ysch * scene->r.size) / 100;
+ *r_width = (scene->r.xsch * scene->r.size) / 100;
+ *r_height = (scene->r.ysch * scene->r.size) / 100;
if ((scene->r.mode & R_BORDER) && (scene->r.mode & R_CROP)) {
- *width *= BLI_rctf_size_x(&scene->r.border);
- *height *= BLI_rctf_size_y(&scene->r.border);
+ *r_width *= BLI_rctf_size_x(&scene->r.border);
+ *r_height *= BLI_rctf_size_y(&scene->r.border);
}
}
/* I know a bit weak... but preview uses not actual image size */
- // XXX else if (image_preview_active(sima, width, height));
+ // XXX else if (image_preview_active(sima, r_width, r_height));
else {
- *width = IMG_SIZE_FALLBACK;
- *height = IMG_SIZE_FALLBACK;
+ *r_width = IMG_SIZE_FALLBACK;
+ *r_height = IMG_SIZE_FALLBACK;
}
ED_space_image_release_buffer(sima, ibuf, lock);
}
-void ED_space_image_get_size_fl(SpaceImage *sima, float size[2])
+void ED_space_image_get_size_fl(SpaceImage *sima, float r_size[2])
{
int size_i[2];
ED_space_image_get_size(sima, &size_i[0], &size_i[1]);
- size[0] = size_i[0];
- size[1] = size_i[1];
+ r_size[0] = size_i[0];
+ r_size[1] = size_i[1];
}
-void ED_space_image_get_aspect(SpaceImage *sima, float *aspx, float *aspy)
+void ED_space_image_get_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy)
{
Image *ima = sima->image;
if ((ima == NULL) || (ima->aspx == 0.0f || ima->aspy == 0.0f)) {
- *aspx = *aspy = 1.0;
+ *r_aspx = *r_aspy = 1.0;
}
else {
- BKE_image_get_aspect(ima, aspx, aspy);
+ BKE_image_get_aspect(ima, r_aspx, r_aspy);
}
}
-void ED_space_image_get_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float *zoomy)
+void ED_space_image_get_zoom(SpaceImage *sima,
+ const ARegion *region,
+ float *r_zoomx,
+ float *r_zoomy)
{
int width, height;
ED_space_image_get_size(sima, &width, &height);
- *zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) /
- (float)(BLI_rctf_size_x(&ar->v2d.cur) * width);
- *zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) /
- (float)(BLI_rctf_size_y(&ar->v2d.cur) * height);
+ *r_zoomx = (float)(BLI_rcti_size_x(&region->winrct) + 1) /
+ (float)(BLI_rctf_size_x(&region->v2d.cur) * width);
+ *r_zoomy = (float)(BLI_rcti_size_y(&region->winrct) + 1) /
+ (float)(BLI_rctf_size_y(&region->v2d.cur) * height);
}
-void ED_space_image_get_uv_aspect(SpaceImage *sima, float *aspx, float *aspy)
+void ED_space_image_get_uv_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy)
{
int w, h;
- ED_space_image_get_aspect(sima, aspx, aspy);
+ ED_space_image_get_aspect(sima, r_aspx, r_aspy);
ED_space_image_get_size(sima, &w, &h);
- *aspx *= (float)w;
- *aspy *= (float)h;
+ *r_aspx *= (float)w;
+ *r_aspy *= (float)h;
- if (*aspx < *aspy) {
- *aspy = *aspy / *aspx;
- *aspx = 1.0f;
+ if (*r_aspx < *r_aspy) {
+ *r_aspy = *r_aspy / *r_aspx;
+ *r_aspx = 1.0f;
}
else {
- *aspx = *aspx / *aspy;
- *aspy = 1.0f;
+ *r_aspx = *r_aspx / *r_aspy;
+ *r_aspy = 1.0f;
}
}
-void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *aspx, float *aspy)
+void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *r_aspx, float *r_aspy)
{
if (ima) {
int w, h;
- BKE_image_get_aspect(ima, aspx, aspy);
+ BKE_image_get_aspect(ima, r_aspx, r_aspy);
BKE_image_get_size(ima, iuser, &w, &h);
- *aspx *= (float)w;
- *aspy *= (float)h;
+ *r_aspx *= (float)w;
+ *r_aspy *= (float)h;
}
else {
- *aspx = 1.0f;
- *aspy = 1.0f;
+ *r_aspx = 1.0f;
+ *r_aspy = 1.0f;
}
}
/* takes event->mval */
-void ED_image_mouse_pos(SpaceImage *sima, ARegion *ar, const int mval[2], float co[2])
+void ED_image_mouse_pos(SpaceImage *sima, const ARegion *region, const int mval[2], float co[2])
{
int sx, sy, width, height;
float zoomx, zoomy;
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
ED_space_image_get_size(sima, &width, &height);
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &sx, &sy);
co[0] = ((mval[0] - sx) / zoomx) / width;
co[1] = ((mval[1] - sy) / zoomy) / height;
@@ -316,29 +343,33 @@ void ED_image_view_center_to_point(SpaceImage *sima, float x, float y)
sima->yof = (y - 0.5f) * height * aspy;
}
-void ED_image_point_pos(SpaceImage *sima, ARegion *ar, float x, float y, float *xr, float *yr)
+void ED_image_point_pos(
+ SpaceImage *sima, const ARegion *region, float x, float y, float *r_x, float *r_y)
{
int sx, sy, width, height;
float zoomx, zoomy;
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
ED_space_image_get_size(sima, &width, &height);
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &sx, &sy);
- *xr = ((x - sx) / zoomx) / width;
- *yr = ((y - sy) / zoomy) / height;
+ *r_x = ((x - sx) / zoomx) / width;
+ *r_y = ((y - sy) / zoomy) / height;
}
-void ED_image_point_pos__reverse(SpaceImage *sima, ARegion *ar, const float co[2], float r_co[2])
+void ED_image_point_pos__reverse(SpaceImage *sima,
+ const ARegion *region,
+ const float co[2],
+ float r_co[2])
{
float zoomx, zoomy;
int width, height;
int sx, sy;
- UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
+ UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &sx, &sy);
ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
r_co[0] = (co[0] * width * zoomx) + (float)sx;
r_co[1] = (co[1] * height * zoomy) + (float)sy;
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index f3ec68db562..ae26363ad79 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -37,8 +37,8 @@ struct wmOperatorType;
extern const char *image_context_dir[]; /* doc access */
/* image_draw.c */
-void draw_image_main(const struct bContext *C, struct ARegion *ar);
-void draw_image_cache(const struct bContext *C, struct ARegion *ar);
+void draw_image_main(const struct bContext *C, struct ARegion *region);
+void draw_image_cache(const struct bContext *C, struct ARegion *region);
void draw_image_grease_pencil(struct bContext *C, bool onlyv2d);
void draw_image_sample_line(struct SpaceImage *sima);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 17c6f76a1d9..eb97077f77a 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -21,11 +21,11 @@
* \ingroup spimage
*/
-#include <stddef.h>
-#include <string.h>
+#include <errno.h>
#include <fcntl.h>
+#include <stddef.h>
#include <stdlib.h>
-#include <errno.h>
+#include <string.h>
#ifndef WIN32
# include <unistd.h>
#else
@@ -46,31 +46,32 @@
#include "BLT_translation.h"
#include "DNA_camera_types.h"
-#include "DNA_object_types.h"
#include "DNA_node_types.h"
+#include "DNA_object_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
+#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_image_save.h"
-#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_paint.h"
#include "BKE_report.h"
-#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "DEG_depsgraph.h"
#include "GPU_draw.h"
-#include "GPU_state.h"
#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
@@ -90,8 +91,9 @@
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_space_api.h"
-#include "ED_uvedit.h"
#include "ED_util.h"
+#include "ED_util_imbuf.h"
+#include "ED_uvedit.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -111,7 +113,7 @@
* \{ */
static void sima_zoom_set(
- SpaceImage *sima, ARegion *ar, float zoom, const float location[2], const bool zoom_to_pos)
+ SpaceImage *sima, ARegion *region, float zoom, const float location[2], const bool zoom_to_pos)
{
float oldzoom = sima->zoom;
int width, height;
@@ -128,10 +130,10 @@ static void sima_zoom_set(
if ((width < 4) && (height < 4) && sima->zoom < oldzoom) {
sima->zoom = oldzoom;
}
- else if (BLI_rcti_size_x(&ar->winrct) <= sima->zoom) {
+ else if (BLI_rcti_size_x(&region->winrct) <= sima->zoom) {
sima->zoom = oldzoom;
}
- else if (BLI_rcti_size_y(&ar->winrct) <= sima->zoom) {
+ else if (BLI_rcti_size_y(&region->winrct) <= sima->zoom) {
sima->zoom = oldzoom;
}
}
@@ -150,16 +152,19 @@ static void sima_zoom_set(
}
}
-static void sima_zoom_set_factor(
- SpaceImage *sima, ARegion *ar, float zoomfac, const float location[2], const bool zoom_to_pos)
+static void sima_zoom_set_factor(SpaceImage *sima,
+ ARegion *region,
+ float zoomfac,
+ const float location[2],
+ const bool zoom_to_pos)
{
- sima_zoom_set(sima, ar, sima->zoom * zoomfac, location, zoom_to_pos);
+ sima_zoom_set(sima, region, sima->zoom * zoomfac, location, zoom_to_pos);
}
/**
* Fits the view to the bounds exactly, caller should add margin if needed.
*/
-static void sima_zoom_set_from_bounds(SpaceImage *sima, ARegion *ar, const rctf *bounds)
+static void sima_zoom_set_from_bounds(SpaceImage *sima, ARegion *region, const rctf *bounds)
{
int image_size[2];
float aspx, aspy;
@@ -175,13 +180,13 @@ static void sima_zoom_set_from_bounds(SpaceImage *sima, ARegion *ar, const rctf
sima->yof = roundf((BLI_rctf_cent_y(bounds) - 0.5f) * image_size[1]);
float size_xy[2], size;
- size_xy[0] = BLI_rcti_size_x(&ar->winrct) / (BLI_rctf_size_x(bounds) * image_size[0]);
- size_xy[1] = BLI_rcti_size_y(&ar->winrct) / (BLI_rctf_size_y(bounds) * image_size[1]);
+ size_xy[0] = BLI_rcti_size_x(&region->winrct) / (BLI_rctf_size_x(bounds) * image_size[0]);
+ size_xy[1] = BLI_rcti_size_y(&region->winrct) / (BLI_rctf_size_y(bounds) * image_size[1]);
size = min_ff(size_xy[0], size_xy[1]);
CLAMP_MAX(size, 100.0f);
- sima_zoom_set(sima, ar, size, NULL, false);
+ sima_zoom_set(sima, region, size, NULL, false);
}
static Image *image_from_context(const bContext *C)
@@ -235,7 +240,7 @@ static bool image_from_context_has_data_poll(bContext *C)
/**
* Use this when the image buffer is accessed without the image user.
*/
-static bool image_from_contect_has_data_poll_no_image_user(bContext *C)
+static bool image_from_context_has_data_poll_no_image_user(bContext *C)
{
Image *ima = image_from_context(C);
@@ -252,10 +257,10 @@ static bool image_not_packed_poll(bContext *C)
bool space_image_main_region_poll(bContext *C)
{
SpaceImage *sima = CTX_wm_space_image(C);
- /* XXX ARegion *ar = CTX_wm_region(C); */
+ /* XXX ARegion *region = CTX_wm_region(C); */
if (sima) {
- return true; /* XXX (ar && ar->type->regionid == RGN_TYPE_WINDOW); */
+ return true; /* XXX (region && region->type->regionid == RGN_TYPE_WINDOW); */
}
return false;
}
@@ -274,28 +279,6 @@ static bool space_image_main_area_not_uv_brush_poll(bContext *C)
return 0;
}
-static bool image_sample_poll(bContext *C)
-{
- SpaceImage *sima = CTX_wm_space_image(C);
- if (sima == NULL) {
- return false;
- }
-
- Object *obedit = CTX_data_edit_object(C);
- if (obedit) {
- /* Disable when UV editing so it doesn't swallow all click events
- * (use for setting cursor). */
- if (ED_space_image_show_uvedit(sima, obedit)) {
- return false;
- }
- }
- else if (sima->mode != SI_MODE_VIEW) {
- return false;
- }
-
- return true;
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -462,14 +445,14 @@ typedef struct ViewZoomData {
/* */
SpaceImage *sima;
- ARegion *ar;
+ ARegion *region;
} ViewZoomData;
static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ViewZoomData *vpd;
op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomData");
@@ -486,7 +469,7 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *eve
vpd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
UI_view2d_region_to_view(
- &ar->v2d, event->mval[0], event->mval[1], &vpd->location[0], &vpd->location[1]);
+ &region->v2d, event->mval[0], event->mval[1], &vpd->location[0], &vpd->location[1]);
if (U.viewzoom == USER_ZOOM_CONT) {
/* needs a timer to continue redrawing */
@@ -495,7 +478,7 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *eve
}
vpd->sima = sima;
- vpd->ar = ar;
+ vpd->region = region;
WM_event_add_modal_handler(C, op);
}
@@ -523,11 +506,11 @@ static void image_view_zoom_exit(bContext *C, wmOperator *op, bool cancel)
static int image_view_zoom_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- sima_zoom_set_factor(sima, ar, RNA_float_get(op->ptr, "factor"), NULL, false);
+ sima_zoom_set_factor(sima, region, RNA_float_get(op->ptr, "factor"), NULL, false);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -542,10 +525,11 @@ static int image_view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
{
if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float delta, factor, location[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
delta = event->prevx - event->x + event->prevy - event->y;
@@ -557,11 +541,11 @@ static int image_view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
RNA_float_set(op->ptr, "factor", factor);
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
sima_zoom_set(sima,
- ar,
+ region,
sima->zoom * factor,
location,
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -616,8 +600,8 @@ static void image_zoom_apply(ViewZoomData *vpd,
}
RNA_float_set(op->ptr, "factor", factor);
- sima_zoom_set(vpd->sima, vpd->ar, vpd->zoom * factor, vpd->location, zoom_to_pos);
- ED_region_tag_redraw(vpd->ar);
+ sima_zoom_set(vpd->sima, vpd->region, vpd->zoom * factor, vpd->location, zoom_to_pos);
+ ED_region_tag_redraw(vpd->region);
}
static int image_view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -715,7 +699,7 @@ static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmE
}
else {
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float pan_vec[3];
const wmNDOFMotionData *ndof = event->customdata;
@@ -726,11 +710,11 @@ static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmE
mul_v2_fl(pan_vec, (speed * ndof->dt) / sima->zoom);
pan_vec[2] *= -ndof->dt;
- sima_zoom_set_factor(sima, ar, 1.0f + pan_vec[2], NULL, false);
+ sima_zoom_set_factor(sima, region, 1.0f + pan_vec[2], NULL, false);
sima->xof += pan_vec[0];
sima->yof += pan_vec[1];
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -766,14 +750,14 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot)
static int image_view_all_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima;
- ARegion *ar;
+ ARegion *region;
float aspx, aspy, zoomx, zoomy, w, h;
int width, height;
const bool fit_view = RNA_boolean_get(op->ptr, "fit_view");
/* retrieve state */
sima = CTX_wm_space_image(C);
- ar = CTX_wm_region(C);
+ region = CTX_wm_region(C);
ED_space_image_get_size(sima, &width, &height);
ED_space_image_get_aspect(sima, &aspx, &aspy);
@@ -781,9 +765,32 @@ static int image_view_all_exec(bContext *C, wmOperator *op)
w = width * aspx;
h = height * aspy;
+ float xof = 0.0f, yof = 0.0f;
+ if ((sima->image == NULL) || (sima->image->source == IMA_SRC_TILED)) {
+ /* Extend the shown area to cover all UDIM tiles. */
+ int x_tiles, y_tiles;
+ if (sima->image == NULL) {
+ x_tiles = sima->tile_grid_shape[0];
+ y_tiles = sima->tile_grid_shape[1];
+ }
+ else {
+ x_tiles = y_tiles = 1;
+ LISTBASE_FOREACH (ImageTile *, tile, &sima->image->tiles) {
+ int tile_x = (tile->tile_number - 1001) % 10;
+ int tile_y = (tile->tile_number - 1001) / 10;
+ x_tiles = max_ii(x_tiles, tile_x + 1);
+ y_tiles = max_ii(y_tiles, tile_y + 1);
+ }
+ }
+ xof = 0.5f * (x_tiles - 1.0f) * w;
+ yof = 0.5f * (y_tiles - 1.0f) * h;
+ w *= x_tiles;
+ h *= y_tiles;
+ }
+
/* check if the image will fit in the image with (zoom == 1) */
- width = BLI_rcti_size_x(&ar->winrct) + 1;
- height = BLI_rcti_size_y(&ar->winrct) + 1;
+ width = BLI_rcti_size_x(&region->winrct) + 1;
+ height = BLI_rcti_size_y(&region->winrct) + 1;
if (fit_view) {
const int margin = 5; /* margin from border */
@@ -791,7 +798,7 @@ static int image_view_all_exec(bContext *C, wmOperator *op)
zoomx = (float)width / (w + 2 * margin);
zoomy = (float)height / (h + 2 * margin);
- sima_zoom_set(sima, ar, min_ff(zoomx, zoomy), NULL, false);
+ sima_zoom_set(sima, region, min_ff(zoomx, zoomy), NULL, false);
}
else {
if ((w >= width || h >= height) && (width > 0 && height > 0)) {
@@ -799,16 +806,17 @@ static int image_view_all_exec(bContext *C, wmOperator *op)
zoomy = (float)height / h;
/* find the zoom value that will fit the image in the image space */
- sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL, false);
+ sima_zoom_set(sima, region, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL, false);
}
else {
- sima_zoom_set(sima, ar, 1.0f, NULL, false);
+ sima_zoom_set(sima, region, 1.0f, NULL, false);
}
}
- sima->xof = sima->yof = 0.0f;
+ sima->xof = xof;
+ sima->yof = yof;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -818,7 +826,7 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->idname = "IMAGE_OT_view_all";
ot->description = "View the entire image";
@@ -843,11 +851,11 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
static int view_center_cursor_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ED_image_view_center_to_point(sima, sima->cursor[0], sima->cursor[1]);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -867,13 +875,13 @@ void IMAGE_OT_view_center_cursor(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Selected Operator
+/** \name Frame Selected Operator
* \{ */
static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceImage *sima;
- ARegion *ar;
+ ARegion *region;
Scene *scene;
ViewLayer *view_layer;
Object *obedit;
@@ -881,7 +889,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
/* retrieve state */
sima = CTX_wm_space_image(C);
- ar = CTX_wm_region(C);
+ region = CTX_wm_region(C);
scene = CTX_data_scene(C);
view_layer = CTX_data_view_layer(C);
obedit = CTX_data_edit_object(C);
@@ -891,7 +899,12 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
/* get bounds */
float min[2], max[2];
if (ED_space_image_show_uvedit(sima, obedit)) {
- if (!ED_uvedit_minmax(scene, ima, obedit, min, max)) {
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+ bool success = ED_uvedit_minmax_multi(scene, ima, objects, objects_len, min, max);
+ MEM_freeN(objects);
+ if (!success) {
return OPERATOR_CANCELLED;
}
}
@@ -910,9 +923,9 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
/* add some margin */
BLI_rctf_scale(&bounds, 1.4f);
- sima_zoom_set_from_bounds(sima, ar, &bounds);
+ sima_zoom_set_from_bounds(sima, region, &bounds);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -943,25 +956,26 @@ void IMAGE_OT_view_selected(wmOperatorType *ot)
static int image_view_zoom_in_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float location[2];
RNA_float_get_array(op->ptr, "location", location);
sima_zoom_set_factor(
- sima, ar, powf(2.0f, 1.0f / 3.0f), location, U.uiflag & USER_ZOOM_TO_MOUSEPOS);
+ sima, region, powf(2.0f, 1.0f / 3.0f), location, U.uiflag & USER_ZOOM_TO_MOUSEPOS);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
static int image_view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float location[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
RNA_float_set_array(op->ptr, "location", location);
return image_view_zoom_in_exec(C, op);
@@ -972,7 +986,7 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "View Zoom In";
+ ot->name = "Zoom In";
ot->idname = "IMAGE_OT_view_zoom_in";
ot->description = "Zoom in the image (centered around 2D cursor)";
@@ -1001,25 +1015,26 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
static int image_view_zoom_out_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float location[2];
RNA_float_get_array(op->ptr, "location", location);
sima_zoom_set_factor(
- sima, ar, powf(0.5f, 1.0f / 3.0f), location, U.uiflag & USER_ZOOM_TO_MOUSEPOS);
+ sima, region, powf(0.5f, 1.0f / 3.0f), location, U.uiflag & USER_ZOOM_TO_MOUSEPOS);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
static int image_view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float location[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
RNA_float_set_array(op->ptr, "location", location);
return image_view_zoom_out_exec(C, op);
@@ -1030,7 +1045,7 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "View Zoom Out";
+ ot->name = "Zoom Out";
ot->idname = "IMAGE_OT_view_zoom_out";
ot->description = "Zoom out the image (centered around 2D cursor)";
@@ -1065,15 +1080,15 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
static int image_view_zoom_ratio_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- sima_zoom_set(sima, ar, RNA_float_get(op->ptr, "ratio"), NULL, false);
+ sima_zoom_set(sima, region, RNA_float_get(op->ptr, "ratio"), NULL, false);
/* ensure pixel exact locations for draw */
sima->xof = (int)sima->xof;
sima->yof = (int)sima->yof;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -1113,13 +1128,13 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
static int image_view_zoom_border_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
rctf bounds;
const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out");
WM_operator_properties_border_to_rctf(op, &bounds);
- UI_view2d_region_to_view_rctf(&ar->v2d, &bounds, &bounds);
+ UI_view2d_region_to_view_rctf(&region->v2d, &bounds, &bounds);
const struct {
float xof;
@@ -1131,7 +1146,7 @@ static int image_view_zoom_border_exec(bContext *C, wmOperator *op)
.zoom = sima->zoom,
};
- sima_zoom_set_from_bounds(sima, ar, &bounds);
+ sima_zoom_set_from_bounds(sima, region, &bounds);
/* zoom out */
if (!zoom_in) {
@@ -1140,7 +1155,7 @@ static int image_view_zoom_border_exec(bContext *C, wmOperator *op)
sima->zoom = sima_view_prev.zoom * (sima_view_prev.zoom / sima->zoom);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -1183,18 +1198,6 @@ typedef struct ImageOpenData {
ImageFormatData im_format;
} ImageOpenData;
-typedef struct ImageFrameRange {
- struct ImageFrameRange *next, *prev;
- ListBase frames;
- /** The full path of the first file in the list of image files */
- char filepath[FILE_MAX];
-} ImageFrameRange;
-
-typedef struct ImageFrame {
- struct ImageFrame *next, *prev;
- int framenr;
-} ImageFrame;
-
static void image_open_init(bContext *C, wmOperator *op)
{
ImageOpenData *iod;
@@ -1209,179 +1212,18 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
op->customdata = NULL;
}
-/**
- * Get a list of frames from the list of image files matching the first file name sequence pattern.
- * \param ptr[in]: The RNA pointer containing the "directory" entry and "files" collection.
- * \param frames_all[out]: the list of frame numbers found in the files matching
- * the first one by name.
- */
-static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all)
-{
- char dir[FILE_MAXDIR];
- const bool do_frame_range = RNA_boolean_get(ptr, "use_sequence_detection");
- ImageFrameRange *frame_range = NULL;
-
- RNA_string_get(ptr, "directory", dir);
- RNA_BEGIN (ptr, itemptr, "files") {
- char base_head[FILE_MAX], base_tail[FILE_MAX];
- char head[FILE_MAX], tail[FILE_MAX];
- unsigned short digits;
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
-
- /* use the first file in the list as base filename */
- frame->framenr = BLI_stringdec(filename, head, tail, &digits);
-
- /* still in the same sequence */
- if (do_frame_range && (frame_range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) &&
- (STREQLEN(base_tail, tail, FILE_MAX))) {
- /* pass */
- }
- else {
- /* start a new frame range */
- frame_range = MEM_callocN(sizeof(*frame_range), __func__);
- BLI_join_dirfile(frame_range->filepath, sizeof(frame_range->filepath), dir, filename);
- BLI_addtail(frames_all, frame_range);
-
- BLI_strncpy(base_head, head, sizeof(base_head));
- BLI_strncpy(base_tail, tail, sizeof(base_tail));
- }
-
- BLI_addtail(&frame_range->frames, frame);
- MEM_freeN(filename);
- }
- RNA_END;
-}
-
-static int image_cmp_frame(const void *a, const void *b)
-{
- const ImageFrame *frame_a = a;
- const ImageFrame *frame_b = b;
-
- if (frame_a->framenr < frame_b->framenr) {
- return -1;
- }
- if (frame_a->framenr > frame_b->framenr) {
- return 1;
- }
- return 0;
-}
-
-/* Checks whether the given filepath refers to a UDIM texture.
- * If yes, the range from 1001 to the highest tile is returned, otherwise 0.
- *
- * If the result is positive, the filepath will be overwritten with that of
- * the 1001 tile.
- * udim_tiles may get filled even if the result ultimately is false! */
-static int image_get_udim(char *filepath, LinkNodePair *udim_tiles)
-{
- char filename[FILE_MAX], dirname[FILE_MAXDIR];
- BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
-
- unsigned short digits;
- char base_head[FILE_MAX], base_tail[FILE_MAX];
- int id = BLI_stringdec(filename, base_head, base_tail, &digits);
-
- if (id < 1001 || id >= IMA_UDIM_MAX) {
- return 0;
- }
-
- bool is_udim = true;
- bool has_primary = false;
- int max_udim = 0;
-
- struct direntry *dir;
- uint totfile = BLI_filelist_dir_contents(dirname, &dir);
- for (int i = 0; i < totfile; i++) {
- if (!(dir[i].type & S_IFREG)) {
- continue;
- }
- char head[FILE_MAX], tail[FILE_MAX];
- id = BLI_stringdec(dir[i].relname, head, tail, &digits);
-
- if (digits > 4 || !(STREQLEN(base_head, head, FILE_MAX)) ||
- !(STREQLEN(base_tail, tail, FILE_MAX))) {
- continue;
- }
-
- if (id < 1001 || id >= IMA_UDIM_MAX) {
- is_udim = false;
- break;
- }
- if (id == 1001) {
- has_primary = true;
- }
-
- BLI_linklist_append(udim_tiles, POINTER_FROM_INT(id));
- max_udim = max_ii(max_udim, id);
- }
- BLI_filelist_free(dir, totfile);
-
- if (is_udim && has_primary) {
- char primary_filename[FILE_MAX];
- BLI_stringenc(primary_filename, base_head, base_tail, digits, 1001);
- BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename);
- return max_udim - 1000;
- }
- return 0;
-}
-
-/**
- * Return the start (offset) and the length of the sequence of
- * continuous frames in the list of frames.
- *
- * \param frames: [in] the list of frame numbers, as a side-effect the list is sorted.
- * \param ofs: [out] offset the first frame number in the sequence.
- * \return the number of contiguous frames in the sequence
- */
-static int image_sequence_get_len(ImageFrameRange *frame_range,
- int *ofs,
- char *filepath_range,
- LinkNodePair *udim_tiles)
-{
- ImageFrame *frame;
-
- BLI_listbase_sort(&frame_range->frames, image_cmp_frame);
- BLI_strncpy(filepath_range, frame_range->filepath, FILE_MAX);
-
- frame = frame_range->frames.first;
- if (frame != NULL) {
- int frame_curr = frame->framenr;
- (*ofs) = frame_curr;
-
- if (udim_tiles != NULL) {
- int len_udim = image_get_udim(filepath_range, udim_tiles);
- if (len_udim > 0) {
- *ofs = 1001;
- return len_udim;
- }
- }
-
- while (frame != NULL && (frame->framenr == frame_curr)) {
- frame_curr++;
- frame = frame->next;
- }
- return frame_curr - (*ofs);
- }
- *ofs = 0;
- return 0;
-}
-
static Image *image_open_single(Main *bmain,
wmOperator *op,
- const char *filepath,
+ ImageFrameRange *range,
const char *relbase,
bool is_relative_path,
- bool use_multiview,
- int frame_seq_len,
- int frame_seq_ofs,
- LinkNodePair *udim_tiles)
+ bool use_multiview)
{
bool exists = false;
Image *ima = NULL;
errno = 0;
- ima = BKE_image_load_exists_ex(bmain, filepath, &exists);
+ ima = BKE_image_load_exists_ex(bmain, range->filepath, &exists);
if (!ima) {
if (op->customdata) {
@@ -1390,7 +1232,7 @@ static Image *image_open_single(Main *bmain,
BKE_reportf(op->reports,
RPT_ERROR,
"Cannot read '%s': %s",
- filepath,
+ range->filepath,
errno ? strerror(errno) : TIP_("unsupported image format"));
return NULL;
}
@@ -1415,11 +1257,11 @@ static Image *image_open_single(Main *bmain,
BKE_image_free_views(ima);
}
- if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) {
- if (udim_tiles && frame_seq_ofs == 1001) {
+ if ((range->length > 1) && (ima->source == IMA_SRC_FILE)) {
+ if (range->udim_tiles.first && range->offset == 1001) {
ima->source = IMA_SRC_TILED;
- for (LinkNode *node = udim_tiles->list; node; node = node->next) {
- BKE_image_add_tile(ima, POINTER_AS_INT(node->link), NULL);
+ LISTBASE_FOREACH (LinkData *, node, &range->udim_tiles) {
+ BKE_image_add_tile(ima, POINTER_AS_INT(node->data), NULL);
}
}
else {
@@ -1434,13 +1276,12 @@ static Image *image_open_single(Main *bmain,
static int image_open_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
ImageUser *iuser = NULL;
ImageOpenData *iod = op->customdata;
Image *ima = NULL;
- char filepath[FILE_MAX];
int frame_seq_len = 0;
int frame_ofs = 1;
@@ -1452,83 +1293,21 @@ static int image_open_exec(bContext *C, wmOperator *op)
image_open_init(C, op);
}
- RNA_string_get(op->ptr, "filepath", filepath);
-
- if (RNA_struct_property_is_set(op->ptr, "directory") &&
- RNA_struct_property_is_set(op->ptr, "files")) {
- bool was_relative = BLI_path_is_rel(filepath);
- ListBase frame_ranges_all;
-
- BLI_listbase_clear(&frame_ranges_all);
- image_sequence_get_frame_ranges(op->ptr, &frame_ranges_all);
- for (ImageFrameRange *frame_range = frame_ranges_all.first; frame_range;
- frame_range = frame_range->next) {
- int frame_range_ofs;
-
- LinkNodePair udim_tiles = {NULL};
- LinkNodePair *udim_tiles_ptr = use_udim ? (&udim_tiles) : NULL;
-
- char filepath_range[FILE_MAX];
- int frame_range_seq_len = image_sequence_get_len(
- frame_range, &frame_range_ofs, filepath_range, udim_tiles_ptr);
- BLI_freelistN(&frame_range->frames);
-
- if (was_relative) {
- BLI_path_rel(filepath_range, BKE_main_blendfile_path(bmain));
- }
+ ListBase ranges = ED_image_filesel_detect_sequences(bmain, op, use_udim);
+ LISTBASE_FOREACH (ImageFrameRange *, range, &ranges) {
+ Image *ima_range = image_open_single(
+ bmain, op, range, BKE_main_blendfile_path(bmain), is_relative_path, use_multiview);
- Image *ima_range = image_open_single(bmain,
- op,
- filepath_range,
- BKE_main_blendfile_path(bmain),
- is_relative_path,
- use_multiview,
- frame_range_seq_len,
- frame_range_ofs,
- udim_tiles_ptr);
-
- /* take the first image */
- if ((ima == NULL) && ima_range) {
- ima = ima_range;
- frame_seq_len = frame_range_seq_len;
- frame_ofs = frame_range_ofs;
- }
-
- BLI_linklist_free(udim_tiles.list, NULL);
- }
- BLI_freelistN(&frame_ranges_all);
- }
- else {
- /* for drag & drop etc. */
-
- LinkNodePair udim_tiles = {NULL};
- frame_seq_len = 1;
- char filepath_range[FILE_MAX];
- BLI_strncpy(filepath_range, filepath, FILE_MAX);
-
- if (use_udim > 0) {
- /* Try to find UDIM tiles corresponding to the image */
- int udim_len = image_get_udim(filepath_range, &udim_tiles);
-
- /* If we found something, mark the image as tiled. */
- if (udim_len) {
- frame_seq_len = udim_len;
- frame_ofs = 1001;
- }
+ /* take the first image */
+ if ((ima == NULL) && ima_range) {
+ ima = ima_range;
+ frame_seq_len = range->length;
+ frame_ofs = range->offset;
}
- ima = image_open_single(bmain,
- op,
- filepath_range,
- BKE_main_blendfile_path(bmain),
- is_relative_path,
- use_multiview,
- frame_seq_len,
- frame_ofs,
- &udim_tiles);
-
- BLI_linklist_free(udim_tiles.list, NULL);
+ BLI_freelistN(&range->udim_tiles);
}
+ BLI_freelistN(&ranges);
if (ima == NULL) {
return OPERATOR_CANCELLED;
@@ -1551,8 +1330,8 @@ static int image_open_exec(bContext *C, wmOperator *op)
if (iod->iuser) {
iuser = iod->iuser;
}
- else if (sa && sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
+ else if (area && area->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = area->spacedata.first;
ED_space_image_set(bmain, sima, obedit, ima, false);
iuser = &sima->iuser;
}
@@ -1565,7 +1344,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
if (iuser == NULL) {
Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
if (cam) {
- for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+ LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) {
if (bgpic->ima == ima) {
iuser = &bgpic->iuser;
break;
@@ -1877,6 +1656,12 @@ void IMAGE_OT_replace(wmOperatorType *ot)
/** \name Save Image As Operator
* \{ */
+typedef struct ImageSaveData {
+ ImageUser *iuser;
+ Image *image;
+ ImageFormatData im_format;
+} ImageSaveData;
+
static char imtype_best_depth(ImBuf *ibuf, const char imtype)
{
const char depth_ok = BKE_imtype_valid_depths(imtype);
@@ -1956,9 +1741,6 @@ static int image_save_options_init(Main *bmain,
opts->im_format.views_format = ima->views_format;
}
- ///* XXX - this is lame, we need to make these available too! */
- // opts->subimtype = scene->r.subimtype;
-
BLI_strncpy(opts->filepath, ibuf->name, sizeof(opts->filepath));
/* sanitize all settings */
@@ -1997,7 +1779,8 @@ static int image_save_options_init(Main *bmain,
}
/* append UDIM numbering if not present */
- if (ima->source == IMA_SRC_TILED && (BLI_stringdec(ima->name, NULL, NULL, NULL) != 1001)) {
+ if (ima->source == IMA_SRC_TILED &&
+ (BLI_path_sequence_decode(ima->name, NULL, NULL, NULL) != 1001)) {
int len = strlen(opts->filepath);
STR_CONCAT(opts->filepath, len, ".1001");
}
@@ -2006,6 +1789,8 @@ static int image_save_options_init(Main *bmain,
/* color management */
BKE_color_managed_display_settings_copy(&opts->im_format.display_settings,
&scene->display_settings);
+
+ BKE_color_managed_view_settings_free(&opts->im_format.view_settings);
BKE_color_managed_view_settings_copy(&opts->im_format.view_settings, &scene->view_settings);
}
@@ -2014,12 +1799,14 @@ static int image_save_options_init(Main *bmain,
return (ibuf != NULL);
}
-static void image_save_options_from_op(Main *bmain, ImageSaveOptions *opts, wmOperator *op)
+static void image_save_options_from_op(Main *bmain,
+ ImageSaveOptions *opts,
+ wmOperator *op,
+ ImageFormatData *imf)
{
- if (op->customdata) {
+ if (imf) {
BKE_color_managed_view_settings_free(&opts->im_format.view_settings);
-
- opts->im_format = *(ImageFormatData *)op->customdata;
+ opts->im_format = *imf;
}
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -2031,20 +1818,17 @@ static void image_save_options_from_op(Main *bmain, ImageSaveOptions *opts, wmOp
static void image_save_options_to_op(ImageSaveOptions *opts, wmOperator *op)
{
if (op->customdata) {
- BKE_color_managed_view_settings_free(&((ImageFormatData *)op->customdata)->view_settings);
-
- *(ImageFormatData *)op->customdata = opts->im_format;
+ ImageSaveData *isd = op->customdata;
+ BKE_color_managed_view_settings_free(&isd->im_format.view_settings);
+ isd->im_format = opts->im_format;
}
RNA_string_set(op->ptr, "filepath", opts->filepath);
}
-static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *opts)
+static bool save_image_op(
+ Main *bmain, Image *ima, ImageUser *iuser, wmOperator *op, ImageSaveOptions *opts)
{
- Main *bmain = CTX_data_main(C);
- Image *ima = image_from_context(C);
- ImageUser *iuser = image_user_from_context(C);
-
opts->relative = (RNA_struct_find_property(op->ptr, "relative_path") &&
RNA_boolean_get(op->ptr, "relative_path"));
opts->save_copy = (RNA_struct_find_property(op->ptr, "copy") &&
@@ -2061,7 +1845,7 @@ static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *o
/* Remember file path for next save. */
BLI_strncpy(G.ima, opts->filepath, sizeof(G.ima));
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ WM_main_add_notifier(NC_IMAGE | NA_EDITED, ima);
return ok;
}
@@ -2069,8 +1853,8 @@ static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *o
static void image_save_as_free(wmOperator *op)
{
if (op->customdata) {
- ImageFormatData *im_format = (ImageFormatData *)op->customdata;
- BKE_color_managed_view_settings_free(&im_format->view_settings);
+ ImageSaveData *isd = op->customdata;
+ BKE_color_managed_view_settings_free(&isd->im_format.view_settings);
MEM_freeN(op->customdata);
op->customdata = NULL;
@@ -2081,20 +1865,32 @@ static int image_save_as_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Image *image = image_from_context(C);
- ImageUser *iuser = image_user_from_context(C);
ImageSaveOptions opts;
+ Image *image = NULL;
+ ImageUser *iuser = NULL;
+ ImageFormatData *imf = NULL;
+ if (op->customdata) {
+ ImageSaveData *isd = op->customdata;
+ image = isd->image;
+ iuser = isd->iuser;
+ imf = &isd->im_format;
+ }
+ else {
+ image = image_from_context(C);
+ iuser = image_user_from_context(C);
+ }
+
BKE_image_save_options_init(&opts, bmain, scene);
/* just in case to initialize values,
* these should be set on invoke or by the caller. */
image_save_options_init(bmain, &opts, image, iuser, false, false);
- image_save_options_from_op(bmain, &opts, op);
+ image_save_options_from_op(bmain, &opts, op, imf);
opts.do_newpath = true;
- save_image_op(C, op, &opts);
+ save_image_op(bmain, image, iuser, op, &opts);
if (opts.save_copy == false) {
BKE_image_free_packedfiles(image);
@@ -2107,8 +1903,8 @@ static int image_save_as_exec(bContext *C, wmOperator *op)
static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op)
{
- ImageFormatData *imf = op->customdata;
- return WM_operator_filesel_ensure_ext_imtype(op, imf);
+ ImageSaveData *isd = op->customdata;
+ return WM_operator_filesel_ensure_ext_imtype(op, &isd->im_format);
}
static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
@@ -2140,8 +1936,12 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
RNA_boolean_set(op->ptr, "save_as_render", save_as_render);
- op->customdata = MEM_mallocN(sizeof(opts.im_format), __func__);
- memcpy(op->customdata, &opts.im_format, sizeof(opts.im_format));
+ ImageSaveData *isd = MEM_callocN(sizeof(*isd), __func__);
+ isd->image = ima;
+ isd->iuser = iuser;
+
+ memcpy(&isd->im_format, &opts.im_format, sizeof(opts.im_format));
+ op->customdata = isd;
/* show multiview save options only if image has multiviews */
prop = RNA_struct_find_property(op->ptr, "show_multiview");
@@ -2174,12 +1974,12 @@ static bool image_save_as_draw_check_prop(PointerRNA *ptr,
static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
{
uiLayout *layout = op->layout;
- ImageFormatData *imf = op->customdata;
+ ImageSaveData *isd = op->customdata;
PointerRNA imf_ptr, ptr;
const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview");
/* image template */
- RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->im_format, &imf_ptr);
uiTemplateImageSettings(layout, &imf_ptr, false);
/* main draw call */
@@ -2319,6 +2119,7 @@ static int image_save_exec(bContext *C, wmOperator *op)
ImageUser *iuser = image_user_from_context(C);
Scene *scene = CTX_data_scene(C);
ImageSaveOptions opts;
+ bool ok = false;
if (BKE_image_has_packedfile(image)) {
/* Save packed files to memory. */
@@ -2330,21 +2131,28 @@ static int image_save_exec(bContext *C, wmOperator *op)
if (image_save_options_init(bmain, &opts, image, iuser, false, false) == 0) {
return OPERATOR_CANCELLED;
}
- image_save_options_from_op(bmain, &opts, op);
+ image_save_options_from_op(bmain, &opts, op, NULL);
if (BLI_exists(opts.filepath) && BLI_file_is_writable(opts.filepath)) {
- if (save_image_op(C, op, &opts)) {
+ if (save_image_op(bmain, image, iuser, op, &opts)) {
/* report since this can be called from key-shortcuts */
BKE_reportf(op->reports, RPT_INFO, "Saved Image '%s'", opts.filepath);
+ ok = true;
}
}
else {
BKE_reportf(
op->reports, RPT_ERROR, "Cannot save image, path '%s' is not writable", opts.filepath);
- return OPERATOR_CANCELLED;
}
- return OPERATOR_FINISHED;
+ BKE_color_managed_view_settings_free(&opts.im_format.view_settings);
+
+ if (ok) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
@@ -2486,7 +2294,7 @@ static bool image_should_be_saved_when_modified(Image *ima)
static bool image_should_be_saved(Image *ima, bool *is_format_writable)
{
if (BKE_image_is_dirty_writable(ima, is_format_writable) &&
- (ima->source == IMA_SRC_FILE || ima->source == IMA_SRC_GENERATED)) {
+ ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_GENERATED, IMA_SRC_TILED)) {
return image_should_be_saved_when_modified(ima);
}
else {
@@ -2499,12 +2307,12 @@ static bool image_has_valid_path(Image *ima)
return strchr(ima->name, '\\') || strchr(ima->name, '/');
}
-bool ED_image_should_save_modified(const bContext *C)
+bool ED_image_should_save_modified(const Main *bmain)
{
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);
- uint modified_images_count = ED_image_save_all_modified_info(C, &reports);
+ uint modified_images_count = ED_image_save_all_modified_info(bmain, &reports);
bool should_save = modified_images_count || !BLI_listbase_is_empty(&reports.list);
BKE_reports_clear(&reports);
@@ -2512,9 +2320,8 @@ bool ED_image_should_save_modified(const bContext *C)
return should_save;
}
-int ED_image_save_all_modified_info(const bContext *C, ReportList *reports)
+int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports)
{
- Main *bmain = CTX_data_main(C);
GSet *unique_paths = BLI_gset_str_new(__func__);
int num_saveable_images = 0;
@@ -2530,7 +2337,7 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports)
else {
BKE_reportf(reports,
RPT_WARNING,
- "Packed library image: %s from library %s can't be saved",
+ "Packed library image can't be saved: \"%s\" from \"%s\"",
ima->id.name + 2,
ima->id.lib->name);
}
@@ -2538,7 +2345,7 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports)
else if (!is_format_writable) {
BKE_reportf(reports,
RPT_WARNING,
- "Image %s can't be saved automatically, must use a different file format",
+ "Image can't be saved, use a different file format: \"%s\"",
ima->id.name + 2);
}
else {
@@ -2547,7 +2354,7 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports)
if (BLI_gset_haskey(unique_paths, ima->name)) {
BKE_reportf(reports,
RPT_WARNING,
- "File path used by more than one saved image: %s",
+ "Multiple images can't be saved to an identical path: \"%s\"",
ima->name);
}
else {
@@ -2555,11 +2362,8 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports)
}
}
else {
- BKE_reportf(reports,
- RPT_WARNING,
- "Image %s can't be saved, no valid file path: %s",
- ima->id.name + 2,
- ima->name);
+ BKE_reportf(
+ reports, RPT_WARNING, "Image can't be saved, no valid file path: \"%s\"", ima->name);
}
}
}
@@ -2571,9 +2375,10 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports)
bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
{
- ED_image_save_all_modified_info(C, reports);
-
Main *bmain = CTX_data_main(C);
+
+ ED_image_save_all_modified_info(bmain, reports);
+
bool ok = true;
for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
@@ -2601,7 +2406,7 @@ bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
static bool image_save_all_modified_poll(bContext *C)
{
- int num_files = ED_image_save_all_modified_info(C, NULL);
+ int num_files = ED_image_save_all_modified_info(CTX_data_main(C), NULL);
return num_files > 0;
}
@@ -2797,7 +2602,7 @@ static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e
/* Better for user feedback. */
RNA_string_set(op->ptr, "name", DATA_(IMA_DEF_NAME));
- return WM_operator_props_dialog_popup(C, op, 300, 100);
+ return WM_operator_props_dialog_popup(C, op, 300);
}
static void image_new_draw(bContext *UNUSED(C), wmOperator *op)
@@ -2929,7 +2734,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, 0);
+ ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser);
if (is_paint) {
ED_imapaint_clear_partial_redraw();
@@ -3011,7 +2816,7 @@ void IMAGE_OT_invert(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_invert_exec;
- ot->poll = image_from_contect_has_data_poll_no_image_user;
+ ot->poll = image_from_context_has_data_poll_no_image_user;
/* properties */
prop = RNA_def_boolean(ot->srna, "invert_r", 0, "Red", "Invert Red Channel");
@@ -3043,7 +2848,7 @@ static int image_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED
RNA_property_int_set_array(op->ptr, prop, size);
BKE_image_release_ibuf(ima, ibuf, NULL);
}
- return WM_operator_props_dialog_popup(C, op, 200, 200);
+ return WM_operator_props_dialog_popup(C, op, 200);
}
static int image_scale_exec(bContext *C, wmOperator *op)
@@ -3073,7 +2878,7 @@ static int image_scale_exec(bContext *C, wmOperator *op)
RNA_property_int_set_array(op->ptr, prop, size);
}
- ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, 0);
+ ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser);
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
IMB_scaleImBuf(ibuf, size[0], size[1]);
@@ -3100,7 +2905,7 @@ void IMAGE_OT_resize(wmOperatorType *ot)
/* api callbacks */
ot->invoke = image_scale_invoke;
ot->exec = image_scale_exec;
- ot->poll = image_from_contect_has_data_poll_no_image_user;
+ ot->poll = image_from_context_has_data_poll_no_image_user;
/* properties */
RNA_def_int_vector(ot->srna, "size", 2, NULL, 1, INT_MAX, "Size", "", 1, SHRT_MAX);
@@ -3124,7 +2929,8 @@ static bool image_pack_test(bContext *C, wmOperator *op)
}
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported");
+ BKE_report(
+ op->reports, RPT_ERROR, "Packing movies, image sequences or tiled images not supported");
return 0;
}
@@ -3174,14 +2980,15 @@ void IMAGE_OT_pack(wmOperatorType *ot)
static int image_unpack_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Image *ima = image_from_context(C);
int method = RNA_enum_get(op->ptr, "method");
- /* find the suppplied image by name */
+ /* find the supplied image by name */
if (RNA_struct_property_is_set(op->ptr, "id")) {
char imaname[MAX_ID_NAME - 2];
RNA_string_get(op->ptr, "id", imaname);
- ima = BLI_findstring(&CTX_data_main(C)->images, imaname, offsetof(ID, name) + 2);
+ ima = BLI_findstring(&bmain->images, imaname, offsetof(ID, name) + 2);
if (!ima) {
ima = image_from_context(C);
}
@@ -3192,7 +2999,8 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
}
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
+ BKE_report(
+ op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
return OPERATOR_CANCELLED;
}
@@ -3225,7 +3033,8 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
}
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
+ BKE_report(
+ op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
return OPERATOR_CANCELLED;
}
@@ -3275,92 +3084,14 @@ void IMAGE_OT_unpack(wmOperatorType *ot)
/** \name Sample Image Operator
* \{ */
-typedef struct ImageSampleInfo {
- ARegionType *art;
- void *draw_handle;
- int x, y;
- int channels;
-
- int width, height;
- int sample_size;
-
- unsigned char col[4];
- float colf[4];
- float linearcol[4];
- int z;
- float zf;
-
- unsigned char *colp;
- const float *colfp;
- int *zp;
- float *zfp;
-
- bool draw;
- bool color_manage;
- int use_default_view;
-} ImageSampleInfo;
-
-static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info)
-{
- ImageSampleInfo *info = arg_info;
- if (!info->draw) {
- return;
- }
-
- Scene *scene = CTX_data_scene(C);
- ED_image_draw_info(scene,
- ar,
- info->color_manage,
- info->use_default_view,
- info->channels,
- info->x,
- info->y,
- info->colp,
- info->colfp,
- info->linearcol,
- info->zp,
- info->zfp);
-
- if (info->sample_size > 1) {
- const wmWindow *win = CTX_wm_window(C);
- const wmEvent *event = win->eventstate;
-
- SpaceImage *sima = CTX_wm_space_image(C);
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- const float color[3] = {1, 1, 1};
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor3fv(color);
-
- /* TODO(campbell): lock to pixels. */
- rctf sample_rect_fl;
- BLI_rctf_init_pt_radius(&sample_rect_fl,
- (float[2]){event->x - ar->winrct.xmin, event->y - ar->winrct.ymin},
- (float)(info->sample_size / 2.0f) * sima->zoom);
-
- glEnable(GL_COLOR_LOGIC_OP);
- glLogicOp(GL_XOR);
- GPU_line_width(1.0f);
- imm_draw_box_wire_2d(pos,
- (float)sample_rect_fl.xmin,
- (float)sample_rect_fl.ymin,
- (float)sample_rect_fl.xmax,
- (float)sample_rect_fl.ymax);
- glDisable(GL_COLOR_LOGIC_OP);
-
- immUnbindProgram();
- }
-}
-
/* Returns color in linear space, matching ED_space_node_color_sample(). */
-bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], float r_col[3])
+bool ED_space_image_color_sample(SpaceImage *sima, ARegion *region, int mval[2], float r_col[3])
{
if (sima->image == NULL) {
return false;
}
float uv[2];
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &uv[0], &uv[1]);
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &uv[0], &uv[1]);
int tile = BKE_image_get_tile_from_pos(sima->image, uv, uv, NULL);
void *lock;
@@ -3374,7 +3105,7 @@ bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], flo
if (uv[0] >= 0.0f && uv[1] >= 0.0f && uv[0] < 1.0f && uv[1] < 1.0f) {
const float *fp;
- unsigned char *cp;
+ uchar *cp;
int x = (int)(uv[0] * ibuf->x), y = (int)(uv[1] * ibuf->y);
CLAMP(x, 0, ibuf->x - 1);
@@ -3386,7 +3117,7 @@ bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], flo
ret = true;
}
else if (ibuf->rect) {
- cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
+ cp = (uchar *)(ibuf->rect + y * ibuf->x + x);
rgb_uchar_to_float(r_col, cp);
IMB_colormanagement_colorspace_to_scene_linear_v3(r_col, ibuf->rect_colorspace);
ret = true;
@@ -3397,279 +3128,6 @@ bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], flo
return ret;
}
-/* -------------------------------------------------------------------- */
-/** \name Image Pixel Sample
- * \{ */
-
-static void image_sample_pixel_color_ubyte(const ImBuf *ibuf,
- const int coord[2],
- uchar r_col[4],
- float r_col_linear[4])
-{
- const uchar *cp = (unsigned char *)(ibuf->rect + coord[1] * ibuf->x + coord[0]);
- copy_v4_v4_uchar(r_col, cp);
- rgba_uchar_to_float(r_col_linear, r_col);
- IMB_colormanagement_colorspace_to_scene_linear_v4(r_col_linear, false, ibuf->rect_colorspace);
-}
-
-static void image_sample_pixel_color_float(ImBuf *ibuf, const int coord[2], float r_col[4])
-{
- const float *cp = ibuf->rect_float + (ibuf->channels) * (coord[1] * ibuf->x + coord[0]);
- copy_v4_v4(r_col, cp);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Image Pixel Region Sample
- * \{ */
-
-static void image_sample_rect_color_ubyte(const ImBuf *ibuf,
- const rcti *rect,
- uchar r_col[4],
- float r_col_linear[4])
-{
- uint col_accum_ub[4] = {0, 0, 0, 0};
- zero_v4(r_col_linear);
- int col_tot = 0;
- int coord[2];
- for (coord[0] = rect->xmin; coord[0] <= rect->xmax; coord[0]++) {
- for (coord[1] = rect->ymin; coord[1] <= rect->ymax; coord[1]++) {
- float col_temp_fl[4];
- uchar col_temp_ub[4];
- image_sample_pixel_color_ubyte(ibuf, coord, col_temp_ub, col_temp_fl);
- add_v4_v4(r_col_linear, col_temp_fl);
- col_accum_ub[0] += (uint)col_temp_ub[0];
- col_accum_ub[1] += (uint)col_temp_ub[1];
- col_accum_ub[2] += (uint)col_temp_ub[2];
- col_accum_ub[3] += (uint)col_temp_ub[3];
- col_tot += 1;
- }
- }
- mul_v4_fl(r_col_linear, 1.0 / (float)col_tot);
-
- r_col[0] = MIN2(col_accum_ub[0] / col_tot, 255);
- r_col[1] = MIN2(col_accum_ub[1] / col_tot, 255);
- r_col[2] = MIN2(col_accum_ub[2] / col_tot, 255);
- r_col[3] = MIN2(col_accum_ub[3] / col_tot, 255);
-}
-
-static void image_sample_rect_color_float(ImBuf *ibuf, const rcti *rect, float r_col[4])
-{
- zero_v4(r_col);
- int col_tot = 0;
- int coord[2];
- for (coord[0] = rect->xmin; coord[0] <= rect->xmax; coord[0]++) {
- for (coord[1] = rect->ymin; coord[1] <= rect->ymax; coord[1]++) {
- float col_temp_fl[4];
- image_sample_pixel_color_float(ibuf, coord, col_temp_fl);
- add_v4_v4(r_col, col_temp_fl);
- col_tot += 1;
- }
- }
- mul_v4_fl(r_col, 1.0 / (float)col_tot);
-}
-
-/** \} */
-
-static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
-{
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
- Image *image = ED_space_image(sima);
-
- float uv[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &uv[0], &uv[1]);
- int tile = BKE_image_get_tile_from_pos(sima->image, uv, uv, NULL);
-
- void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile);
- ImageSampleInfo *info = op->customdata;
- Scene *scene = CTX_data_scene(C);
- CurveMapping *curve_mapping = scene->view_settings.curve_mapping;
-
- if (ibuf == NULL) {
- ED_space_image_release_buffer(sima, ibuf, lock);
- info->draw = false;
- return;
- }
-
- if (uv[0] >= 0.0f && uv[1] >= 0.0f && uv[0] < 1.0f && uv[1] < 1.0f) {
- int x = (int)(uv[0] * ibuf->x), y = (int)(uv[1] * ibuf->y);
-
- CLAMP(x, 0, ibuf->x - 1);
- CLAMP(y, 0, ibuf->y - 1);
-
- info->width = ibuf->x;
- info->height = ibuf->y;
- info->x = x;
- info->y = y;
-
- info->draw = true;
- info->channels = ibuf->channels;
-
- info->colp = NULL;
- info->colfp = NULL;
- info->zp = NULL;
- info->zfp = NULL;
-
- info->use_default_view = (image->flag & IMA_VIEW_AS_RENDER) ? false : true;
-
- rcti sample_rect;
- sample_rect.xmin = max_ii(0, x - info->sample_size / 2);
- sample_rect.ymin = max_ii(0, y - info->sample_size / 2);
- sample_rect.xmax = min_ii(ibuf->x, sample_rect.xmin + info->sample_size) - 1;
- sample_rect.ymax = min_ii(ibuf->y, sample_rect.ymin + info->sample_size) - 1;
-
- if (ibuf->rect) {
- image_sample_rect_color_ubyte(ibuf, &sample_rect, info->col, info->linearcol);
- rgba_uchar_to_float(info->colf, info->col);
-
- info->colp = info->col;
- info->colfp = info->colf;
- info->color_manage = true;
- }
- if (ibuf->rect_float) {
- image_sample_rect_color_float(ibuf, &sample_rect, info->colf);
-
- if (ibuf->channels == 4) {
- /* pass */
- }
- else if (ibuf->channels == 3) {
- info->colf[3] = 1.0f;
- }
- else {
- info->colf[1] = info->colf[0];
- info->colf[2] = info->colf[0];
- info->colf[3] = 1.0f;
- }
- info->colfp = info->colf;
-
- copy_v4_v4(info->linearcol, info->colf);
-
- info->color_manage = true;
- }
-
- if (ibuf->zbuf) {
- /* TODO, blend depth (not urgent). */
- info->z = ibuf->zbuf[y * ibuf->x + x];
- info->zp = &info->z;
- if (ibuf->zbuf == (int *)ibuf->rect) {
- info->colp = NULL;
- }
- }
- if (ibuf->zbuf_float) {
- /* TODO, blend depth (not urgent). */
- info->zf = ibuf->zbuf_float[y * ibuf->x + x];
- info->zfp = &info->zf;
- if (ibuf->zbuf_float == ibuf->rect_float) {
- info->colfp = NULL;
- }
- }
-
- if (curve_mapping && ibuf->channels == 4) {
- /* we reuse this callback for set curves point operators */
- if (RNA_struct_find_property(op->ptr, "point")) {
- int point = RNA_enum_get(op->ptr, "point");
-
- if (point == 1) {
- BKE_curvemapping_set_black_white(curve_mapping, NULL, info->linearcol);
- }
- else if (point == 0) {
- BKE_curvemapping_set_black_white(curve_mapping, info->linearcol, NULL);
- }
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- }
- }
-
- // XXX node curve integration ..
-#if 0
- {
- ScrArea *sa, *cur = curarea;
-
- node_curvemap_sample(fp); /* sends global to node editor */
- for (sa = G.curscreen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_NODE) {
- areawinset(sa->win);
- scrarea_do_windraw(sa);
- }
- }
- node_curvemap_sample(NULL); /* clears global in node editor */
- curarea = cur;
- }
-#endif
- }
- else {
- info->draw = 0;
- }
-
- ED_space_image_release_buffer(sima, ibuf, lock);
- ED_area_tag_redraw(CTX_wm_area(C));
-}
-
-static void image_sample_exit(bContext *C, wmOperator *op)
-{
- ImageSampleInfo *info = op->customdata;
-
- ED_region_draw_cb_exit(info->art, info->draw_handle);
- ED_area_tag_redraw(CTX_wm_area(C));
- MEM_freeN(info);
-}
-
-static int image_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
- ImageSampleInfo *info;
-
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- if (event->mval[1] <= 16 && ED_space_image_show_cache(sima)) {
- return OPERATOR_PASS_THROUGH;
- }
- }
-
- if (!ED_space_image_has_buffer(sima)) {
- return OPERATOR_CANCELLED;
- }
-
- info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
-
- info->art = ar->type;
- info->draw_handle = ED_region_draw_cb_activate(
- ar->type, image_sample_draw, info, REGION_DRAW_POST_PIXEL);
- info->sample_size = RNA_int_get(op->ptr, "size");
- op->customdata = info;
-
- image_sample_apply(C, op, event);
-
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int image_sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- switch (event->type) {
- case LEFTMOUSE:
- case RIGHTMOUSE: // XXX hardcoded
- if (event->val == KM_RELEASE) {
- image_sample_exit(C, op);
- return OPERATOR_CANCELLED;
- }
- break;
- case MOUSEMOVE:
- image_sample_apply(C, op, event);
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void image_sample_cancel(bContext *C, wmOperator *op)
-{
- image_sample_exit(C, op);
-}
-
void IMAGE_OT_sample(wmOperatorType *ot)
{
/* identifiers */
@@ -3678,10 +3136,10 @@ void IMAGE_OT_sample(wmOperatorType *ot)
ot->description = "Use mouse to sample a color in current image";
/* api callbacks */
- ot->invoke = image_sample_invoke;
- ot->modal = image_sample_modal;
- ot->cancel = image_sample_cancel;
- ot->poll = image_sample_poll;
+ ot->invoke = ED_imbuf_sample_invoke;
+ ot->modal = ED_imbuf_sample_modal;
+ ot->cancel = ED_imbuf_sample_cancel;
+ ot->poll = ED_imbuf_sample_poll;
/* flags */
ot->flag = OPTYPE_BLOCKING;
@@ -3701,7 +3159,7 @@ void IMAGE_OT_sample(wmOperatorType *ot)
static int image_sample_line_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
Image *ima = ED_space_image(sima);
@@ -3711,8 +3169,8 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
int y_end = RNA_int_get(op->ptr, "yend");
float uv1[2], uv2[2], ofs[2];
- UI_view2d_region_to_view(&ar->v2d, x_start, y_start, &uv1[0], &uv1[1]);
- UI_view2d_region_to_view(&ar->v2d, x_end, y_end, &uv2[0], &uv2[1]);
+ UI_view2d_region_to_view(&region->v2d, x_start, y_start, &uv1[0], &uv1[1]);
+ UI_view2d_region_to_view(&region->v2d, x_end, y_end, &uv2[0], &uv2[1]);
/* If the image has tiles, shift the positions accordingly. */
int tile = BKE_image_get_tile_from_pos(ima, uv1, uv1, ofs);
@@ -3807,9 +3265,9 @@ void IMAGE_OT_curves_point_set(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
- ot->invoke = image_sample_invoke;
- ot->modal = image_sample_modal;
- ot->cancel = image_sample_cancel;
+ ot->invoke = ED_imbuf_sample_invoke;
+ ot->modal = ED_imbuf_sample_modal;
+ ot->cancel = ED_imbuf_sample_cancel;
ot->poll = space_image_main_area_not_uv_brush_poll;
/* properties */
@@ -4014,19 +3472,19 @@ static int change_frame_exec(bContext *C, wmOperator *op)
static int frame_from_event(bContext *C, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
int framenr = 0;
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ float sfra = SFRA, efra = EFRA, framelen = region->winx / (efra - sfra + 1);
framenr = sfra + event->mval[0] / framelen;
}
else {
float viewx, viewy;
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
framenr = round_fl_to_int(viewx);
}
@@ -4036,13 +3494,13 @@ static int frame_from_event(bContext *C, const wmEvent *event)
static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- if (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
SpaceImage *sima = CTX_wm_space_image(C);
/* Local coordinate visible rect inside region, to accommodate overlapping ui. */
- const rcti *rect_visible = ED_region_visible_rect(ar);
+ const rcti *rect_visible = ED_region_visible_rect(region);
const int region_bottom = rect_visible->ymin;
if (event->mval[1] > (region_bottom + 16 * UI_DPI_FAC) || !ED_space_image_show_cache(sima)) {
@@ -4063,7 +3521,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
return OPERATOR_FINISHED;
case MOUSEMOVE:
@@ -4111,7 +3569,7 @@ static int image_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
SpaceImage *sima = CTX_wm_space_image(C);
Image *ima;
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
+ ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
if (sima->image == NULL) {
ED_space_image_set(bmain, sima, NULL, ima, false);
}
@@ -4143,7 +3601,7 @@ void IMAGE_OT_read_viewlayers(wmOperatorType *ot)
static int render_border_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
Render *re = RE_GetSceneRender(scene);
RenderData *rd;
@@ -4162,7 +3620,7 @@ static int render_border_exec(bContext *C, wmOperator *op)
/* get rectangle from operator */
WM_operator_properties_border_to_rctf(op, &border);
- UI_view2d_region_to_view_rctf(&ar->v2d, &border, &border);
+ UI_view2d_region_to_view_rctf(&region->v2d, &border, &border);
/* actually set border */
CLAMP(border.xmin, 0.0f, 1.0f);
@@ -4240,7 +3698,9 @@ void IMAGE_OT_clear_render_border(wmOperatorType *ot)
/** \} */
-/* ********************* Add tile operator ****************** */
+/* -------------------------------------------------------------------- */
+/** \name Add Tile Operator
+ * \{ */
static bool do_fill_tile(PointerRNA *ptr, Image *ima, ImageTile *tile)
{
@@ -4346,7 +3806,13 @@ static int tile_add_exec(bContext *C, wmOperator *op)
Image *ima = CTX_data_edit_image(C);
int start_tile = RNA_int_get(op->ptr, "number");
- int end_tile = min_ii(start_tile + RNA_int_get(op->ptr, "count"), IMA_UDIM_MAX);
+ int end_tile = start_tile + RNA_int_get(op->ptr, "count");
+
+ if (start_tile < 1001 || end_tile > IMA_UDIM_MAX) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid UDIM index range was specified");
+ return OPERATOR_CANCELLED;
+ }
+
bool fill_tile = RNA_boolean_get(op->ptr, "fill");
char *label = RNA_string_get_alloc(op->ptr, "label", NULL, 0);
@@ -4395,7 +3861,7 @@ static int tile_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(ev
RNA_int_set(op->ptr, "count", 1);
RNA_string_set(op->ptr, "label", "");
- return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y);
+ return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X);
}
static void tile_add_draw(bContext *UNUSED(C), wmOperator *op)
@@ -4442,15 +3908,26 @@ void IMAGE_OT_tile_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(
- ot->srna, "number", 1002, 1001, INT_MAX, "Number", "UDIM number of the tile", 1001, 1099);
+ RNA_def_int(ot->srna,
+ "number",
+ 1002,
+ 1001,
+ IMA_UDIM_MAX,
+ "Number",
+ "UDIM number of the tile",
+ 1001,
+ 1099);
RNA_def_int(ot->srna, "count", 1, 1, INT_MAX, "Count", "How many tiles to add", 1, 1000);
RNA_def_string(ot->srna, "label", NULL, 0, "Label", "Optional tile label");
RNA_def_boolean(ot->srna, "fill", true, "Fill", "Fill new tile with a generated image");
def_fill_tile(ot->srna);
}
-/* ********************* Remove tile operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Remove Tile Operator
+ * \{ */
static bool tile_remove_poll(bContext *C)
{
@@ -4491,7 +3968,11 @@ void IMAGE_OT_tile_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************* Fill tile operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Fill Tile Operator
+ * \{ */
static bool tile_fill_poll(bContext *C)
{
@@ -4522,7 +4003,7 @@ static int tile_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e
{
initialize_fill_tile(op->ptr, CTX_data_edit_image(C), NULL);
- return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y);
+ return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X);
}
static void tile_fill_draw(bContext *UNUSED(C), wmOperator *op)
diff --git a/source/blender/editors/space_image/image_sequence.c b/source/blender/editors/space_image/image_sequence.c
new file mode 100644
index 00000000000..0817bdda88d
--- /dev/null
+++ b/source/blender/editors/space_image/image_sequence.c
@@ -0,0 +1,255 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup spimage
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_fileops.h"
+#include "BLI_fileops_types.h"
+#include "BLI_linklist.h"
+#include "BLI_listbase.h"
+#include "BLI_math_base.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_image_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+
+#include "BKE_image.h"
+#include "BKE_main.h"
+
+#include "ED_image.h"
+
+#include "WM_types.h"
+
+typedef struct ImageFrame {
+ struct ImageFrame *next, *prev;
+ int framenr;
+} ImageFrame;
+
+/**
+ * Get a list of frames from the list of image files matching the first file
+ * name sequence pattern. The files and directory are read from standard
+ * fileselect operator properties.
+ *
+ * The output is a list of frame ranges, each containing a list of frames with matching names.
+ */
+static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges)
+{
+ char dir[FILE_MAXDIR];
+ const bool do_frame_range = RNA_boolean_get(op->ptr, "use_sequence_detection");
+ ImageFrameRange *range = NULL;
+ int range_first_frame = 0;
+
+ RNA_string_get(op->ptr, "directory", dir);
+ RNA_BEGIN (op->ptr, itemptr, "files") {
+ char base_head[FILE_MAX], base_tail[FILE_MAX];
+ char head[FILE_MAX], tail[FILE_MAX];
+ ushort digits;
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
+
+ /* use the first file in the list as base filename */
+ frame->framenr = BLI_path_sequence_decode(filename, head, tail, &digits);
+
+ /* still in the same sequence */
+ if (do_frame_range && (range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) &&
+ (STREQLEN(base_tail, tail, FILE_MAX))) {
+ /* Set filepath to first frame in the range. */
+ if (frame->framenr < range_first_frame) {
+ BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename);
+ range_first_frame = frame->framenr;
+ }
+ }
+ else {
+ /* start a new frame range */
+ range = MEM_callocN(sizeof(*range), __func__);
+ BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename);
+ BLI_addtail(ranges, range);
+
+ BLI_strncpy(base_head, head, sizeof(base_head));
+ BLI_strncpy(base_tail, tail, sizeof(base_tail));
+
+ range_first_frame = frame->framenr;
+ }
+
+ BLI_addtail(&range->frames, frame);
+ MEM_freeN(filename);
+ }
+ RNA_END;
+}
+
+static int image_cmp_frame(const void *a, const void *b)
+{
+ const ImageFrame *frame_a = a;
+ const ImageFrame *frame_b = b;
+
+ if (frame_a->framenr < frame_b->framenr) {
+ return -1;
+ }
+ if (frame_a->framenr > frame_b->framenr) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Checks whether the given filepath refers to a UDIM texture.
+ * If yes, the range from 1001 to the highest tile is returned, otherwise 0.
+ *
+ * If the result is positive, the filepath will be overwritten with that of
+ * the 1001 tile.
+ *
+ * udim_tiles may get filled even if the result ultimately is false!
+ */
+static int image_get_udim(char *filepath, ListBase *udim_tiles)
+{
+ char filename[FILE_MAX], dirname[FILE_MAXDIR];
+ BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
+
+ ushort digits;
+ char base_head[FILE_MAX], base_tail[FILE_MAX];
+ int id = BLI_path_sequence_decode(filename, base_head, base_tail, &digits);
+
+ if (id < 1001 || id >= IMA_UDIM_MAX) {
+ return 0;
+ }
+
+ bool is_udim = true;
+ bool has_primary = false;
+ int max_udim = 0;
+
+ struct direntry *dir;
+ uint totfile = BLI_filelist_dir_contents(dirname, &dir);
+ for (int i = 0; i < totfile; i++) {
+ if (!(dir[i].type & S_IFREG)) {
+ continue;
+ }
+ char head[FILE_MAX], tail[FILE_MAX];
+ id = BLI_path_sequence_decode(dir[i].relname, head, tail, &digits);
+
+ if (digits > 4 || !(STREQLEN(base_head, head, FILE_MAX)) ||
+ !(STREQLEN(base_tail, tail, FILE_MAX))) {
+ continue;
+ }
+
+ if (id < 1001 || id >= IMA_UDIM_MAX) {
+ is_udim = false;
+ break;
+ }
+ if (id == 1001) {
+ has_primary = true;
+ }
+
+ BLI_addtail(udim_tiles, BLI_genericNodeN(POINTER_FROM_INT(id)));
+ max_udim = max_ii(max_udim, id);
+ }
+ BLI_filelist_free(dir, totfile);
+
+ if (is_udim && has_primary) {
+ char primary_filename[FILE_MAX];
+ BLI_path_sequence_encode(primary_filename, base_head, base_tail, digits, 1001);
+ BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename);
+ return max_udim - 1000;
+ }
+ return 0;
+}
+
+/**
+ * From a list of frames, compute the start (offset) and length of the sequence
+ * of contiguous frames. If UDIM is detect, it will return UDIM tiles as well.
+ */
+static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim)
+{
+ /* UDIM */
+ if (detect_udim) {
+ int len_udim = image_get_udim(range->filepath, &range->udim_tiles);
+
+ if (len_udim > 0) {
+ range->offset = 1001;
+ range->length = len_udim;
+ return;
+ }
+ }
+
+ /* Image Sequence */
+ BLI_listbase_sort(&range->frames, image_cmp_frame);
+
+ ImageFrame *frame = range->frames.first;
+ if (frame != NULL) {
+ int frame_curr = frame->framenr;
+ range->offset = frame_curr;
+
+ while (frame != NULL && (frame->framenr == frame_curr)) {
+ frame_curr++;
+ frame = frame->next;
+ }
+
+ range->length = frame_curr - range->offset;
+ }
+ else {
+ range->length = 1;
+ range->offset = 0;
+ }
+}
+
+/* Used for both images and volume file loading. */
+ListBase ED_image_filesel_detect_sequences(Main *bmain, wmOperator *op, const bool detect_udim)
+{
+ ListBase ranges;
+ BLI_listbase_clear(&ranges);
+
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
+
+ /* File browser. */
+ if (RNA_struct_property_is_set(op->ptr, "directory") &&
+ RNA_struct_property_is_set(op->ptr, "files")) {
+ const bool was_relative = BLI_path_is_rel(filepath);
+
+ image_sequence_get_frame_ranges(op, &ranges);
+ LISTBASE_FOREACH (ImageFrameRange *, range, &ranges) {
+ image_detect_frame_range(range, detect_udim);
+ BLI_freelistN(&range->frames);
+
+ if (was_relative) {
+ BLI_path_rel(range->filepath, BKE_main_blendfile_path(bmain));
+ }
+ }
+ }
+ /* Filepath property for drag & drop etc. */
+ else {
+ ImageFrameRange *range = MEM_callocN(sizeof(*range), __func__);
+ BLI_addtail(&ranges, range);
+
+ BLI_strncpy(range->filepath, filepath, FILE_MAX);
+ image_detect_frame_range(range, detect_udim);
+ }
+
+ return ranges;
+}
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index 79aa4d2ed7f..eb1c46240cb 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -34,16 +34,16 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "BLI_threads.h"
+#include "BLI_utildefines.h"
#include "DNA_image_types.h"
-#include "DNA_windowmanager_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -55,10 +55,10 @@
#include "DEG_depsgraph.h"
+#include "ED_object.h"
#include "ED_paint.h"
#include "ED_undo.h"
#include "ED_util.h"
-#include "ED_object.h"
#include "GPU_draw.h"
@@ -107,7 +107,11 @@ typedef struct PaintTile {
struct PaintTile *next, *prev;
Image *image;
ImBuf *ibuf;
- int tile_number;
+ /* For 2D image painting the ImageUser uses most of the values.
+ * Even though views and passes are stored they are currently not supported for painting.
+ * For 3D projection painting this only uses a tile & frame number.
+ * The scene pointer must be cleared (or temporarily set it as needed, but leave cleared). */
+ ImageUser iuser;
union {
float *fp;
uint *uint;
@@ -141,7 +145,7 @@ static void ptile_free_list(ListBase *paint_tiles)
static void ptile_invalidate_list(ListBase *paint_tiles)
{
- for (PaintTile *ptile = paint_tiles->first; ptile; ptile = ptile->next) {
+ LISTBASE_FOREACH (PaintTile *, ptile, paint_tiles) {
ptile->valid = false;
}
}
@@ -149,19 +153,19 @@ static void ptile_invalidate_list(ListBase *paint_tiles)
void *ED_image_paint_tile_find(ListBase *paint_tiles,
Image *image,
ImBuf *ibuf,
- int tile_number,
+ ImageUser *iuser,
int x_tile,
int y_tile,
ushort **r_mask,
bool validate)
{
- for (PaintTile *ptile = paint_tiles->first; ptile; ptile = ptile->next) {
+ LISTBASE_FOREACH (PaintTile *, ptile, paint_tiles) {
if (ptile->x_tile == x_tile && ptile->y_tile == y_tile) {
- if (ptile->image == image && ptile->ibuf == ibuf && ptile->tile_number == tile_number) {
+ if (ptile->image == image && ptile->ibuf == ibuf && ptile->iuser.tile == iuser->tile) {
if (r_mask) {
/* allocate mask if requested. */
if (!ptile->mask) {
- ptile->mask = MEM_callocN(sizeof(ushort) * SQUARE(ED_IMAGE_UNDO_TILE_SIZE),
+ ptile->mask = MEM_callocN(sizeof(ushort) * square_i(ED_IMAGE_UNDO_TILE_SIZE),
"UndoImageTile.mask");
}
*r_mask = ptile->mask;
@@ -180,7 +184,7 @@ void *ED_image_paint_tile_push(ListBase *paint_tiles,
Image *image,
ImBuf *ibuf,
ImBuf **tmpibuf,
- int tile_number,
+ ImageUser *iuser,
int x_tile,
int y_tile,
ushort **r_mask,
@@ -195,7 +199,7 @@ void *ED_image_paint_tile_push(ListBase *paint_tiles,
/* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
if (find_prev) {
void *data = ED_image_paint_tile_find(
- paint_tiles, image, ibuf, tile_number, x_tile, y_tile, r_mask, true);
+ paint_tiles, image, ibuf, iuser, x_tile, y_tile, r_mask, true);
if (data) {
return data;
}
@@ -209,19 +213,20 @@ void *ED_image_paint_tile_push(ListBase *paint_tiles,
ptile->image = image;
ptile->ibuf = ibuf;
- ptile->tile_number = tile_number;
+ ptile->iuser = *iuser;
+ ptile->iuser.scene = NULL;
ptile->x_tile = x_tile;
ptile->y_tile = y_tile;
/* add mask explicitly here */
if (r_mask) {
- *r_mask = ptile->mask = MEM_callocN(sizeof(ushort) * SQUARE(ED_IMAGE_UNDO_TILE_SIZE),
+ *r_mask = ptile->mask = MEM_callocN(sizeof(ushort) * square_i(ED_IMAGE_UNDO_TILE_SIZE),
"PaintTile.mask");
}
ptile->rect.pt = MEM_mapallocN((ibuf->rect_float ? sizeof(float[4]) : sizeof(char[4])) *
- SQUARE(ED_IMAGE_UNDO_TILE_SIZE),
+ square_i(ED_IMAGE_UNDO_TILE_SIZE),
"PaintTile.rect");
ptile->use_float = has_float;
@@ -262,12 +267,9 @@ static void ptile_restore_runtime_list(ListBase *paint_tiles)
{
ImBuf *tmpibuf = imbuf_alloc_temp_tile();
- for (PaintTile *ptile = paint_tiles->first; ptile; ptile = ptile->next) {
+ LISTBASE_FOREACH (PaintTile *, ptile, paint_tiles) {
Image *image = ptile->image;
- ImageUser iuser;
- BKE_imageuser_default(&iuser);
- iuser.tile = ptile->tile_number;
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, NULL);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, &ptile->iuser, NULL);
const bool has_float = (ibuf->rect_float != NULL);
if (has_float) {
@@ -333,10 +335,10 @@ static UndoImageTile *utile_alloc(bool has_float)
{
UndoImageTile *utile = MEM_callocN(sizeof(*utile), "ImageUndoTile");
if (has_float) {
- utile->rect.fp = MEM_mallocN(sizeof(float[4]) * SQUARE(ED_IMAGE_UNDO_TILE_SIZE), __func__);
+ utile->rect.fp = MEM_mallocN(sizeof(float[4]) * square_i(ED_IMAGE_UNDO_TILE_SIZE), __func__);
}
else {
- utile->rect.uint = MEM_mallocN(sizeof(uint) * SQUARE(ED_IMAGE_UNDO_TILE_SIZE), __func__);
+ utile->rect.uint = MEM_mallocN(sizeof(uint) * square_i(ED_IMAGE_UNDO_TILE_SIZE), __func__);
}
return utile;
}
@@ -540,7 +542,7 @@ static void uhandle_restore_list(ListBase *undo_handles, bool use_init)
{
ImBuf *tmpibuf = imbuf_alloc_temp_tile();
- for (UndoImageHandle *uh = undo_handles->first; uh; uh = uh->next) {
+ LISTBASE_FOREACH (UndoImageHandle *, uh, undo_handles) {
/* Tiles only added to second set of tiles. */
Image *image = uh->image_ref.ptr;
@@ -550,7 +552,7 @@ static void uhandle_restore_list(ListBase *undo_handles, bool use_init)
continue;
}
bool changed = false;
- for (UndoImageBuf *ubuf_iter = uh->buffers.first; ubuf_iter; ubuf_iter = ubuf_iter->next) {
+ LISTBASE_FOREACH (UndoImageBuf *, ubuf_iter, &uh->buffers) {
UndoImageBuf *ubuf = use_init ? ubuf_iter : ubuf_iter->post;
ubuf_ensure_compat_ibuf(ubuf, ibuf);
@@ -609,7 +611,7 @@ static UndoImageBuf *uhandle_lookup_ubuf(UndoImageHandle *uh,
const Image *UNUSED(image),
const char *ibuf_name)
{
- for (UndoImageBuf *ubuf = uh->buffers.first; ubuf; ubuf = ubuf->next) {
+ LISTBASE_FOREACH (UndoImageBuf *, ubuf, &uh->buffers) {
if (STREQ(ubuf->ibuf_name, ibuf_name)) {
return ubuf;
}
@@ -641,7 +643,7 @@ static UndoImageHandle *uhandle_lookup_by_name(ListBase *undo_handles,
const Image *image,
int tile_number)
{
- for (UndoImageHandle *uh = undo_handles->first; uh; uh = uh->next) {
+ LISTBASE_FOREACH (UndoImageHandle *, uh, undo_handles) {
if (STREQ(image->id.name + 2, uh->image_ref.name + 2) && uh->iuser.tile == tile_number) {
return uh;
}
@@ -651,7 +653,7 @@ static UndoImageHandle *uhandle_lookup_by_name(ListBase *undo_handles,
static UndoImageHandle *uhandle_lookup(ListBase *undo_handles, const Image *image, int tile_number)
{
- for (UndoImageHandle *uh = undo_handles->first; uh; uh = uh->next) {
+ LISTBASE_FOREACH (UndoImageHandle *, uh, undo_handles) {
if (image == uh->image_ref.ptr && uh->iuser.tile == tile_number) {
return uh;
}
@@ -659,22 +661,23 @@ static UndoImageHandle *uhandle_lookup(ListBase *undo_handles, const Image *imag
return NULL;
}
-static UndoImageHandle *uhandle_add(ListBase *undo_handles, Image *image, int tile_number)
+static UndoImageHandle *uhandle_add(ListBase *undo_handles, Image *image, ImageUser *iuser)
{
- BLI_assert(uhandle_lookup(undo_handles, image, tile_number) == NULL);
+ BLI_assert(uhandle_lookup(undo_handles, image, iuser->tile) == NULL);
UndoImageHandle *uh = MEM_callocN(sizeof(*uh), __func__);
uh->image_ref.ptr = image;
+ uh->iuser = *iuser;
+ uh->iuser.scene = NULL;
uh->iuser.ok = 1;
- uh->iuser.tile = tile_number;
BLI_addtail(undo_handles, uh);
return uh;
}
-static UndoImageHandle *uhandle_ensure(ListBase *undo_handles, Image *image, int tile_number)
+static UndoImageHandle *uhandle_ensure(ListBase *undo_handles, Image *image, ImageUser *iuser)
{
- UndoImageHandle *uh = uhandle_lookup(undo_handles, image, tile_number);
+ UndoImageHandle *uh = uhandle_lookup(undo_handles, image, iuser->tile);
if (uh == NULL) {
- uh = uhandle_add(undo_handles, image, tile_number);
+ uh = uhandle_add(undo_handles, image, iuser);
}
return uh;
}
@@ -711,7 +714,7 @@ static UndoImageBuf *ubuf_lookup_from_reference(ImageUndoStep *us_prev,
int tile_number,
const UndoImageBuf *ubuf)
{
- /* Use name lookup because because the pointer is cleared for previous steps. */
+ /* Use name lookup because the pointer is cleared for previous steps. */
UndoImageHandle *uh_prev = uhandle_lookup_by_name(&us_prev->handles, image, tile_number);
if (uh_prev != NULL) {
UndoImageBuf *ubuf_reference = uhandle_lookup_ubuf(uh_prev, image, ubuf->ibuf_name);
@@ -730,9 +733,9 @@ static bool image_undosys_poll(bContext *C)
{
Object *obact = CTX_data_active_object(C);
- ScrArea *sa = CTX_wm_area(C);
- if (sa && (sa->spacetype == SPACE_IMAGE)) {
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
+ ScrArea *area = CTX_wm_area(C);
+ if (area && (area->spacetype == SPACE_IMAGE)) {
+ SpaceImage *sima = (SpaceImage *)area->spacedata.first;
if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
return true;
}
@@ -779,7 +782,7 @@ static bool image_undosys_step_encode(struct bContext *C,
/* Initialize undo tiles from ptiles (if they exist). */
for (PaintTile *ptile = us->paint_tiles.first, *ptile_next; ptile; ptile = ptile_next) {
if (ptile->valid) {
- UndoImageHandle *uh = uhandle_ensure(&us->handles, ptile->image, ptile->tile_number);
+ UndoImageHandle *uh = uhandle_ensure(&us->handles, ptile->image, &ptile->iuser);
UndoImageBuf *ubuf_pre = uhandle_ensure_ubuf(uh, ptile->image, ptile->ibuf);
UndoImageTile *utile = MEM_callocN(sizeof(*utile), "UndoImageTile");
@@ -796,8 +799,8 @@ static bool image_undosys_step_encode(struct bContext *C,
}
BLI_listbase_clear(&us->paint_tiles);
- for (UndoImageHandle *uh = us->handles.first; uh; uh = uh->next) {
- for (UndoImageBuf *ubuf_pre = uh->buffers.first; ubuf_pre; ubuf_pre = ubuf_pre->next) {
+ LISTBASE_FOREACH (UndoImageHandle *, uh, &us->handles) {
+ LISTBASE_FOREACH (UndoImageBuf *, ubuf_pre, &uh->buffers) {
ImBuf *ibuf = BKE_image_acquire_ibuf(uh->image_ref.ptr, &uh->iuser, NULL);
@@ -976,7 +979,7 @@ static void image_undosys_foreach_ID_ref(UndoStep *us_p,
void *user_data)
{
ImageUndoStep *us = (ImageUndoStep *)us_p;
- for (UndoImageHandle *uh = us->handles.first; uh; uh = uh->next) {
+ LISTBASE_FOREACH (UndoImageHandle *, uh, &us->handles) {
foreach_ID_ref_fn(user_data, ((UndoRefID *)&uh->image_ref));
}
}
@@ -1047,12 +1050,12 @@ void ED_image_undo_push_begin(const char *name, int paint_mode)
void ED_image_undo_push_begin_with_image(const char *name,
Image *image,
ImBuf *ibuf,
- int tile_number)
+ ImageUser *iuser)
{
ImageUndoStep *us = image_undo_push_begin(name, PAINT_MODE_TEXTURE_2D);
- BLI_assert(BKE_image_get_tile(image, tile_number));
- UndoImageHandle *uh = uhandle_ensure(&us->handles, image, tile_number);
+ BLI_assert(BKE_image_get_tile(image, iuser->tile));
+ UndoImageHandle *uh = uhandle_ensure(&us->handles, image, iuser);
UndoImageBuf *ubuf_pre = uhandle_ensure_ubuf(uh, image, ibuf);
BLI_assert(ubuf_pre->post == NULL);
@@ -1061,7 +1064,7 @@ void ED_image_undo_push_begin_with_image(const char *name,
us_reference = (ImageUndoStep *)us_reference->step.prev;
}
UndoImageBuf *ubuf_reference = (us_reference ? ubuf_lookup_from_reference(
- us_reference, image, tile_number, ubuf_pre) :
+ us_reference, image, iuser->tile, ubuf_pre) :
NULL);
if (ubuf_reference) {
@@ -1080,6 +1083,7 @@ void ED_image_undo_push_end(void)
{
UndoStack *ustack = ED_undo_stack_get();
BKE_undosys_step_push(ustack, NULL, NULL);
+ BKE_undosys_stack_limit_steps_and_memory_defaults(ustack);
WM_file_tag_modified();
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 57560c560d7..d7d85112497 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -22,12 +22,12 @@
*/
#include "DNA_gpencil_types.h"
-#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
#include "DNA_mask_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_image_types.h"
#include "MEM_guardedalloc.h"
@@ -40,7 +40,7 @@
#include "BKE_editmesh.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -59,23 +59,23 @@
#include "ED_mesh.h"
#include "ED_node.h"
#include "ED_render.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
-#include "ED_uvedit.h"
+#include "ED_space_api.h"
#include "ED_transform.h"
+#include "ED_uvedit.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
-#include "UI_resources.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "UI_view2d.h"
-#include "image_intern.h"
-#include "GPU_framebuffer.h"
#include "GPU_batch_presets.h"
+#include "GPU_framebuffer.h"
#include "GPU_viewport.h"
+#include "image_intern.h"
/* TODO(fclem) remove bad level calls */
#include "../draw/DRW_engine.h"
@@ -83,14 +83,14 @@
/**************************** common state *****************************/
-static void image_scopes_tag_refresh(ScrArea *sa)
+static void image_scopes_tag_refresh(ScrArea *area)
{
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
- ARegion *ar;
+ SpaceImage *sima = (SpaceImage *)area->spacedata.first;
+ ARegion *region;
/* only while histogram is visible */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_TOOL_PROPS && ar->flag & RGN_FLAG_HIDDEN) {
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_TOOL_PROPS && region->flag & RGN_FLAG_HIDDEN) {
return;
}
}
@@ -119,7 +119,7 @@ static void image_user_refresh_scene(const bContext *C, SpaceImage *sima)
static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceImage *simage;
simage = MEM_callocN(sizeof(SpaceImage), "initimage");
@@ -127,6 +127,7 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce
simage->zoom = 1.0f;
simage->lock = true;
simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS;
+ simage->uv_opacity = 1.0f;
BKE_imageuser_default(&simage->iuser);
simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS;
@@ -138,41 +139,41 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce
simage->tile_grid_shape[1] = 1;
/* tool header */
- ar = MEM_callocN(sizeof(ARegion), "tool header for image");
+ region = MEM_callocN(sizeof(ARegion), "tool header for image");
- BLI_addtail(&simage->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOL_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- ar->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
+ BLI_addtail(&simage->regionbase, region);
+ region->regiontype = RGN_TYPE_TOOL_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ region->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for image");
+ region = MEM_callocN(sizeof(ARegion), "header for image");
- BLI_addtail(&simage->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&simage->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* buttons/list view */
- ar = MEM_callocN(sizeof(ARegion), "buttons for image");
+ region = MEM_callocN(sizeof(ARegion), "buttons for image");
- BLI_addtail(&simage->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_RIGHT;
- ar->flag = RGN_FLAG_HIDDEN;
+ BLI_addtail(&simage->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_RIGHT;
+ region->flag = RGN_FLAG_HIDDEN;
/* scopes/uv sculpt/paint */
- ar = MEM_callocN(sizeof(ARegion), "buttons for image");
+ region = MEM_callocN(sizeof(ARegion), "buttons for image");
- BLI_addtail(&simage->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOLS;
- ar->alignment = RGN_ALIGN_LEFT;
- ar->flag = RGN_FLAG_HIDDEN;
+ BLI_addtail(&simage->regionbase, region);
+ region->regiontype = RGN_TYPE_TOOLS;
+ region->alignment = RGN_ALIGN_LEFT;
+ region->flag = RGN_FLAG_HIDDEN;
/* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for image");
+ region = MEM_callocN(sizeof(ARegion), "main area for image");
- BLI_addtail(&simage->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&simage->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
return (SpaceLink *)simage;
}
@@ -186,12 +187,12 @@ static void image_free(SpaceLink *sl)
}
/* spacetype; init callback, add handlers */
-static void image_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void image_init(struct wmWindowManager *UNUSED(wm), ScrArea *area)
{
ListBase *lb = WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
/* add drop boxes */
- WM_event_add_dropbox_handler(&sa->handlers, lb);
+ WM_event_add_dropbox_handler(&area->handlers, lb);
}
static SpaceLink *image_duplicate(SpaceLink *sl)
@@ -262,18 +263,22 @@ static void image_keymap(struct wmKeyConfig *keyconf)
}
/* dropboxes */
-static bool image_drop_poll(bContext *UNUSED(C),
+static bool image_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const wmEvent *event,
+ const char **UNUSED(r_tooltip))
{
+ ScrArea *area = CTX_wm_area(C);
+ if (ED_region_overlap_isect_any_xy(area, &event->x)) {
+ return false;
+ }
if (drag->type == WM_DRAG_PATH) {
/* rule might not work? */
if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) {
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
static void image_drop_copy(wmDrag *drag, wmDropBox *drop)
@@ -294,10 +299,10 @@ static void image_dropboxes(void)
* \note take care not to get into feedback loop here,
* calling composite job causes viewer to refresh.
*/
-static void image_refresh(const bContext *C, ScrArea *sa)
+static void image_refresh(const bContext *C, ScrArea *area)
{
Scene *scene = CTX_data_scene(C);
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
Image *ima;
ima = ED_space_image(sima);
@@ -314,53 +319,53 @@ static void image_refresh(const bContext *C, ScrArea *sa)
}
}
-static void image_listener(wmWindow *win, ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
+static void image_listener(wmWindow *win, ScrArea *area, wmNotifier *wmn, Scene *UNUSED(scene))
{
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
+ SpaceImage *sima = (SpaceImage *)area->spacedata.first;
/* context changes */
switch (wmn->category) {
case NC_WINDOW:
/* notifier comes from editing color space */
- image_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ image_scopes_tag_refresh(area);
+ ED_area_tag_redraw(area);
break;
case NC_SCENE:
switch (wmn->data) {
case ND_FRAME:
- image_scopes_tag_refresh(sa);
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ image_scopes_tag_refresh(area);
+ ED_area_tag_refresh(area);
+ ED_area_tag_redraw(area);
break;
case ND_MODE:
if (wmn->subtype == NS_EDITMODE_MESH) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case ND_RENDER_RESULT:
case ND_RENDER_OPTIONS:
case ND_COMPO_RESULT:
if (ED_space_image_show_render(sima)) {
- image_scopes_tag_refresh(sa);
+ image_scopes_tag_refresh(area);
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
break;
case NC_IMAGE:
if (wmn->reference == sima->image || !wmn->reference) {
if (wmn->action != NA_PAINTING) {
- image_scopes_tag_refresh(sa);
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ image_scopes_tag_refresh(area);
+ ED_area_tag_refresh(area);
+ ED_area_tag_redraw(area);
}
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_IMAGE) {
- image_scopes_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ image_scopes_tag_refresh(area);
+ ED_area_tag_redraw(area);
}
break;
case NC_MASK: {
@@ -370,23 +375,23 @@ static void image_listener(wmWindow *win, ScrArea *sa, wmNotifier *wmn, Scene *U
if (sima->mode == SI_MODE_MASK) {
switch (wmn->data) {
case ND_SELECT:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case ND_DATA:
case ND_DRAW:
/* causes node-recalc */
- ED_area_tag_redraw(sa);
- ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(area);
+ ED_area_tag_refresh(area);
break;
}
switch (wmn->action) {
case NA_SELECTED:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case NA_EDITED:
/* causes node-recalc */
- ED_area_tag_redraw(sa);
- ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(area);
+ ED_area_tag_refresh(area);
break;
}
}
@@ -396,9 +401,9 @@ static void image_listener(wmWindow *win, ScrArea *sa, wmNotifier *wmn, Scene *U
switch (wmn->data) {
case ND_DATA:
case ND_SELECT:
- image_scopes_tag_refresh(sa);
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ image_scopes_tag_refresh(area);
+ ED_area_tag_refresh(area);
+ ED_area_tag_redraw(area);
break;
}
break;
@@ -411,8 +416,8 @@ static void image_listener(wmWindow *win, ScrArea *sa, wmNotifier *wmn, Scene *U
Object *ob = OBACT(view_layer);
if (ob && (ob == wmn->reference) && (ob->mode & OB_MODE_EDIT)) {
if (sima->lock && (sima->flag & SI_DRAWSHADOW)) {
- ED_area_tag_refresh(sa);
- ED_area_tag_redraw(sa);
+ ED_area_tag_refresh(area);
+ ED_area_tag_redraw(area);
}
}
break;
@@ -423,14 +428,14 @@ static void image_listener(wmWindow *win, ScrArea *sa, wmNotifier *wmn, Scene *U
}
case NC_ID: {
if (wmn->action == NA_RENAME) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
}
case NC_WM:
if (wmn->data == ND_UNDO) {
- ED_area_tag_redraw(sa);
- ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(area);
+ ED_area_tag_refresh(area);
}
break;
}
@@ -536,7 +541,7 @@ static void image_widgets(void)
/************************** main region ***************************/
/* sets up the fields of the View2D from zoom and offset */
-static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar)
+static void image_main_region_set_view2d(SpaceImage *sima, ARegion *region)
{
Image *ima = ED_space_image(sima);
@@ -550,79 +555,79 @@ static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar)
h *= ima->aspy / ima->aspx;
}
- int winx = BLI_rcti_size_x(&ar->winrct) + 1;
- int winy = BLI_rcti_size_y(&ar->winrct) + 1;
+ int winx = BLI_rcti_size_x(&region->winrct) + 1;
+ int winy = BLI_rcti_size_y(&region->winrct) + 1;
/* For region overlap, move center so image doesn't overlap header. */
- const rcti *visible_rect = ED_region_visible_rect(ar);
+ const rcti *visible_rect = ED_region_visible_rect(region);
const int visible_winy = BLI_rcti_size_y(visible_rect) + 1;
int visible_centerx = 0;
int visible_centery = visible_rect->ymin + (visible_winy - winy) / 2;
- ar->v2d.tot.xmin = 0;
- ar->v2d.tot.ymin = 0;
- ar->v2d.tot.xmax = w;
- ar->v2d.tot.ymax = h;
+ region->v2d.tot.xmin = 0;
+ region->v2d.tot.ymin = 0;
+ region->v2d.tot.xmax = w;
+ region->v2d.tot.ymax = h;
- ar->v2d.mask.xmin = ar->v2d.mask.ymin = 0;
- ar->v2d.mask.xmax = winx;
- ar->v2d.mask.ymax = winy;
+ region->v2d.mask.xmin = region->v2d.mask.ymin = 0;
+ region->v2d.mask.xmax = winx;
+ region->v2d.mask.ymax = winy;
/* which part of the image space do we see? */
- float x1 = ar->winrct.xmin + visible_centerx + (winx - sima->zoom * w) / 2.0f;
- float y1 = ar->winrct.ymin + visible_centery + (winy - sima->zoom * h) / 2.0f;
+ float x1 = region->winrct.xmin + visible_centerx + (winx - sima->zoom * w) / 2.0f;
+ float y1 = region->winrct.ymin + visible_centery + (winy - sima->zoom * h) / 2.0f;
x1 -= sima->zoom * sima->xof;
y1 -= sima->zoom * sima->yof;
/* relative display right */
- ar->v2d.cur.xmin = ((ar->winrct.xmin - (float)x1) / sima->zoom);
- ar->v2d.cur.xmax = ar->v2d.cur.xmin + ((float)winx / sima->zoom);
+ region->v2d.cur.xmin = ((region->winrct.xmin - (float)x1) / sima->zoom);
+ region->v2d.cur.xmax = region->v2d.cur.xmin + ((float)winx / sima->zoom);
/* relative display left */
- ar->v2d.cur.ymin = ((ar->winrct.ymin - (float)y1) / sima->zoom);
- ar->v2d.cur.ymax = ar->v2d.cur.ymin + ((float)winy / sima->zoom);
+ region->v2d.cur.ymin = ((region->winrct.ymin - (float)y1) / sima->zoom);
+ region->v2d.cur.ymax = region->v2d.cur.ymin + ((float)winy / sima->zoom);
/* normalize 0.0..1.0 */
- ar->v2d.cur.xmin /= w;
- ar->v2d.cur.xmax /= w;
- ar->v2d.cur.ymin /= h;
- ar->v2d.cur.ymax /= h;
+ region->v2d.cur.xmin /= w;
+ region->v2d.cur.xmax /= w;
+ region->v2d.cur.ymin /= h;
+ region->v2d.cur.ymax /= h;
}
/* add handlers, stuff you only do once or on area/region changes */
-static void image_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void image_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
// image space manages own v2d
- // UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+ // UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_STANDARD, region->winx, region->winy);
/* mask polls mode */
keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
/* image paint polls for mode */
keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "UV Editor", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
/* own keymaps */
keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Image", SPACE_IMAGE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void image_main_region_draw(const bContext *C, ARegion *ar)
+static void image_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceImage *sima = CTX_wm_space_image(C);
@@ -634,7 +639,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
bool show_curve = false;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
// View2DScrollers *scrollers;
float col[3];
@@ -642,32 +647,36 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
* old context since we now use it for drawing the entire area. */
gpu_batch_presets_reset();
- GPUViewport *viewport =
- ar->draw_buffer->viewport[ar->draw_buffer->stereo ? sima->iuser.multiview_eye : 0];
+ GPUViewport *viewport = region->draw_buffer->viewport;
DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport);
GPU_framebuffer_bind(fbl->default_fb);
+ GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
+ GPU_clear(GPU_COLOR_BIT);
+
+ GPU_framebuffer_bind(fbl->overlay_fb);
/* XXX not supported yet, disabling for now */
scene->r.scemode &= ~R_COMP_CROP;
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
- GPU_clear_color(col[0], col[1], col[2], 0.0f);
+ srgb_to_linearrgb_v3_v3(col, col);
+ GPU_clear_color(col[0], col[1], col[2], 1.0f);
GPU_clear(GPU_COLOR_BIT);
GPU_depth_test(false);
image_user_refresh_scene(C, sima);
/* we set view2d from own zoom and offset each time */
- image_main_region_set_view2d(sima, ar);
+ image_main_region_set_view2d(sima, region);
/* we draw image in pixelspace */
- draw_image_main(C, ar);
+ draw_image_main(C, region);
/* and uvs in 0.0-1.0 space */
UI_view2d_view_ortho(v2d);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
ED_uvedit_draw_main(sima, scene, view_layer, obedit, obact, depsgraph);
@@ -682,7 +691,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
show_curve = true;
}
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
if (sima->flag & SI_SHOW_GPENCIL) {
/* Grease Pencil too (in addition to UV's) */
@@ -722,7 +731,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
ED_mask_draw_region(depsgraph,
mask,
- ar,
+ region,
sima->mask_info.draw_flag,
sima->mask_info.draw_type,
sima->mask_info.overlay_mode,
@@ -738,51 +747,54 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
if (show_uvedit || mask || show_curve) {
UI_view2d_view_ortho(v2d);
- ED_image_draw_cursor(ar, sima->cursor);
+ ED_image_draw_cursor(region, sima->cursor);
UI_view2d_view_restore(C);
}
- WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
+ WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
- draw_image_cache(C, ar);
+ draw_image_cache(C, region);
}
-static void image_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
+static void image_main_region_listener(wmWindow *UNUSED(win),
+ ScrArea *area,
+ ARegion *region,
+ wmNotifier *wmn,
+ const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_GEOM:
if (ELEM(wmn->data, ND_DATA, ND_SELECT)) {
- WM_gizmomap_tag_refresh(ar->gizmo_map);
+ WM_gizmomap_tag_refresh(region->gizmo_map);
}
break;
case NC_GPENCIL:
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
else if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_IMAGE:
if (wmn->action == NA_PAINTING) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
- WM_gizmomap_tag_refresh(ar->gizmo_map);
+ WM_gizmomap_tag_refresh(region->gizmo_map);
break;
case NC_MATERIAL:
if (wmn->data == ND_SHADING_LINKS) {
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
if (sima->iuser.scene && (sima->iuser.scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -791,18 +803,18 @@ static void image_main_region_listener(
/* *********************** buttons region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void image_buttons_region_init(wmWindowManager *wm, ARegion *ar)
+static void image_buttons_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void image_buttons_region_layout(const bContext *C, ARegion *ar)
+static void image_buttons_region_layout(const bContext *C, ARegion *region)
{
const enum eContextObjectMode mode = CTX_data_mode_enum(C);
const char *contexts_base[3] = {NULL};
@@ -826,10 +838,11 @@ static void image_buttons_region_layout(const bContext *C, ARegion *ar)
}
const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts_base, -1, vertical, NULL);
+ ED_region_panels_layout_ex(
+ C, region, &region->type->paneltypes, contexts_base, -1, vertical, NULL);
}
-static void image_buttons_region_draw(const bContext *C, ARegion *ar)
+static void image_buttons_region_draw(const bContext *C, ARegion *region)
{
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
@@ -837,7 +850,7 @@ static void image_buttons_region_draw(const bContext *C, ARegion *ar)
/* TODO(lukas): Support tiles in scopes? */
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
/* XXX performance regression if name of scopes category changes! */
- PanelCategoryStack *category = UI_panel_category_active_find(ar, "Scopes");
+ PanelCategoryStack *category = UI_panel_category_active_find(region, "Scopes");
/* only update scopes if scope category is active */
if (category) {
@@ -857,12 +870,12 @@ static void image_buttons_region_draw(const bContext *C, ARegion *ar)
ED_space_image_release_buffer(sima, ibuf, lock);
/* Layout handles details. */
- ED_region_panels_draw(C, ar);
+ ED_region_panels_draw(C, region);
}
static void image_buttons_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -872,33 +885,33 @@ static void image_buttons_region_listener(wmWindow *UNUSED(win),
case NC_MATERIAL:
/* sending by texture render job and needed to properly update displaying
* brush texture icon */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_SCENE:
switch (wmn->data) {
case ND_MODE:
case ND_RENDER_RESULT:
case ND_COMPO_RESULT:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_IMAGE:
if (wmn->action != NA_PAINTING) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_NODE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_GPENCIL:
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_BRUSH:
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -907,25 +920,25 @@ static void image_buttons_region_listener(wmWindow *UNUSED(win),
/* *********************** scopes region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void image_tools_region_init(wmWindowManager *wm, ARegion *ar)
+static void image_tools_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void image_tools_region_draw(const bContext *C, ARegion *ar)
+static void image_tools_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
static void image_tools_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -933,13 +946,13 @@ static void image_tools_region_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_GPENCIL:
if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_BRUSH:
/* NA_SELECTED is used on brush changes */
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
@@ -947,17 +960,17 @@ static void image_tools_region_listener(wmWindow *UNUSED(win),
case ND_MODE:
case ND_RENDER_RESULT:
case ND_COMPO_RESULT:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_IMAGE:
if (wmn->action != NA_PAINTING) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_NODE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
}
@@ -965,24 +978,24 @@ static void image_tools_region_listener(wmWindow *UNUSED(win),
/************************* header region **************************/
/* add handlers, stuff you only do once or on area/region changes */
-static void image_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void image_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void image_header_region_draw(const bContext *C, ARegion *ar)
+static void image_header_region_draw(const bContext *C, ARegion *region)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceImage *sima = sa->spacedata.first;
+ ScrArea *area = CTX_wm_area(C);
+ SpaceImage *sima = area->spacedata.first;
image_user_refresh_scene(C, sima);
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
static void image_header_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -992,7 +1005,7 @@ static void image_header_region_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_MODE:
case ND_TOOLSETTINGS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -1000,19 +1013,19 @@ static void image_header_region_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_DATA:
case ND_SELECT:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_BRUSH:
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
}
-static void image_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void image_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceImage *simg = (SpaceImage *)slink;
@@ -1042,15 +1055,15 @@ static void image_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
* The previous non-uv-edit mode is stored so switching back to the
* image doesn't always reset the sub-mode.
*/
-static int image_space_subtype_get(ScrArea *sa)
+static int image_space_subtype_get(ScrArea *area)
{
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
return sima->mode == SI_MODE_UV ? SI_MODE_UV : SI_MODE_VIEW;
}
-static void image_space_subtype_set(ScrArea *sa, int value)
+static void image_space_subtype_set(ScrArea *area, int value)
{
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
if (value == SI_MODE_UV) {
if (sima->mode != SI_MODE_UV) {
sima->mode_prev = sima->mode;
diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c
index d86e0e2af97..2a3f6d6e365 100644
--- a/source/blender/editors/space_info/info_draw.c
+++ b/source/blender/editors/space_info/info_draw.c
@@ -21,42 +21,39 @@
* \ingroup spinfo
*/
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
#include <limits.h>
+#include <string.h>
#include "BLI_utildefines.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "BKE_report.h"
-#include "UI_resources.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "UI_view2d.h"
+#include "GPU_framebuffer.h"
#include "info_intern.h"
#include "textview.h"
-#include "GPU_framebuffer.h"
-static int report_line_data(struct TextViewContext *tvc,
- unsigned char fg[4],
- unsigned char bg[4],
- int *icon,
- unsigned char icon_fg[4],
- unsigned char icon_bg[4])
+static enum eTextViewContext_LineFlag report_line_data(TextViewContext *tvc,
+ uchar fg[4],
+ uchar bg[4],
+ int *r_icon,
+ uchar r_icon_fg[4],
+ uchar r_icon_bg[4])
{
- Report *report = (Report *)tvc->iter;
+ const Report *report = tvc->iter;
/* Same text color no matter what type of report. */
UI_GetThemeColor4ubv((report->flag & SELECT) ? TH_INFO_SELECTED_TEXT : TH_TEXT, fg);
/* Zebra striping for background. */
int bg_id = (report->flag & SELECT) ? TH_INFO_SELECTED : TH_BACK;
- int shade = tvc->iter_tmp % 2 ? 4 : -4;
+ int shade = (tvc->iter_tmp % 2) ? 4 : -4;
UI_GetThemeColorShade4ubv(bg_id, shade, bg);
/* Icon color and backgound depend of report type. */
@@ -64,38 +61,41 @@ static int report_line_data(struct TextViewContext *tvc,
int icon_fg_id;
int icon_bg_id;
- if (report->type & RPT_ERROR_ALL) {
+ if (tvc->iter_char_begin != 0) {
+ *r_icon = ICON_NONE;
+ }
+ else if (report->type & RPT_ERROR_ALL) {
icon_fg_id = TH_INFO_ERROR_TEXT;
icon_bg_id = TH_INFO_ERROR;
- *icon = ICON_CANCEL;
+ *r_icon = ICON_CANCEL;
}
else if (report->type & RPT_WARNING_ALL) {
icon_fg_id = TH_INFO_WARNING_TEXT;
icon_bg_id = TH_INFO_WARNING;
- *icon = ICON_ERROR;
+ *r_icon = ICON_ERROR;
}
else if (report->type & RPT_INFO_ALL) {
icon_fg_id = TH_INFO_INFO_TEXT;
icon_bg_id = TH_INFO_INFO;
- *icon = ICON_INFO;
+ *r_icon = ICON_INFO;
}
else if (report->type & RPT_DEBUG_ALL) {
icon_fg_id = TH_INFO_DEBUG_TEXT;
icon_bg_id = TH_INFO_DEBUG;
- *icon = ICON_SYSTEM;
+ *r_icon = ICON_SYSTEM;
}
else if (report->type & RPT_PROPERTY) {
icon_fg_id = TH_INFO_PROPERTY_TEXT;
icon_bg_id = TH_INFO_PROPERTY;
- *icon = ICON_OPTIONS;
+ *r_icon = ICON_OPTIONS;
}
else if (report->type & RPT_OPERATOR) {
icon_fg_id = TH_INFO_OPERATOR_TEXT;
icon_bg_id = TH_INFO_OPERATOR;
- *icon = ICON_CHECKMARK;
+ *r_icon = ICON_CHECKMARK;
}
else {
- *icon = ICON_NONE;
+ *r_icon = ICON_NONE;
}
if (report->flag & SELECT) {
@@ -103,9 +103,9 @@ static int report_line_data(struct TextViewContext *tvc,
icon_bg_id = TH_INFO_SELECTED_TEXT;
}
- if (*icon != ICON_NONE) {
- UI_GetThemeColor4ubv(icon_fg_id, icon_fg);
- UI_GetThemeColor4ubv(icon_bg_id, icon_bg);
+ if (*r_icon != ICON_NONE) {
+ UI_GetThemeColor4ubv(icon_fg_id, r_icon_fg);
+ UI_GetThemeColor4ubv(icon_bg_id, r_icon_bg);
return TVC_LINE_FG | TVC_LINE_BG | TVC_LINE_ICON | TVC_LINE_ICON_FG | TVC_LINE_ICON_BG;
}
else {
@@ -116,23 +116,22 @@ static int report_line_data(struct TextViewContext *tvc,
/* reports! */
static void report_textview_init__internal(TextViewContext *tvc)
{
- Report *report = (Report *)tvc->iter;
+ const Report *report = tvc->iter;
const char *str = report->message;
- const char *next_str = strchr(str + tvc->iter_char, '\n');
-
- if (next_str) {
- tvc->iter_char_next = (int)(next_str - str);
- }
- else {
- tvc->iter_char_next = report->len;
+ for (int i = tvc->iter_char_end - 1; i >= 0; i -= 1) {
+ if (str[i] == '\n') {
+ tvc->iter_char_begin = i + 1;
+ return;
+ }
}
+ tvc->iter_char_begin = 0;
}
static int report_textview_skip__internal(TextViewContext *tvc)
{
- SpaceInfo *sinfo = (SpaceInfo *)tvc->arg1;
+ const SpaceInfo *sinfo = tvc->arg1;
const int report_mask = info_report_mask(sinfo);
- while (tvc->iter && (((Report *)tvc->iter)->type & report_mask) == 0) {
+ while (tvc->iter && (((const Report *)tvc->iter)->type & report_mask) == 0) {
tvc->iter = (void *)((Link *)tvc->iter)->prev;
}
return (tvc->iter != NULL);
@@ -140,7 +139,7 @@ static int report_textview_skip__internal(TextViewContext *tvc)
static int report_textview_begin(TextViewContext *tvc)
{
- ReportList *reports = (ReportList *)tvc->arg2;
+ const ReportList *reports = tvc->arg2;
tvc->lheight = 14 * UI_DPI_FAC;
tvc->sel_start = 0;
@@ -155,7 +154,8 @@ static int report_textview_begin(TextViewContext *tvc)
tvc->iter_tmp = 0;
if (tvc->iter && report_textview_skip__internal(tvc)) {
/* init the newline iterator */
- tvc->iter_char = 0;
+ const Report *report = tvc->iter;
+ tvc->iter_char_end = report->len;
report_textview_init__internal(tvc);
return true;
@@ -173,14 +173,15 @@ static void report_textview_end(TextViewContext *UNUSED(tvc))
static int report_textview_step(TextViewContext *tvc)
{
/* simple case, but no newline support */
- Report *report = (Report *)tvc->iter;
+ const Report *report = tvc->iter;
- if (report->len <= tvc->iter_char_next) {
+ if (tvc->iter_char_begin <= 0) {
tvc->iter = (void *)((Link *)tvc->iter)->prev;
if (tvc->iter && report_textview_skip__internal(tvc)) {
tvc->iter_tmp++;
- tvc->iter_char = 0; /* reset start */
+ report = tvc->iter;
+ tvc->iter_char_end = report->len; /* reset start */
report_textview_init__internal(tvc);
return true;
@@ -191,32 +192,40 @@ static int report_textview_step(TextViewContext *tvc)
}
else {
/* step to the next newline */
- tvc->iter_char = tvc->iter_char_next + 1;
+ tvc->iter_char_end = tvc->iter_char_begin - 1;
report_textview_init__internal(tvc);
return true;
}
}
-static int report_textview_line_get(struct TextViewContext *tvc, const char **line, int *len)
+static void report_textview_line_get(TextViewContext *tvc, const char **r_line, int *r_len)
{
- Report *report = (Report *)tvc->iter;
- *line = report->message + tvc->iter_char;
- *len = tvc->iter_char_next - tvc->iter_char;
- return 1;
+ const Report *report = tvc->iter;
+ *r_line = report->message + tvc->iter_char_begin;
+ *r_len = tvc->iter_char_end - tvc->iter_char_begin;
}
-static void info_textview_draw_rect_calc(const ARegion *ar, rcti *draw_rect)
+static void info_textview_draw_rect_calc(const ARegion *region,
+ rcti *r_draw_rect,
+ rcti *r_draw_rect_outer)
{
- draw_rect->xmin = 0;
- draw_rect->xmax = ar->winx;
- draw_rect->ymin = 0;
- draw_rect->ymax = ar->winy;
+ const int margin = 0.45f * U.widget_unit;
+ r_draw_rect->xmin = margin + UI_UNIT_X;
+ r_draw_rect->xmax = region->winx - V2D_SCROLL_WIDTH;
+ r_draw_rect->ymin = margin;
+ r_draw_rect->ymax = region->winy;
+ /* No margin at the top (allow text to scroll off the window). */
+
+ r_draw_rect_outer->xmin = 0;
+ r_draw_rect_outer->xmax = region->winx;
+ r_draw_rect_outer->ymin = 0;
+ r_draw_rect_outer->ymax = region->winy;
}
-static int info_textview_main__internal(struct SpaceInfo *sinfo,
- const ARegion *ar,
- ReportList *reports,
+static int info_textview_main__internal(const SpaceInfo *sinfo,
+ const ARegion *region,
+ const ReportList *reports,
const bool do_draw,
const int mval[2],
void **r_mval_pick_item,
@@ -224,7 +233,7 @@ static int info_textview_main__internal(struct SpaceInfo *sinfo,
{
int ret = 0;
- const View2D *v2d = &ar->v2d;
+ const View2D *v2d = &region->v2d;
TextViewContext tvc = {0};
tvc.begin = report_textview_begin;
@@ -243,35 +252,36 @@ static int info_textview_main__internal(struct SpaceInfo *sinfo,
tvc.sel_end = 0;
tvc.lheight = 17 * UI_DPI_FAC;
tvc.row_vpadding = 0.4 * tvc.lheight;
- tvc.margin_left_chars = 5;
- tvc.margin_right_chars = 2;
tvc.scroll_ymin = v2d->cur.ymin;
tvc.scroll_ymax = v2d->cur.ymax;
- info_textview_draw_rect_calc(ar, &tvc.draw_rect);
+ info_textview_draw_rect_calc(region, &tvc.draw_rect, &tvc.draw_rect_outer);
ret = textview_draw(&tvc, do_draw, mval, r_mval_pick_item, r_mval_pick_offset);
return ret;
}
-void *info_text_pick(struct SpaceInfo *sinfo, const ARegion *ar, ReportList *reports, int mval_y)
+void *info_text_pick(const SpaceInfo *sinfo,
+ const ARegion *region,
+ const ReportList *reports,
+ int mval_y)
{
void *mval_pick_item = NULL;
const int mval[2] = {0, mval_y};
- info_textview_main__internal(sinfo, ar, reports, false, mval, &mval_pick_item, NULL);
+ info_textview_main__internal(sinfo, region, reports, false, mval, &mval_pick_item, NULL);
return (void *)mval_pick_item;
}
-int info_textview_height(struct SpaceInfo *sinfo, const ARegion *ar, ReportList *reports)
+int info_textview_height(const SpaceInfo *sinfo, const ARegion *region, const ReportList *reports)
{
int mval[2] = {INT_MAX, INT_MAX};
- return info_textview_main__internal(sinfo, ar, reports, false, mval, NULL, NULL);
+ return info_textview_main__internal(sinfo, region, reports, false, mval, NULL, NULL);
}
-void info_textview_main(struct SpaceInfo *sinfo, const ARegion *ar, ReportList *reports)
+void info_textview_main(const SpaceInfo *sinfo, const ARegion *region, const ReportList *reports)
{
int mval[2] = {INT_MAX, INT_MAX};
- info_textview_main__internal(sinfo, ar, reports, true, mval, NULL, NULL);
+ info_textview_main__internal(sinfo, region, reports, true, mval, NULL, NULL);
}
diff --git a/source/blender/editors/space_info/info_intern.h b/source/blender/editors/space_info/info_intern.h
index 177b43edf74..79bfb1fa047 100644
--- a/source/blender/editors/space_info/info_intern.h
+++ b/source/blender/editors/space_info/info_intern.h
@@ -45,19 +45,19 @@ void FILE_OT_find_missing_files(struct wmOperatorType *ot);
void INFO_OT_reports_display_update(struct wmOperatorType *ot);
/* info_draw.c */
-void *info_text_pick(struct SpaceInfo *sinfo,
- const struct ARegion *ar,
- ReportList *reports,
+void *info_text_pick(const struct SpaceInfo *sinfo,
+ const struct ARegion *region,
+ const struct ReportList *reports,
int mouse_y);
-int info_textview_height(struct SpaceInfo *sinfo,
- const struct ARegion *ar,
- struct ReportList *reports);
-void info_textview_main(struct SpaceInfo *sinfo,
- const struct ARegion *ar,
- struct ReportList *reports);
+int info_textview_height(const struct SpaceInfo *sinfo,
+ const struct ARegion *region,
+ const struct ReportList *reports);
+void info_textview_main(const struct SpaceInfo *sinfo,
+ const struct ARegion *region,
+ const struct ReportList *reports);
/* info_report.c */
-int info_report_mask(struct SpaceInfo *sinfo);
+int info_report_mask(const struct SpaceInfo *sinfo);
void INFO_OT_select_pick(struct wmOperatorType *ot); /* report selection */
void INFO_OT_select_all(struct wmOperatorType *ot);
void INFO_OT_select_box(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 124e3c08165..30f36509b41 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -21,8 +21,8 @@
* \ingroup spinfo
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "DNA_packedFile_types.h"
#include "DNA_space_types.h"
@@ -40,7 +40,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c
index 0fa9ddacc20..adc6391a0f6 100644
--- a/source/blender/editors/space_info/info_report.c
+++ b/source/blender/editors/space_info/info_report.c
@@ -18,9 +18,9 @@
* \ingroup spinfo
*/
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include <limits.h>
#include "MEM_guardedalloc.h"
@@ -72,7 +72,7 @@ static void reports_select_all(ReportList *reports, int report_mask, int action)
}
}
-int info_report_mask(SpaceInfo *UNUSED(sinfo))
+int info_report_mask(const SpaceInfo *UNUSED(sinfo))
{
#if 0
int report_mask = 0;
@@ -172,11 +172,11 @@ static int select_report_pick_exec(bContext *C, wmOperator *op)
static int select_report_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceInfo *sinfo = CTX_wm_space_info(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ReportList *reports = CTX_wm_reports(C);
Report *report;
- report = info_text_pick(sinfo, ar, reports, event->mval[1]);
+ report = info_text_pick(sinfo, region, reports, event->mval[1]);
RNA_int_set(op->ptr, "report_index", BLI_findindex(&reports->list, report));
@@ -239,7 +239,7 @@ void INFO_OT_select_all(wmOperatorType *ot)
static int box_select_exec(bContext *C, wmOperator *op)
{
SpaceInfo *sinfo = CTX_wm_space_info(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ReportList *reports = CTX_wm_reports(C);
int report_mask = info_report_mask(sinfo);
Report *report_min, *report_max;
@@ -250,7 +250,7 @@ static int box_select_exec(bContext *C, wmOperator *op)
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
const int select = (sel_op != SEL_OP_SUB);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- for (Report *report = reports->list.first; report; report = report->next) {
+ LISTBASE_FOREACH (Report *, report, &reports->list) {
if ((report->type & report_mask) == 0) {
continue;
}
@@ -258,13 +258,13 @@ static int box_select_exec(bContext *C, wmOperator *op)
}
}
- report_min = info_text_pick(sinfo, ar, reports, rect.ymax);
- report_max = info_text_pick(sinfo, ar, reports, rect.ymin);
+ report_min = info_text_pick(sinfo, region, reports, rect.ymax);
+ report_max = info_text_pick(sinfo, region, reports, rect.ymin);
/* get the first report if none found */
if (report_min == NULL) {
// printf("find_min\n");
- for (Report *report = reports->list.first; report; report = report->next) {
+ LISTBASE_FOREACH (Report *, report, &reports->list) {
if (report->type & report_mask) {
report_min = report;
break;
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 225ca72a7d0..f8c0e66873f 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -33,6 +33,8 @@
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
+#include "BLF_api.h"
+
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
@@ -40,29 +42,29 @@
#include "BLT_translation.h"
-#include "BKE_anim.h"
#include "BKE_blender_version.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
+#include "BKE_editmesh.h"
+#include "BKE_gpencil.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
-#include "BKE_editmesh.h"
-#include "BKE_object.h"
-#include "BKE_gpencil.h"
#include "BKE_scene.h"
#include "BKE_subdiv_ccg.h"
#include "DEG_depsgraph_query.h"
-#include "ED_info.h"
#include "ED_armature.h"
+#include "ED_info.h"
+
+#include "UI_resources.h"
#include "GPU_extensions.h"
-#define MAX_INFO_LEN 512
#define MAX_INFO_NUM_LEN 16
typedef struct SceneStats {
@@ -74,8 +76,6 @@ typedef struct SceneStats {
uint64_t totlamp, totlampsel;
uint64_t tottri;
uint64_t totgplayer, totgpframe, totgpstroke, totgppoint;
-
- char infostr[MAX_INFO_LEN];
} SceneStats;
typedef struct SceneStatsFmt {
@@ -137,7 +137,7 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset)
switch (ob->type) {
case OB_MESH: {
/* we assume evaluated mesh is already built, this strictly does stats now. */
- Mesh *me_eval = ob->runtime.mesh_eval;
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
if (!BLI_gset_add(objects_gset, me_eval)) {
break;
}
@@ -153,8 +153,7 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset)
case OB_SURF:
case OB_CURVE:
case OB_FONT: {
- Mesh *me_eval = ob->runtime.mesh_eval;
-
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
if ((me_eval != NULL) && !BLI_gset_add(objects_gset, me_eval)) {
break;
}
@@ -205,6 +204,11 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset)
}
break;
}
+ case OB_HAIR:
+ case OB_POINTCLOUD:
+ case OB_VOLUME: {
+ break;
+ }
}
}
@@ -365,10 +369,16 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
if (obedit) {
/* Edit Mode */
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, ((View3D *)NULL), ob->type, ob->mode, ob_iter) {
- stats_object_edit(ob_iter, &stats);
+ FOREACH_OBJECT_BEGIN (view_layer, ob_iter) {
+ if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) {
+ if (ob_iter->mode == OB_MODE_EDIT) {
+ stats_object_edit(ob_iter, &stats);
+ stats.totobjsel++;
+ }
+ stats.totobj++;
+ }
}
- FOREACH_OBJECT_IN_MODE_END;
+ FOREACH_OBJECT_END;
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
/* Pose Mode */
@@ -395,26 +405,98 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
*(view_layer->stats) = stats;
}
-static void stats_string(ViewLayer *view_layer)
+static const char *footer_string(ViewLayer *view_layer)
{
#define MAX_INFO_MEM_LEN 64
- SceneStats *stats = view_layer->stats;
- SceneStatsFmt stats_fmt;
- LayerCollection *layer_collection = view_layer->active_collection;
- Object *ob = OBACT(view_layer);
- Object *obedit = OBEDIT_FROM_OBACT(ob);
- eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT;
- uintptr_t mem_in_use, mmap_in_use;
char memstr[MAX_INFO_MEM_LEN];
char gpumemstr[MAX_INFO_MEM_LEN] = "";
char formatted_mem[15];
- char *s;
size_t ofs = 0;
- mem_in_use = MEM_get_memory_in_use();
- mmap_in_use = MEM_get_mapped_memory_in_use();
+ uintptr_t mem_in_use = MEM_get_memory_in_use();
+ uintptr_t mmap_in_use = MEM_get_mapped_memory_in_use();
+
+ /* get memory statistics */
+ BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, false);
+ ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, TIP_("Mem: %s"), formatted_mem);
+
+ if (mmap_in_use) {
+ BLI_str_format_byte_unit(formatted_mem, mmap_in_use, false);
+ BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_(" (%s)"), formatted_mem);
+ }
+
+ if (GPU_mem_stats_supported()) {
+ int gpu_free_mem, gpu_tot_memory;
+
+ GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem);
+
+ BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, false);
+ ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, TIP_(" | Free GPU Mem: %s"), formatted_mem);
+
+ if (gpu_tot_memory) {
+ BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, false);
+ BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_("/%s"), formatted_mem);
+ }
+ }
+
+ BLI_snprintf(view_layer->footer_str,
+ sizeof(view_layer->footer_str),
+ "%s%s | %s",
+ memstr,
+ gpumemstr,
+ versionstr);
- /* Generate formatted numbers */
+ return view_layer->footer_str;
+
+#undef MAX_INFO_MEM_LEN
+}
+
+void ED_info_stats_clear(ViewLayer *view_layer)
+{
+ if (view_layer->stats) {
+ MEM_freeN(view_layer->stats);
+ view_layer->stats = NULL;
+ }
+}
+
+const char *ED_info_footer_string(ViewLayer *view_layer)
+{
+ return footer_string(view_layer);
+}
+
+static void stats_row(int col1,
+ const char *key,
+ int col2,
+ const char *value1,
+ const char *value2,
+ int *y,
+ int height)
+{
+ *y -= height;
+ BLF_draw_default(col1, *y, 0.0f, key, 128);
+ char values[128];
+ BLI_snprintf(values, sizeof(values), (value2) ? "%s / %s" : "%s", value1, value2);
+ BLF_draw_default(col2, *y, 0.0f, values, sizeof(values));
+}
+
+void ED_info_draw_stats(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height)
+{
+ /* Create stats if they don't already exist. */
+ if (!view_layer->stats) {
+ /* Do not not access dependency graph if interface is marked as locked. */
+ wmWindowManager *wm = bmain->wm.first;
+ if (wm->is_interface_locked) {
+ return;
+ }
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true);
+ stats_update(depsgraph, view_layer);
+ }
+
+ SceneStats *stats = view_layer->stats;
+ SceneStatsFmt stats_fmt;
+
+ /* Generate formatted numbers. */
#define SCENE_STATS_FMT_INT(_id) BLI_str_format_uint64_grouped(stats_fmt._id, stats->_id)
SCENE_STATS_FMT_INT(totvert);
@@ -444,151 +526,94 @@ static void stats_string(ViewLayer *view_layer)
#undef SCENE_STATS_FMT_INT
- /* get memory statistics */
- BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, false);
- ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, TIP_(" | Mem: %s"), formatted_mem);
-
- if (mmap_in_use) {
- BLI_str_format_byte_unit(formatted_mem, mmap_in_use, false);
- BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_(" (%s)"), formatted_mem);
+ Object *ob = OBACT(view_layer);
+ Object *obedit = OBEDIT_FROM_OBACT(ob);
+ eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT;
+ const int font_id = BLF_default();
+
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
+ BLF_enable(font_id, BLF_SHADOW);
+ BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
+ BLF_shadow_offset(font_id, 1, -1);
+
+ /* Translated labels for each stat row. */
+ enum {
+ OBJ,
+ VERTS,
+ EDGES,
+ FACES,
+ TRIS,
+ BONES,
+ LAYERS,
+ FRAMES,
+ STROKES,
+ POINTS,
+ MAX_LABELS_COUNT
+ };
+ char labels[MAX_LABELS_COUNT][64];
+
+ STRNCPY(labels[OBJ], IFACE_("Objects"));
+ STRNCPY(labels[VERTS], IFACE_("Vertices"));
+ STRNCPY(labels[EDGES], IFACE_("Edges"));
+ STRNCPY(labels[FACES], IFACE_("Faces"));
+ STRNCPY(labels[TRIS], IFACE_("Triangles"));
+ STRNCPY(labels[BONES], IFACE_("Bones"));
+ STRNCPY(labels[LAYERS], IFACE_("Layers"));
+ STRNCPY(labels[FRAMES], IFACE_("Frames"));
+ STRNCPY(labels[STROKES], IFACE_("Strokes"));
+ STRNCPY(labels[POINTS], IFACE_("Points"));
+
+ int longest_label = 0;
+ int i;
+ for (i = 0; i < MAX_LABELS_COUNT; ++i) {
+ longest_label = max_ii(longest_label, BLF_width(font_id, labels[i], sizeof(labels[i])));
}
- if (GPU_mem_stats_supported()) {
- int gpu_free_mem, gpu_tot_memory;
+ int col1 = x;
+ int col2 = x + longest_label + (0.5f * U.widget_unit);
- GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem);
-
- BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, false);
- ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, TIP_(" | Free GPU Mem: %s"), formatted_mem);
-
- if (gpu_tot_memory) {
- BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, false);
- BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_("/%s"), formatted_mem);
- }
- }
-
- s = stats->infostr;
- ofs = 0;
+ /* Add some extra margin above this section. */
+ *y -= (0.6f * height);
if (object_mode == OB_MODE_OBJECT) {
- ofs += BLI_snprintf(s + ofs,
- MAX_INFO_LEN - ofs,
- "%s | ",
- BKE_collection_ui_name_get(layer_collection->collection));
- }
-
- if (ob) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, "%s | ", ob->id.name + 2);
+ stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height);
}
if (obedit) {
- if (BKE_keyblock_from_object(obedit)) {
- ofs += BLI_strncpy_rlen(s + ofs, TIP_("(Key) "), MAX_INFO_LEN - ofs);
- }
-
if (obedit->type == OB_MESH) {
- ofs += BLI_snprintf(s + ofs,
- MAX_INFO_LEN - ofs,
- TIP_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"),
- stats_fmt.totvertsel,
- stats_fmt.totvert,
- stats_fmt.totedgesel,
- stats_fmt.totedge,
- stats_fmt.totfacesel,
- stats_fmt.totface,
- stats_fmt.tottri);
+ stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height);
+ stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
+ stats_row(col1, labels[EDGES], col2, stats_fmt.totedgesel, stats_fmt.totedge, y, height);
+ stats_row(col1, labels[FACES], col2, stats_fmt.totfacesel, stats_fmt.totface, y, height);
+ stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
}
else if (obedit->type == OB_ARMATURE) {
- ofs += BLI_snprintf(s + ofs,
- MAX_INFO_LEN - ofs,
- TIP_("Verts:%s/%s | Bones:%s/%s"),
- stats_fmt.totvertsel,
- stats_fmt.totvert,
- stats_fmt.totbonesel,
- stats_fmt.totbone);
+ stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
+ stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height);
}
else {
- ofs += BLI_snprintf(s + ofs,
- MAX_INFO_LEN - ofs,
- TIP_("Verts:%s/%s"),
- stats_fmt.totvertsel,
- stats_fmt.totvert);
+ stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
}
-
- ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs);
- ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs);
}
else if (ob && (object_mode & OB_MODE_POSE)) {
- ofs += BLI_snprintf(s + ofs,
- MAX_INFO_LEN - ofs,
- TIP_("Bones:%s/%s %s%s"),
- stats_fmt.totbonesel,
- stats_fmt.totbone,
- memstr,
- gpumemstr);
+ stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height);
}
else if ((ob) && (ob->type == OB_GPENCIL)) {
- ofs += BLI_snprintf(s + ofs,
- MAX_INFO_LEN - ofs,
- TIP_("Layers:%s | Frames:%s | Strokes:%s | Points:%s | Objects:%s/%s"),
- stats_fmt.totgplayer,
- stats_fmt.totgpframe,
- stats_fmt.totgpstroke,
- stats_fmt.totgppoint,
- stats_fmt.totobjsel,
- stats_fmt.totobj);
-
- ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs);
- ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs);
+ stats_row(col1, labels[LAYERS], col2, stats_fmt.totgplayer, NULL, y, height);
+ stats_row(col1, labels[FRAMES], col2, stats_fmt.totgpframe, NULL, y, height);
+ stats_row(col1, labels[STROKES], col2, stats_fmt.totgpstroke, NULL, y, height);
+ stats_row(col1, labels[POINTS], col2, stats_fmt.totgppoint, NULL, y, height);
}
else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) {
- ofs += BLI_snprintf(s + ofs,
- MAX_INFO_LEN - ofs,
- TIP_("Verts:%s | Tris:%s%s"),
- stats_fmt.totvert,
- stats_fmt.tottri,
- gpumemstr);
+ stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height);
+ stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
}
else {
- ofs += BLI_snprintf(s + ofs,
- MAX_INFO_LEN - ofs,
- TIP_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s%s%s"),
- stats_fmt.totvert,
- stats_fmt.totface,
- stats_fmt.tottri,
- stats_fmt.totobjsel,
- stats_fmt.totobj,
- memstr,
- gpumemstr);
- }
-
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, " | %s", versionstr);
-#undef MAX_INFO_MEM_LEN
-}
-
-#undef MAX_INFO_LEN
-
-void ED_info_stats_clear(ViewLayer *view_layer)
-{
- if (view_layer->stats) {
- MEM_freeN(view_layer->stats);
- view_layer->stats = NULL;
+ stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height);
+ stats_row(col1, labels[EDGES], col2, stats_fmt.totedge, NULL, y, height);
+ stats_row(col1, labels[FACES], col2, stats_fmt.totface, NULL, y, height);
+ stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
}
-}
-const char *ED_info_stats_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
-{
- /* Looping through dependency graph when interface is locked in not safe.
- * Thew interface is marked as locked when jobs wants to modify the
- * dependency graph. */
- wmWindowManager *wm = bmain->wm.first;
- if (wm->is_interface_locked) {
- return "";
- }
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true);
- if (!view_layer->stats) {
- stats_update(depsgraph, view_layer);
- }
- stats_string(view_layer);
- return view_layer->stats->infostr;
+ BLF_disable(font_id, BLF_SHADOW);
}
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index 8eddf90b06b..04df0f0d4f0 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -21,8 +21,8 @@
* \ingroup spinfo
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -34,28 +34,28 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "RNA_access.h"
-#include "UI_resources.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "UI_view2d.h"
-#include "info_intern.h" /* own include */
#include "BLO_readfile.h"
#include "GPU_framebuffer.h"
+#include "info_intern.h" /* own include */
/* ******************** default callbacks for info space ***************** */
static SpaceLink *info_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceInfo *sinfo;
sinfo = MEM_callocN(sizeof(SpaceInfo), "initinfo");
@@ -64,28 +64,28 @@ static SpaceLink *info_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
sinfo->rpt_mask = INFO_RPT_OP;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for info");
+ region = MEM_callocN(sizeof(ARegion), "header for info");
- BLI_addtail(&sinfo->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&sinfo->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for info");
+ region = MEM_callocN(sizeof(ARegion), "main region for info");
- BLI_addtail(&sinfo->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sinfo->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
/* keep in sync with console */
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
- ar->v2d.align |= V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y; /* align bottom left */
- ar->v2d.keepofs |= V2D_LOCKOFS_X;
- ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- ar->v2d.keeptot = V2D_KEEPTOT_BOUNDS;
- ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
+ region->v2d.scroll |= (V2D_SCROLL_RIGHT);
+ region->v2d.align |= V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y; /* align bottom left */
+ region->v2d.keepofs |= V2D_LOCKOFS_X;
+ region->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ region->v2d.keeptot = V2D_KEEPTOT_BOUNDS;
+ region->v2d.minzoom = region->v2d.maxzoom = 1.0f;
/* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- // ar->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM);
+ // region->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM);
return (SpaceLink *)sinfo;
}
@@ -97,7 +97,7 @@ static void info_free(SpaceLink *UNUSED(sl))
}
/* spacetype; init callback */
-static void info_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void info_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -111,33 +111,34 @@ static SpaceLink *info_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void info_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void info_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
/* force it on init, for old files, until it becomes config */
- ar->v2d.scroll = (V2D_SCROLL_RIGHT);
+ region->v2d.scroll = (V2D_SCROLL_RIGHT);
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Info", SPACE_INFO, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void info_textview_update_rect(const bContext *C, ARegion *ar)
+static void info_textview_update_rect(const bContext *C, ARegion *region)
{
SpaceInfo *sinfo = CTX_wm_space_info(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
- UI_view2d_totRect_set(v2d, ar->winx - 1, info_textview_height(sinfo, ar, CTX_wm_reports(C)));
+ UI_view2d_totRect_set(
+ v2d, region->winx - 1, info_textview_height(sinfo, region, CTX_wm_reports(C)));
}
-static void info_main_region_draw(const bContext *C, ARegion *ar)
+static void info_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceInfo *sinfo = CTX_wm_space_info(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
/* clear and setup matrix */
@@ -145,16 +146,16 @@ static void info_main_region_draw(const bContext *C, ARegion *ar)
GPU_clear(GPU_COLOR_BIT);
/* quick way to avoid drawing if not bug enough */
- if (ar->winy < 16) {
+ if (region->winy < 16) {
return;
}
- info_textview_update_rect(C, ar);
+ info_textview_update_rect(C, region);
/* worlks best with no view2d matrix set */
UI_view2d_view_ortho(v2d);
- info_textview_main(sinfo, ar, CTX_wm_reports(C));
+ info_textview_main(sinfo, region, CTX_wm_reports(C));
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -197,38 +198,38 @@ static void info_keymap(struct wmKeyConfig *keyconf)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void info_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void info_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void info_header_region_draw(const bContext *C, ARegion *ar)
+static void info_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
static void info_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
- // SpaceInfo *sinfo = sa->spacedata.first;
+ // SpaceInfo *sinfo = area->spacedata.first;
/* context changes */
switch (wmn->category) {
case NC_SPACE:
if (wmn->data == ND_SPACE_INFO_REPORT) {
/* redraw also but only for report view, could do less redraws by checking the type */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
}
static void info_header_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -236,27 +237,27 @@ static void info_header_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER, ND_ANIMPLAY)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_WM:
if (wmn->data == ND_JOB) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
if (wmn->data == ND_RENDER_RESULT) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_INFO) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -266,13 +267,13 @@ static void info_header_region_message_subscribe(const bContext *UNUSED(C),
WorkSpace *UNUSED(workspace),
Scene *UNUSED(scene),
bScreen *UNUSED(screen),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
struct wmMsgBus *mbus)
{
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 9828034aaac..c842fa8b4ac 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -18,30 +18,25 @@
* \ingroup spinfo
*/
-#include <math.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include <assert.h>
-
#include "MEM_guardedalloc.h"
#include "BLF_api.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_string_utf8.h"
+#include "BLI_utildefines.h"
#include "GPU_immediate.h"
#include "GPU_state.h"
-#include "BKE_report.h"
+#include "DNA_userdef_types.h" /* For 'U.dpi_fac' */
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "textview.h"
-static void console_font_begin(const int font_id, const int lheight)
+static void textview_font_begin(const int font_id, const int lheight)
{
/* Font size in relation to line height. */
BLF_size(font_id, 0.8f * lheight, 72);
@@ -53,12 +48,13 @@ typedef struct TextViewDrawState {
int lheight;
/** Text vertical offset per line. */
int lofs;
- int margin_left_chars;
- int margin_right_chars;
int row_vpadding;
/** Number of characters that fit into the width of the console (fixed width). */
int columns;
+ /** For drawing text. */
const rcti *draw_rect;
+ /** For drawing backgrounds colors which may extend beyond text. */
+ const rcti *draw_rect_outer;
int scroll_ymin, scroll_ymax;
int *xy; // [2]
int *sel; // [2]
@@ -68,26 +64,25 @@ typedef struct TextViewDrawState {
bool do_draw;
} TextViewDrawState;
-BLI_INLINE void console_step_sel(TextViewDrawState *tds, const int step)
+BLI_INLINE void textview_step_sel(TextViewDrawState *tds, const int step)
{
tds->sel[0] += step;
tds->sel[1] += step;
}
-static void console_draw_sel(const char *str,
- const int xy[2],
- const int str_len_draw,
- TextViewDrawState *tds,
- const unsigned char bg_sel[4])
+static void textview_draw_sel(const char *str,
+ const int xy[2],
+ const int str_len_draw,
+ TextViewDrawState *tds,
+ const uchar bg_sel[4])
{
const int sel[2] = {tds->sel[0], tds->sel[1]};
const int cwidth = tds->cwidth;
const int lheight = tds->lheight;
if (sel[0] <= str_len_draw && sel[1] >= 0) {
- const int sta = BLI_str_utf8_offset_to_column(str, max_ii(sel[0], 0)) + tds->margin_left_chars;
- const int end = BLI_str_utf8_offset_to_column(str, min_ii(sel[1], str_len_draw)) +
- tds->margin_left_chars;
+ const int sta = BLI_str_utf8_offset_to_column(str, max_ii(sel[0], 0));
+ const int end = BLI_str_utf8_offset_to_column(str, min_ii(sel[1], str_len_draw));
GPU_blend(true);
GPU_blend_set_func_separate(
@@ -98,7 +93,7 @@ static void console_draw_sel(const char *str,
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv(bg_sel);
- immRecti(pos, xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2);
+ immRecti(pos, xy[0] + (cwidth * sta), xy[1] + lheight, xy[0] + (cwidth * end), xy[1]);
immUnbindProgram();
@@ -107,28 +102,29 @@ static void console_draw_sel(const char *str,
}
/**
- * \warning Allocated memory for 'offsets' must be freed by caller.
+ * \warning Allocated memory for 'r_offsets' must be freed by caller.
* \return The length in bytes.
*/
-static int console_wrap_offsets(const char *str, int len, int width, int *lines, int **offsets)
+static int textview_wrap_offsets(
+ const char *str, int len, int width, int *r_lines, int **r_offsets)
{
int i, end; /* Offset as unicode code-point. */
int j; /* Offset as bytes. */
- *lines = 1;
+ *r_lines = 1;
- *offsets = MEM_callocN(
- sizeof(**offsets) *
+ *r_offsets = MEM_callocN(
+ sizeof(**r_offsets) *
(len * BLI_UTF8_WIDTH_MAX / MAX2(1, width - (BLI_UTF8_WIDTH_MAX - 1)) + 1),
- "console_wrap_offsets");
- (*offsets)[0] = 0;
+ __func__);
+ (*r_offsets)[0] = 0;
for (i = 0, end = width, j = 0; j < len && str[j]; j += BLI_str_utf8_size_safe(str + j)) {
int columns = BLI_str_utf8_char_width_safe(str + j);
if (i + columns > end) {
- (*offsets)[*lines] = j;
- (*lines)++;
+ (*r_offsets)[*r_lines] = j;
+ (*r_lines)++;
end = i + width;
}
@@ -141,25 +137,20 @@ static int console_wrap_offsets(const char *str, int len, int width, int *lines,
* return false if the last line is off the screen
* should be able to use this for any string type.
*/
-static bool console_draw_string(TextViewDrawState *tds,
- const char *str,
- int str_len,
- const unsigned char fg[4],
- const unsigned char bg[4],
- int icon,
- const unsigned char icon_fg[4],
- const unsigned char icon_bg[4],
- const unsigned char bg_sel[4])
+static bool textview_draw_string(TextViewDrawState *tds,
+ const char *str,
+ int str_len,
+ const uchar fg[4],
+ const uchar bg[4],
+ int icon,
+ const uchar icon_fg[4],
+ const uchar icon_bg[4],
+ const uchar bg_sel[4])
{
int tot_lines; /* Total number of lines for wrapping. */
int *offsets; /* Offsets of line beginnings for wrapping. */
- str_len = console_wrap_offsets(str,
- str_len,
- tds->columns - (tds->margin_left_chars + tds->margin_right_chars),
- &tot_lines,
- &offsets);
-
+ str_len = textview_wrap_offsets(str, str_len, tds->columns, &tot_lines, &offsets);
int line_height = (tot_lines * tds->lheight) + (tds->row_vpadding * 2);
int line_bottom = tds->xy[1];
@@ -201,7 +192,7 @@ static bool console_draw_string(TextViewDrawState *tds,
/* Adjust selection even if not drawing. */
if (tds->sel[0] != tds->sel[1]) {
- console_step_sel(tds, -(str_len + 1));
+ textview_step_sel(tds, -(str_len + 1));
}
MEM_freeN(offsets);
@@ -224,15 +215,15 @@ static bool console_draw_string(TextViewDrawState *tds,
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv(bg);
- immRecti(pos, 0, line_bottom, tds->draw_rect->xmax, line_top);
+ immRecti(pos, tds->draw_rect_outer->xmin, line_bottom, tds->draw_rect_outer->xmax, line_top);
immUnbindProgram();
}
if (icon_bg) {
float col[4];
- int bg_size = 20 * UI_DPI_FAC;
+ int bg_size = UI_DPI_ICON_SIZE * 1.2;
float vpadding = (tds->lheight + (tds->row_vpadding * 2) - bg_size) / 2;
- float hpadding = ((tds->margin_left_chars * tds->cwidth) - bg_size) / 2;
+ float hpadding = tds->draw_rect->xmin - (bg_size * 1.2f);
rgba_uchar_to_float(col, icon_bg);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
@@ -247,7 +238,7 @@ static bool console_draw_string(TextViewDrawState *tds,
if (icon) {
int vpadding = (tds->lheight + (tds->row_vpadding * 2) - UI_DPI_ICON_SIZE) / 2;
- int hpadding = ((tds->margin_left_chars * tds->cwidth) - UI_DPI_ICON_SIZE) / 2;
+ int hpadding = tds->draw_rect->xmin - (UI_DPI_ICON_SIZE * 1.3f);
GPU_blend(true);
UI_icon_draw_ex(hpadding,
@@ -267,17 +258,14 @@ static bool console_draw_string(TextViewDrawState *tds,
const int final_offset = offsets[tot_lines - 1];
len = str_len - final_offset;
s = str + final_offset;
- BLF_position(tds->font_id,
- tds->xy[0] + (tds->margin_left_chars * tds->cwidth),
- tds->lofs + line_bottom + tds->row_vpadding,
- 0);
+ BLF_position(tds->font_id, tds->xy[0], tds->lofs + line_bottom + tds->row_vpadding, 0);
BLF_color4ubv(tds->font_id, fg);
BLF_draw_mono(tds->font_id, s, len, tds->cwidth);
if (tds->sel[0] != tds->sel[1]) {
- console_step_sel(tds, -final_offset);
+ textview_step_sel(tds, -final_offset);
int pos[2] = {tds->xy[0], line_bottom};
- console_draw_sel(s, pos, len, tds, bg_sel);
+ textview_draw_sel(s, pos, len, tds, bg_sel);
}
tds->xy[1] += tds->lheight;
@@ -288,20 +276,17 @@ static bool console_draw_string(TextViewDrawState *tds,
len = offsets[i] - offsets[i - 1];
s = str + offsets[i - 1];
- BLF_position(tds->font_id,
- tds->xy[0] + (tds->margin_left_chars * tds->cwidth),
- tds->lofs + tds->xy[1],
- 0);
+ BLF_position(tds->font_id, tds->xy[0], tds->lofs + tds->xy[1], 0);
BLF_draw_mono(tds->font_id, s, len, tds->cwidth);
if (tds->sel[0] != tds->sel[1]) {
- console_step_sel(tds, len);
- console_draw_sel(s, tds->xy, len, tds, bg_sel);
+ textview_step_sel(tds, len);
+ textview_draw_sel(s, tds->xy, len, tds, bg_sel);
}
tds->xy[1] += tds->lheight;
- /* Check if were out of view bounds. */
+ /* Check if we're out of view bounds. */
if (tds->xy[1] > tds->scroll_ymax) {
MEM_freeN(offsets);
return false;
@@ -311,7 +296,7 @@ static bool console_draw_string(TextViewDrawState *tds,
tds->xy[1] = y_next;
copy_v2_v2_int(tds->sel, sel_orig);
- console_step_sel(tds, -(str_len + 1));
+ textview_step_sel(tds, -(str_len + 1));
MEM_freeN(offsets);
return true;
@@ -332,15 +317,15 @@ int textview_draw(TextViewContext *tvc,
{
TextViewDrawState tds = {0};
- int x_orig = tvc->draw_rect.xmin, y_orig = tvc->draw_rect.ymin + tvc->lheight / 6;
+ const int x_orig = tvc->draw_rect.xmin, y_orig = tvc->draw_rect.ymin;
int xy[2];
/* Disable selection by. */
int sel[2] = {-1, -1};
- unsigned char fg[4], bg[4], icon_fg[4], icon_bg[4];
+ uchar fg[4], bg[4], icon_fg[4], icon_bg[4];
int icon = 0;
const int font_id = blf_mono_font;
- console_font_begin(font_id, tvc->lheight);
+ textview_font_begin(font_id, tvc->lheight);
xy[0] = x_orig;
xy[1] = y_orig;
@@ -365,8 +350,6 @@ int textview_draw(TextViewContext *tvc,
tds.cwidth = (int)BLF_fixed_width(font_id);
BLI_assert(tds.cwidth > 0);
tds.lheight = tvc->lheight;
- tds.margin_left_chars = tvc->margin_left_chars;
- tds.margin_right_chars = tvc->margin_right_chars;
tds.row_vpadding = tvc->row_vpadding;
tds.lofs = -BLF_descender(font_id);
/* Note, scroll bar must be already subtracted. */
@@ -376,6 +359,7 @@ int textview_draw(TextViewContext *tvc,
tds.columns = 1;
}
tds.draw_rect = &tvc->draw_rect;
+ tds.draw_rect_outer = &tvc->draw_rect_outer;
tds.scroll_ymin = tvc->scroll_ymin;
tds.scroll_ymax = tvc->scroll_ymax;
tds.xy = xy;
@@ -384,23 +368,19 @@ int textview_draw(TextViewContext *tvc,
tds.mval = mval;
tds.do_draw = do_draw;
- /* Shouldnt be needed. */
- tvc->cwidth = tds.cwidth;
- tvc->columns = tds.columns;
- tvc->iter_index = 0;
-
if (tvc->sel_start != tvc->sel_end) {
sel[0] = tvc->sel_start;
sel[1] = tvc->sel_end;
}
if (tvc->begin(tvc)) {
- unsigned char bg_sel[4] = {0};
+ uchar bg_sel[4] = {0};
if (do_draw && tvc->const_colors) {
tvc->const_colors(tvc, bg_sel);
}
+ int iter_index = 0;
do {
const char *ext_line;
int ext_len;
@@ -414,15 +394,15 @@ int textview_draw(TextViewContext *tvc,
tvc->line_get(tvc, &ext_line, &ext_len);
- if (!console_draw_string(&tds,
- ext_line,
- ext_len,
- (data_flag & TVC_LINE_FG) ? fg : NULL,
- (data_flag & TVC_LINE_BG) ? bg : NULL,
- (data_flag & TVC_LINE_ICON) ? icon : 0,
- (data_flag & TVC_LINE_ICON_FG) ? icon_fg : NULL,
- (data_flag & TVC_LINE_ICON_BG) ? icon_bg : NULL,
- bg_sel)) {
+ if (!textview_draw_string(&tds,
+ ext_line,
+ ext_len,
+ (data_flag & TVC_LINE_FG) ? fg : NULL,
+ (data_flag & TVC_LINE_BG) ? bg : NULL,
+ (data_flag & TVC_LINE_ICON) ? icon : 0,
+ (data_flag & TVC_LINE_ICON_FG) ? icon_fg : NULL,
+ (data_flag & TVC_LINE_ICON_BG) ? icon_bg : NULL,
+ bg_sel)) {
/* When drawing, if we pass v2d->cur.ymax, then quit. */
if (do_draw) {
/* Past the y limits. */
@@ -431,8 +411,8 @@ int textview_draw(TextViewContext *tvc,
}
if (do_draw) {
- if (tvc->draw_cursor && tvc->iter_index == 0) {
- tvc->draw_cursor(tvc);
+ if (tvc->draw_cursor && iter_index == 0) {
+ tvc->draw_cursor(tvc, tds.cwidth, tds.columns, tds.lofs);
}
}
@@ -441,7 +421,7 @@ int textview_draw(TextViewContext *tvc,
break;
}
- tvc->iter_index++;
+ iter_index++;
} while (tvc->step(tvc));
}
diff --git a/source/blender/editors/space_info/textview.h b/source/blender/editors/space_info/textview.h
index 3f7ba9739c4..8eef4ef5d56 100644
--- a/source/blender/editors/space_info/textview.h
+++ b/source/blender/editors/space_info/textview.h
@@ -21,22 +21,26 @@
#ifndef __TEXTVIEW_H__
#define __TEXTVIEW_H__
+enum eTextViewContext_LineFlag {
+ TVC_LINE_FG = (1 << 0),
+ TVC_LINE_BG = (1 << 1),
+ TVC_LINE_ICON = (1 << 2),
+ TVC_LINE_ICON_FG = (1 << 3),
+ TVC_LINE_ICON_BG = (1 << 4)
+};
+
typedef struct TextViewContext {
/** Font size scaled by the interface size. */
int lheight;
/** Text selection, when a selection range is in use. */
int sel_start, sel_end;
- /* view settings */
- int cwidth; /* shouldnt be needed! */
- int columns; /* shouldnt be needed! */
-
int row_vpadding;
- int margin_left_chars;
- int margin_right_chars;
- /** Area to draw: (0, 0, winx, winy) with a margin applied and scroll-bar subtracted. */
+ /** Area to draw text: (0, 0, winx, winy) with a margin applied and scroll-bar subtracted. */
rcti draw_rect;
+ /** Area to draw text background colors (extending beyond text in some cases). */
+ rcti draw_rect_outer;
/** Scroll offset in pixels. */
int scroll_ymin, scroll_ymax;
@@ -44,27 +48,27 @@ typedef struct TextViewContext {
/* callbacks */
int (*begin)(struct TextViewContext *tvc);
void (*end)(struct TextViewContext *tvc);
- void *arg1;
- void *arg2;
+ const void *arg1;
+ const void *arg2;
/* iterator */
int (*step)(struct TextViewContext *tvc);
- int (*line_get)(struct TextViewContext *tvc, const char **, int *);
- int (*line_data)(struct TextViewContext *tvc,
- unsigned char fg[4],
- unsigned char bg[4],
- int *icon,
- unsigned char icon_fg[4],
- unsigned char icon_bg[4]);
- void (*draw_cursor)(struct TextViewContext *tvc);
+ void (*line_get)(struct TextViewContext *tvc, const char **r_line, int *r_len);
+ enum eTextViewContext_LineFlag (*line_data)(struct TextViewContext *tvc,
+ uchar fg[4],
+ uchar bg[4],
+ int *r_icon,
+ uchar r_icon_fg[4],
+ uchar r_icon_bg[4]);
+ void (*draw_cursor)(struct TextViewContext *tvc, int cwidth, int columns, int descender);
/* constant theme colors */
void (*const_colors)(struct TextViewContext *tvc, unsigned char bg_sel[4]);
- void *iter;
+ const void *iter;
int iter_index;
- /** Char index, used for multi-line report display. */
- int iter_char;
- /** Same as 'iter_char', next new-line. */
- int iter_char_next;
+ /** Used for internal multi-line iteration. */
+ int iter_char_begin;
+ /** The last character (not inclusive). */
+ int iter_char_end;
/** Internal iterator use. */
int iter_tmp;
@@ -76,12 +80,4 @@ int textview_draw(struct TextViewContext *tvc,
void **r_mval_pick_item,
int *r_mval_pick_offset);
-enum {
- TVC_LINE_FG = (1 << 0),
- TVC_LINE_BG = (1 << 1),
- TVC_LINE_ICON = (1 << 2),
- TVC_LINE_ICON_FG = (1 << 3),
- TVC_LINE_ICON_BG = (1 << 4)
-};
-
#endif /* __TEXTVIEW_H__ */
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 4277e579274..307b6d9bc21 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -21,10 +21,10 @@
* \ingroup spnla
*/
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_anim_types.h"
@@ -36,8 +36,8 @@
#include "BLT_translation.h"
-#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_nla.h"
#include "BKE_screen.h"
#include "WM_api.h"
@@ -140,7 +140,11 @@ bool nla_panel_context(const bContext *C,
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_PALETTE: {
+ case ANIMTYPE_PALETTE:
+ case ANIMTYPE_DSHAIR:
+ case ANIMTYPE_DSPOINTCLOUD:
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* for these channels, we only do AnimData */
if (ale->adt && adt_ptr) {
ID *id;
@@ -239,11 +243,11 @@ static bool nla_strip_eval_panel_poll(const bContext *C, PanelType *UNUSED(pt))
/* -------------- */
/* active AnimData */
-static void nla_panel_animdata(const bContext *C, Panel *pa)
+static void nla_panel_animdata(const bContext *C, Panel *panel)
{
PointerRNA adt_ptr;
/* AnimData *adt; */
- uiLayout *layout = pa->layout;
+ uiLayout *layout = panel->layout;
uiLayout *row;
uiBlock *block;
@@ -309,10 +313,10 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
}
/* generic settings for active NLA-Strip */
-static void nla_panel_stripname(const bContext *C, Panel *pa)
+static void nla_panel_stripname(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
+ uiLayout *layout = panel->layout;
uiLayout *row;
uiBlock *block;
@@ -347,11 +351,11 @@ static void nla_panel_stripname(const bContext *C, Panel *pa)
}
/* generic settings for active NLA-Strip */
-static void nla_panel_properties(const bContext *C, Panel *pa)
+static void nla_panel_properties(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
- uiLayout *column;
+ uiLayout *layout = panel->layout;
+ uiLayout *column, *row;
uiBlock *block;
short showEvalProps = 1;
@@ -398,28 +402,27 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
uiItemR(column, &strip_ptr, "blend_in", 0, IFACE_("Blend In"), ICON_NONE);
uiItemR(column, &strip_ptr, "blend_out", 0, IFACE_("Out"), ICON_NONE);
- column = uiLayoutColumn(layout, true);
- uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false);
- uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle?
-
- uiItemS(layout);
+ row = uiLayoutRow(column, true);
+ uiLayoutSetActive(row, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false);
+ uiItemR(row, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle?
/* settings */
- column = uiLayoutColumn(layout, true);
- uiLayoutSetActive(column,
+ column = uiLayoutColumnWithHeading(layout, true, "Playback");
+ row = uiLayoutRow(column, true);
+ uiLayoutSetActive(row,
!(RNA_boolean_get(&strip_ptr, "use_animated_influence") ||
RNA_boolean_get(&strip_ptr, "use_animated_time")));
- uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE);
+ uiItemR(row, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE);
- uiItemR(layout, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE);
+ uiItemR(column, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE);
}
}
/* action-clip only settings for active NLA-Strip */
-static void nla_panel_actclip(const bContext *C, Panel *pa)
+static void nla_panel_actclip(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
+ uiLayout *layout = panel->layout;
uiLayout *column, *row;
uiBlock *block;
@@ -439,15 +442,12 @@ static void nla_panel_actclip(const bContext *C, Panel *pa)
uiItemR(row, &strip_ptr, "action", 0, NULL, ICON_ACTION);
/* action extents */
- // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future?
column = uiLayoutColumn(layout, true);
uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Frame Start"), ICON_NONE);
uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End"), ICON_NONE);
- /* XXX: this layout may actually be too abstract and confusing,
- * and may be better using standard column layout. */
- row = uiLayoutRow(layout, false);
- uiItemR(row, &strip_ptr, "use_sync_length", 0, IFACE_("Sync Length"), ICON_NONE);
+ row = uiLayoutRowWithHeading(layout, false, "Sync Length");
+ uiItemR(row, &strip_ptr, "use_sync_length", 0, "", ICON_NONE);
uiItemO(row, IFACE_("Now"), ICON_FILE_REFRESH, "NLA_OT_action_sync_length");
/* action usage */
@@ -458,10 +458,10 @@ static void nla_panel_actclip(const bContext *C, Panel *pa)
}
/* evaluation settings for active NLA-Strip */
-static void nla_panel_animated_influence_header(const bContext *C, Panel *pa)
+static void nla_panel_animated_influence_header(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
+ uiLayout *layout = panel->layout;
uiLayout *col;
uiBlock *block;
@@ -478,10 +478,10 @@ static void nla_panel_animated_influence_header(const bContext *C, Panel *pa)
}
/* evaluation settings for active NLA-Strip */
-static void nla_panel_evaluation(const bContext *C, Panel *pa)
+static void nla_panel_evaluation(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
+ uiLayout *layout = panel->layout;
uiBlock *block;
/* check context and also validity of pointer */
@@ -497,10 +497,10 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa)
uiItemR(layout, &strip_ptr, "influence", 0, NULL, ICON_NONE);
}
-static void nla_panel_animated_strip_time_header(const bContext *C, Panel *pa)
+static void nla_panel_animated_strip_time_header(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
+ uiLayout *layout = panel->layout;
uiLayout *col;
uiBlock *block;
@@ -516,10 +516,10 @@ static void nla_panel_animated_strip_time_header(const bContext *C, Panel *pa)
uiItemR(col, &strip_ptr, "use_animated_time", 0, "", ICON_NONE);
}
-static void nla_panel_animated_strip_time(const bContext *C, Panel *pa)
+static void nla_panel_animated_strip_time(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
- uiLayout *layout = pa->layout;
+ uiLayout *layout = panel->layout;
uiBlock *block;
/* check context and also validity of pointer */
@@ -536,7 +536,7 @@ static void nla_panel_animated_strip_time(const bContext *C, Panel *pa)
}
/* F-Modifiers for active NLA-Strip */
-static void nla_panel_modifiers(const bContext *C, Panel *pa)
+static void nla_panel_modifiers(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
NlaStrip *strip;
@@ -550,12 +550,12 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
}
strip = strip_ptr.data;
- block = uiLayoutGetBlock(pa->layout);
+ block = uiLayoutGetBlock(panel->layout);
UI_block_func_handle_set(block, do_nla_region_buttons, NULL);
/* 'add modifier' button at top of panel */
{
- row = uiLayoutRow(pa->layout, false);
+ row = uiLayoutRow(panel->layout, false);
block = uiLayoutGetBlock(row);
// FIXME: we need to set the only-active property so that this
@@ -571,7 +571,7 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
/* draw each modifier */
for (fcm = strip->modifiers.first; fcm; fcm = fcm->next) {
- col = uiLayoutColumn(pa->layout, true);
+ col = uiLayoutColumn(panel->layout, true);
ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.owner_id, &strip->modifiers, fcm);
}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 456eb783706..d399ea47d7e 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -21,10 +21,10 @@
* \ingroup spnla
*/
-#include <string.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#include <math.h>
+#include <string.h>
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -33,13 +33,13 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BKE_animsys.h"
-#include "BKE_nla.h"
+#include "BKE_anim_data.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_nla.h"
+#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BKE_report.h"
#include "ED_anim_api.h"
#include "ED_keyframes_edit.h"
@@ -81,7 +81,7 @@ static int mouse_nla_channels(
bAnimListElem *ale;
int filter;
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
int notifierFlags = 0;
/* get the channel that was clicked on */
@@ -146,7 +146,7 @@ static int mouse_nla_channels(
else {
/* deselect all */
/* TODO: should this deselect all other types of channels too? */
- for (Base *b = view_layer->object_bases.first; b; b = b->next) {
+ LISTBASE_FOREACH (Base *, b, &view_layer->object_bases) {
ED_object_base_select(b, BA_DESELECT);
if (b->object->adt) {
b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
@@ -190,7 +190,11 @@ static int mouse_nla_channels(
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
- case ANIMTYPE_PALETTE: {
+ case ANIMTYPE_PALETTE:
+ case ANIMTYPE_DSHAIR:
+ case ANIMTYPE_DSPOINTCLOUD:
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* sanity checking... */
if (ale->adt) {
/* select/deselect */
@@ -361,7 +365,7 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEv
{
bAnimContext ac;
SpaceNla *snla;
- ARegion *ar;
+ ARegion *region;
View2D *v2d;
int channel_index;
int notifierFlags = 0;
@@ -375,8 +379,8 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEv
/* get useful pointers from animation context data */
snla = (SpaceNla *)ac.sl;
- ar = ac.ar;
- v2d = &ar->v2d;
+ region = ac.region;
+ v2d = &region->v2d;
/* select mode is either replace (deselect all, then add) or add/extend */
if (RNA_boolean_get(op->ptr, "extend")) {
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 913d2a06d46..5c4ccd96534 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -21,11 +21,11 @@
* \ingroup spnla
*/
-#include <string.h>
+#include <float.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#include <math.h>
-#include <float.h>
+#include <string.h>
#include "DNA_anim_types.h"
#include "DNA_node_types.h"
@@ -37,9 +37,9 @@
#include "BLI_dlrbTree.h"
#include "BLI_utildefines.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
-#include "BKE_context.h"
#include "BKE_screen.h"
#include "ED_anim_api.h"
@@ -55,8 +55,8 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "nla_private.h"
#include "nla_intern.h" /* own include */
+#include "nla_private.h"
/* *********************************************** */
/* Strips */
@@ -150,7 +150,7 @@ static void nla_action_draw_keyframes(
/* - disregard the selection status of keyframes so they draw a certain way
* - size is 6.0f which is smaller than the editable keyframes, so that there is a distinction
*/
- for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) {
+ LISTBASE_FOREACH (ActKeyColumn *, ak, &keys) {
draw_keyframe_shape(ak->cfra,
y,
6.0f,
@@ -207,7 +207,7 @@ static void nla_actionclip_draw_markers(
immUniformThemeColorShade(TH_STRIP_SELECT, shade);
immBeginAtMost(GPU_PRIM_LINES, BLI_listbase_count(&act->markers) * 2);
- for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
+ LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) {
float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP);
@@ -238,7 +238,7 @@ static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
/* just a solid color, so that it is very easy to spot */
int shade = 20;
/* draw the markers in the first level of strips only (if they are actions) */
- for (NlaStrip *nls = strip->strips.first; nls; nls = nls->next) {
+ LISTBASE_FOREACH (NlaStrip *, nls, &strip->strips) {
if (nls->type == NLASTRIP_TYPE_CLIP) {
nla_actionclip_draw_markers(nls, yminc, ymaxc, shade, false);
}
@@ -313,7 +313,7 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col
}
/* helper call for drawing influence/time control curves for a given NLA-strip */
-static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos)
+static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, uint pos)
{
const float yheight = ymaxc - yminc;
@@ -565,7 +565,7 @@ static void nla_draw_strip(SpaceNla *snla,
immBeginAtMost(GPU_PRIM_LINES, 4 * BLI_listbase_count(&strip->strips));
/* only draw first-level of child-strips, but don't draw any lines on the endpoints */
- for (NlaStrip *cs = strip->strips.first; cs; cs = cs->next) {
+ LISTBASE_FOREACH (NlaStrip *, cs, &strip->strips) {
/* draw start-line if not same as end of previous (and only if not the first strip)
* - on upper half of strip
*/
@@ -604,7 +604,7 @@ static void nla_draw_strip_text(AnimData *adt,
(nlt->flag & NLATRACK_SOLO) == 0);
char str[256];
size_t str_len;
- char col[4];
+ uchar col[4];
/* just print the name and the range */
if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
@@ -652,7 +652,7 @@ static void nla_draw_strip_frames_text(
NlaTrack *UNUSED(nlt), NlaStrip *strip, View2D *v2d, float UNUSED(yminc), float ymaxc)
{
const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */
- const char col[4] = {220, 220, 220, 255}; /* light gray */
+ const uchar col[4] = {220, 220, 220, 255}; /* light gray */
char numstr[32];
size_t numstr_len;
@@ -673,9 +673,9 @@ static void nla_draw_strip_frames_text(
/* ---------------------- */
-void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
+void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
const float text_margin_x = (8 * UI_DPI_FAC) * pixelx;
@@ -803,14 +803,14 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* *********************************************** */
/* Channel List */
-void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
+void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *region)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
SpaceNla *snla = (SpaceNla *)ac->sl;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
size_t items;
/* build list of channels to draw */
@@ -828,7 +828,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
/* need to do a view-sync here, so that the keys area doesn't jump around
* (it must copy this) */
- UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
+ UI_view2d_sync(NULL, ac->area, v2d, V2D_LOCK_COPY);
/* draw channels */
{ /* first pass: just the standard GL-drawing for backdrop + text */
@@ -848,7 +848,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
}
}
{ /* second pass: UI widgets */
- uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
size_t channel_index = 0;
float ymax = NLACHANNEL_FIRST_TOP(ac);
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 0f170b1f530..f68896e21d6 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -21,9 +21,9 @@
* \ingroup spnla
*/
-#include <string.h>
-#include <stdio.h>
#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -40,7 +40,7 @@
#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_report.h"
@@ -410,8 +410,8 @@ void NLA_OT_previewrange_set(wmOperatorType *ot)
/**
* Find the extents of the active channel
*
- * \param[out] min Bottom y-extent of channel
- * \param[out] max Top y-extent of channel
+ * \param[out] min: Bottom y-extent of channel.
+ * \param[out] max: Top y-extent of channel.
* \return Success of finding a selected channel
*/
static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, float *max)
@@ -469,7 +469,7 @@ static int nlaedit_viewall(bContext *C, const bool only_sel)
if (ANIM_animdata_get_context(C, &ac) == 0) {
return OPERATOR_CANCELLED;
}
- v2d = &ac.ar->v2d;
+ v2d = &ac.region->v2d;
/* set the horizontal range, with an extra offset so that the extreme keys will be in view */
get_nlastrip_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, only_sel);
@@ -526,7 +526,7 @@ static int nlaedit_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
void NLA_OT_view_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->idname = "NLA_OT_view_all";
ot->description = "Reset viewable area to show full strips range";
@@ -541,7 +541,7 @@ void NLA_OT_view_all(wmOperatorType *ot)
void NLA_OT_view_selected(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Selected";
+ ot->name = "Frame Selected";
ot->idname = "NLA_OT_view_selected";
ot->description = "Reset viewable area to show selected strips range";
@@ -587,6 +587,7 @@ void NLA_OT_view_frame(wmOperatorType *ot)
/* add the specified action as new strip */
static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
bAnimContext ac;
Scene *scene;
@@ -608,7 +609,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
cfra = (float)CFRA;
/* get action to use */
- act = BLI_findlink(&CTX_data_main(C)->actions, RNA_enum_get(op->ptr, "action"));
+ act = BLI_findlink(&bmain->actions, RNA_enum_get(op->ptr, "action"));
if (act == NULL) {
BKE_report(op->reports, RPT_ERROR, "No valid action to add");
@@ -1505,7 +1506,7 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
NlaTrack *nlt = (NlaTrack *)ale->data;
NlaStrip *strip, *stripN = NULL;
- NlaStrip *sa = NULL, *sb = NULL;
+ NlaStrip *area = NULL, *sb = NULL;
/* make temporary metastrips so that entire islands of selections can be moved around */
BKE_nlastrips_make_metas(&nlt->strips, 1);
@@ -1532,9 +1533,9 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
if (strip->flag & NLASTRIP_FLAG_SELECT) {
/* first or second strip? */
- if (sa == NULL) {
+ if (area == NULL) {
/* store as first */
- sa = strip;
+ area = strip;
}
else if (sb == NULL) {
/* store as second */
@@ -1555,7 +1556,7 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
"Too many clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected",
nlt->name);
}
- else if (sa == NULL) {
+ else if (area == NULL) {
/* no warning as this is just a common case,
* and it may get annoying when doing multiple tracks */
}
@@ -1572,24 +1573,24 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
/* remove these strips from the track,
* so that we can test if they can fit in the proposed places */
- BLI_remlink(&nlt->strips, sa);
+ BLI_remlink(&nlt->strips, area);
BLI_remlink(&nlt->strips, sb);
/* calculate new extents for strips */
/* a --> b */
nsa[0] = sb->start;
- nsa[1] = sb->start + (sa->end - sa->start);
+ nsa[1] = sb->start + (area->end - area->start);
/* b --> a */
- nsb[0] = sa->start;
- nsb[1] = sa->start + (sb->end - sb->start);
+ nsb[0] = area->start;
+ nsb[1] = area->start + (sb->end - sb->start);
/* check if the track has room for the strips to be swapped */
if (BKE_nlastrips_has_space(&nlt->strips, nsa[0], nsa[1]) &&
BKE_nlastrips_has_space(&nlt->strips, nsb[0], nsb[1])) {
/* set new extents for strips then */
- sa->start = nsa[0];
- sa->end = nsa[1];
- BKE_nlameta_flush_transforms(sa);
+ area->start = nsa[0];
+ area->end = nsa[1];
+ BKE_nlameta_flush_transforms(area);
sb->start = nsb[0];
sb->end = nsb[1];
@@ -1597,7 +1598,7 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
}
else {
/* not enough room to swap, so show message */
- if ((sa->flag & NLASTRIP_FLAG_TEMP_META) || (sb->flag & NLASTRIP_FLAG_TEMP_META)) {
+ if ((area->flag & NLASTRIP_FLAG_TEMP_META) || (sb->flag & NLASTRIP_FLAG_TEMP_META)) {
BKE_report(
op->reports,
RPT_WARNING,
@@ -1608,13 +1609,13 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
RPT_WARNING,
"Cannot swap '%s' and '%s' as one or both will not be able to fit in their "
"new places",
- sa->name,
+ area->name,
sb->name);
}
}
/* add strips back to track now */
- BKE_nlatrack_add_strip(nlt, sa);
+ BKE_nlatrack_add_strip(nlt, area);
BKE_nlatrack_add_strip(nlt, sb);
}
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index 2b20ab69fa7..6b0429230fe 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -42,8 +42,8 @@ void nla_buttons_register(ARegionType *art);
/* **************************************** */
/* nla_draw.c */
-void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar);
-void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar);
+void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region);
+void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *region);
/* **************************************** */
/* nla_select.c */
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 55470388e22..2e32c496170 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -21,8 +21,8 @@
* \ingroup spnla
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "DNA_scene_types.h"
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index 938e7f09881..ec41368b9f0 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -21,8 +21,8 @@
* \ingroup spnla
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
@@ -31,8 +31,8 @@
#include "BLI_blenlib.h"
-#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_nla.h"
#include "BKE_screen.h"
#include "ED_anim_api.h"
@@ -46,8 +46,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_view2d.h"
#include "UI_interface.h"
+#include "UI_view2d.h"
#include "nla_intern.h" // own include
@@ -231,7 +231,7 @@ static void box_select_nla_strips(bAnimContext *ac, rcti rect, short mode, short
int filter;
SpaceNla *snla = (SpaceNla *)ac->sl;
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
rctf rectf;
/* convert border-region to view coordinates */
@@ -285,7 +285,7 @@ static void nlaedit_strip_at_region_position(
*r_strip = NULL;
SpaceNla *snla = (SpaceNla *)ac->sl;
- View2D *v2d = &ac->ar->v2d;
+ View2D *v2d = &ac->region->v2d;
float view_x, view_y;
int channel_index;
@@ -308,7 +308,7 @@ static void nlaedit_strip_at_region_position(
if (ale->type == ANIMTYPE_NLATRACK) {
NlaTrack *nlt = (NlaTrack *)ale->data;
- for (NlaStrip *strip = nlt->strips.first; strip; strip = strip->next) {
+ LISTBASE_FOREACH (NlaStrip *, strip, &nlt->strips) {
if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) {
*r_ale = ale;
*r_strip = strip;
@@ -550,8 +550,8 @@ static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, const wm
/* handle mode-based testing */
if (leftright == NLAEDIT_LRSEL_TEST) {
Scene *scene = ac.scene;
- ARegion *ar = ac.ar;
- View2D *v2d = &ar->v2d;
+ ARegion *region = ac.region;
+ View2D *v2d = &region->v2d;
float x;
/* determine which side of the current frame mouse is on */
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 5cd2a86adf8..f060693d9f4 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -21,8 +21,8 @@
* \ingroup spnla
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "DNA_anim_types.h"
#include "DNA_collection_types.h"
@@ -36,15 +36,15 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "ED_space_api.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "ED_time_scrub_ui.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "RNA_access.h"
@@ -52,14 +52,14 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "nla_intern.h" /* own include */
#include "GPU_framebuffer.h"
+#include "nla_intern.h" /* own include */
/* ******************** default callbacks for nla space ***************** */
-static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
+static SpaceLink *nla_new(const ScrArea *area, const Scene *scene)
{
- ARegion *ar;
+ ARegion *region;
SpaceNla *snla;
snla = MEM_callocN(sizeof(SpaceNla), "initnla");
@@ -74,57 +74,57 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
snla->flag = SNLA_SHOW_MARKERS;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for nla");
+ region = MEM_callocN(sizeof(ARegion), "header for nla");
- BLI_addtail(&snla->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&snla->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* channel list region */
- ar = MEM_callocN(sizeof(ARegion), "channel list for nla");
- BLI_addtail(&snla->regionbase, ar);
- ar->regiontype = RGN_TYPE_CHANNELS;
- ar->alignment = RGN_ALIGN_LEFT;
+ region = MEM_callocN(sizeof(ARegion), "channel list for nla");
+ BLI_addtail(&snla->regionbase, region);
+ region->regiontype = RGN_TYPE_CHANNELS;
+ region->alignment = RGN_ALIGN_LEFT;
/* only need to set these settings since this will use the 'stack' configuration */
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
- ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+ region->v2d.scroll = V2D_SCROLL_BOTTOM;
+ region->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
/* ui buttons */
- ar = MEM_callocN(sizeof(ARegion), "buttons region for nla");
+ region = MEM_callocN(sizeof(ARegion), "buttons region for nla");
- BLI_addtail(&snla->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_RIGHT;
- ar->flag = RGN_FLAG_HIDDEN;
+ BLI_addtail(&snla->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_RIGHT;
+ region->flag = RGN_FLAG_HIDDEN;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for nla");
+ region = MEM_callocN(sizeof(ARegion), "main region for nla");
- BLI_addtail(&snla->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&snla->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.tot.xmin = (float)(SFRA - 10);
- ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f;
- ar->v2d.tot.xmax = (float)(EFRA + 10);
- ar->v2d.tot.ymax = 0.0f;
+ region->v2d.tot.xmin = (float)(SFRA - 10);
+ region->v2d.tot.ymin = (float)(-area->winy) / 3.0f;
+ region->v2d.tot.xmax = (float)(EFRA + 10);
+ region->v2d.tot.ymax = 0.0f;
- ar->v2d.cur = ar->v2d.tot;
+ region->v2d.cur = region->v2d.tot;
- ar->v2d.min[0] = 0.0f;
- ar->v2d.min[1] = 0.0f;
+ region->v2d.min[0] = 0.0f;
+ region->v2d.min[1] = 0.0f;
- ar->v2d.max[0] = MAXFRAMEF;
- ar->v2d.max[1] = 10000.0f;
+ region->v2d.max[0] = MAXFRAMEF;
+ region->v2d.max[1] = 10000.0f;
- ar->v2d.minzoom = 0.01f;
- ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
- ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
- ar->v2d.keepofs = V2D_KEEPOFS_Y;
- ar->v2d.align = V2D_ALIGN_NO_POS_Y;
- ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+ region->v2d.minzoom = 0.01f;
+ region->v2d.maxzoom = 50;
+ region->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ region->v2d.scroll |= (V2D_SCROLL_RIGHT);
+ region->v2d.keepzoom = V2D_LOCKZOOM_Y;
+ region->v2d.keepofs = V2D_KEEPOFS_Y;
+ region->v2d.align = V2D_ALIGN_NO_POS_Y;
+ region->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
return (SpaceLink *)snla;
}
@@ -141,9 +141,9 @@ static void nla_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void nla_init(struct wmWindowManager *wm, ScrArea *sa)
+static void nla_init(struct wmWindowManager *wm, ScrArea *area)
{
- SpaceNla *snla = (SpaceNla *)sa->spacedata.first;
+ SpaceNla *snla = (SpaceNla *)area->spacedata.first;
/* init dopesheet data if non-existent (i.e. for old files) */
if (snla->ads == NULL) {
@@ -151,7 +151,7 @@ static void nla_init(struct wmWindowManager *wm, ScrArea *sa)
snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
}
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
static SpaceLink *nla_duplicate(SpaceLink *sl)
@@ -165,32 +165,32 @@ static SpaceLink *nla_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void nla_channel_region_init(wmWindowManager *wm, ARegion *ar)
+static void nla_channel_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
/* ensure the 2d view sync works - main region has bottom scroller */
- ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+ region->v2d.scroll = V2D_SCROLL_BOTTOM;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
/* own keymap */
/* own channels map first to override some channel keymaps */
keymap = WM_keymap_ensure(wm->defaultconf, "NLA Channels", SPACE_NLA, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
/* now generic channels map for everything else that can apply */
keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
/* draw entirely, view changes should be handled here */
-static void nla_channel_region_draw(const bContext *C, ARegion *ar)
+static void nla_channel_region_draw(const bContext *C, ARegion *region)
{
bAnimContext ac;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
/* clear and setup matrix */
@@ -201,11 +201,11 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar)
/* data */
if (ANIM_animdata_get_context(C, &ac)) {
- draw_nla_channel_list(C, &ac, ar);
+ draw_nla_channel_list(C, &ac, region);
}
/* channel filter next to scrubbing area */
- ED_time_scrub_channel_search_draw(C, ar, ac.ads);
+ ED_time_scrub_channel_search_draw(C, region, ac.ads);
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -217,26 +217,26 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void nla_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void nla_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "NLA Editor", SPACE_NLA, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void nla_main_region_draw(const bContext *C, ARegion *ar)
+static void nla_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceNla *snla = CTX_wm_space_nla(C);
Scene *scene = CTX_data_scene(C);
bAnimContext ac;
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
short cfra_flag = 0;
@@ -249,7 +249,7 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
/* time grid */
UI_view2d_draw_lines_x__discrete_frames_or_seconds(v2d, scene, snla->flag & SNLA_DRAWTIME);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
/* start and end frame */
ANIM_draw_framerange(scene, v2d);
@@ -257,10 +257,10 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
/* data */
if (ANIM_animdata_get_context(C, &ac)) {
/* strips and backdrops */
- draw_nla_main_data(&ac, snla, ar);
+ draw_nla_main_data(&ac, snla, region);
/* text draw cached, in pixelspace now */
- UI_view2d_text_cache_draw(ar);
+ UI_view2d_text_cache_draw(region);
}
UI_view2d_view_ortho(v2d);
@@ -272,7 +272,7 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
ANIM_draw_cfra(C, v2d, cfra_flag);
/* markers */
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ UI_view2d_view_orthoSpecial(region, v2d, 1);
int marker_draw_flag = DRAW_MARKERS_MARGIN;
if (snla->flag & SNLA_SHOW_MARKERS) {
ED_markers_draw(C, marker_draw_flag);
@@ -284,12 +284,12 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
/* callback */
UI_view2d_view_ortho(v2d);
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
/* reset view matrix */
UI_view2d_view_restore(C);
- ED_time_scrub_draw(ar, scene, snla->flag & SNLA_DRAWTIME, true);
+ ED_time_scrub_draw(region, scene, snla->flag & SNLA_DRAWTIME, true);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -298,49 +298,51 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void nla_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void nla_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void nla_header_region_draw(const bContext *C, ARegion *ar)
+static void nla_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void nla_buttons_region_init(wmWindowManager *wm, ARegion *ar)
+static void nla_buttons_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void nla_buttons_region_draw(const bContext *C, ARegion *ar)
+static void nla_buttons_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
static void nla_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_SCENE:
switch (wmn->data) {
case ND_OB_ACTIVE:
case ND_FRAME:
case ND_MARKERS:
- ED_region_tag_redraw(ar);
+ case ND_LAYER_CONTENT:
+ case ND_OB_SELECT:
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -349,28 +351,29 @@ static void nla_region_listener(wmWindow *UNUSED(win),
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
case ND_KEYS:
- ED_region_tag_redraw(ar);
+ case ND_DRAW:
+ ED_region_tag_redraw(region);
break;
}
break;
default:
if (wmn->data == ND_KEYS) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
}
static void nla_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_SCENE:
switch (wmn->data) {
@@ -379,7 +382,9 @@ static void nla_main_region_listener(wmWindow *UNUSED(win),
case ND_FRAME:
case ND_FRAME_RANGE:
case ND_MARKERS:
- ED_region_tag_redraw(ar);
+ case ND_LAYER_CONTENT:
+ case ND_OB_SELECT:
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -389,30 +394,30 @@ static void nla_main_region_listener(wmWindow *UNUSED(win),
case ND_BONE_SELECT:
case ND_KEYS:
case ND_TRANSFORM:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_NODE:
switch (wmn->action) {
case NA_EDITED:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
default:
if (wmn->data == ND_KEYS) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -422,16 +427,16 @@ static void nla_main_region_message_subscribe(const struct bContext *UNUSED(C),
struct WorkSpace *UNUSED(workspace),
struct Scene *scene,
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceNLA, sa->spacedata.first, &ptr);
+ RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -461,20 +466,22 @@ static void nla_main_region_message_subscribe(const struct bContext *UNUSED(C),
}
static void nla_channel_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_SCENE:
switch (wmn->data) {
case ND_OB_ACTIVE:
- ED_region_tag_redraw(ar);
+ case ND_LAYER_CONTENT:
+ case ND_OB_SELECT:
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -483,18 +490,19 @@ static void nla_channel_region_listener(wmWindow *UNUSED(win),
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
case ND_KEYS:
- ED_region_tag_redraw(ar);
+ case ND_DRAW:
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
default:
if (wmn->data == ND_KEYS) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -504,16 +512,16 @@ static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *screen,
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
PointerRNA ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceNLA, sa->spacedata.first, &ptr);
+ RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -535,24 +543,27 @@ static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C
}
/* editor level listener */
-static void nla_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
+static void nla_listener(wmWindow *UNUSED(win),
+ ScrArea *area,
+ wmNotifier *wmn,
+ Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
// TODO: filter specific types of changes?
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case NC_SCENE:
#if 0
switch (wmn->data) {
case ND_OB_ACTIVE:
case ND_OB_SELECT:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
}
#endif
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case NC_OBJECT:
switch (wmn->data) {
@@ -560,19 +571,19 @@ static void nla_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Sc
/* do nothing */
break;
default:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_NLA) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
}
}
-static void nla_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void nla_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceNla *snla = (SpaceNla *)slink;
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index f8c30f9a688..4e21cdc9d16 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -75,6 +75,10 @@ if(WITH_OPENIMAGEDENOISE)
add_definitions(-DWITH_OPENIMAGEDENOISE)
endif()
+if (WITH_NEW_SIMULATION_TYPE)
+ add_definitions(-DWITH_NEW_SIMULATION_TYPE)
+endif()
+
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 35c9082b54c..44003a5b9bc 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -28,10 +28,10 @@
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
-#include "DNA_userdef_types.h"
+#include "DNA_space_types.h"
#include "DNA_text_types.h"
+#include "DNA_userdef_types.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -47,9 +47,9 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
-#include "GPU_platform.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_platform.h"
#include "GPU_state.h"
#include "RNA_access.h"
@@ -67,10 +67,14 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
-#include "node_intern.h" /* own include */
#include "NOD_composite.h"
#include "NOD_shader.h"
+#include "NOD_simulation.h"
#include "NOD_texture.h"
+#include "node_intern.h" /* own include */
+
+/* Default flags for uiItemR(). Name is kept short since this is used a lot in this file. */
+#define DEFAULT_FLAGS UI_ITEM_R_SPLIT_EMPTY_NAME
/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
@@ -93,7 +97,7 @@ static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *p
PointerRNA sockptr;
RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr);
- uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
+ uiItemR(layout, &sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -107,7 +111,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr
col = uiLayoutColumn(layout, false);
uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0);
- uiItemR(col, &sockptr, "default_value", UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(col, &sockptr, "default_value", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
}
static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -118,12 +122,12 @@ static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA
col = uiLayoutColumn(layout, false);
row = uiLayoutRow(col, true);
- uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE);
+ uiItemR(row, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE);
if (ELEM(ntree->type, NTREE_COMPOSIT, NTREE_TEXTURE)) {
- uiItemR(row, ptr, "use_alpha", 0, "", ICON_IMAGE_RGB_ALPHA);
+ uiItemR(row, ptr, "use_alpha", DEFAULT_FLAGS, "", ICON_IMAGE_RGB_ALPHA);
}
- uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -145,8 +149,8 @@ static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *pt
uiTemplateCurveMapping(layout, ptr, "curve", 's', false, false, false, false);
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "frame_start", 0, IFACE_("Sta"), ICON_NONE);
- uiItemR(row, ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
+ uiItemR(row, ptr, "frame_start", DEFAULT_FLAGS, IFACE_("Sta"), ICON_NONE);
+ uiItemR(row, ptr, "frame_end", DEFAULT_FLAGS, IFACE_("End"), ICON_NONE);
}
static void node_buts_colorramp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -196,7 +200,7 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *
PointerRNA sockptr;
RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr);
- uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
+ uiItemR(layout, &sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
}
#if 0 /* not used in 2.5x yet */
@@ -242,33 +246,33 @@ static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA
short multi = (node->id && ((Tex *)node->id)->use_nodes && (node->type != CMP_NODE_TEXTURE) &&
(node->type != TEX_NODE_TEXTURE));
- uiItemR(layout, ptr, "texture", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "texture", DEFAULT_FLAGS, "", ICON_NONE);
if (multi) {
/* Number Drawing not optimal here, better have a list*/
- uiItemR(layout, ptr, "node_output", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "node_output", DEFAULT_FLAGS, "", ICON_NONE);
}
}
static void node_shader_buts_clamp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "clamp_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "clamp_type", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "interpolation_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "interpolation_type", DEFAULT_FLAGS, "", ICON_NONE);
if (!ELEM(RNA_enum_get(ptr, "interpolation_type"),
NODE_MAP_RANGE_SMOOTHSTEP,
NODE_MAP_RANGE_SMOOTHERSTEP)) {
- uiItemR(layout, ptr, "clamp", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "clamp", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
static void node_buts_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "use_clamp", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static int node_resize_area_default(bNode *node, int x, int y)
@@ -376,7 +380,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
const int font_size = data->label_size / aspect;
const float margin = (float)(NODE_DY / 4);
int label_height;
- unsigned char color[3];
+ uchar color[3];
nodeLabel(ntree, node, label, sizeof(label));
@@ -447,7 +451,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
}
static void node_draw_frame(const bContext *C,
- ARegion *ar,
+ ARegion *region,
SpaceNode *snode,
bNodeTree *ntree,
bNode *node,
@@ -459,7 +463,7 @@ static void node_draw_frame(const bContext *C,
float alpha;
/* skip if out of view */
- if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == false) {
+ if (BLI_rctf_isect(&node->totr, &region->v2d.cur, NULL) == false) {
UI_block_end(C, node->block);
node->block = NULL;
return;
@@ -534,9 +538,9 @@ static int node_resize_area_frame(bNode *node, int x, int y)
static void node_buts_frame_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "label_size", 0, IFACE_("Label Size"), ICON_NONE);
- uiItemR(layout, ptr, "shrink", 0, IFACE_("Shrink"), ICON_NONE);
- uiItemR(layout, ptr, "text", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "label_size", DEFAULT_FLAGS, IFACE_("Label Size"), ICON_NONE);
+ uiItemR(layout, ptr, "shrink", DEFAULT_FLAGS, IFACE_("Shrink"), ICON_NONE);
+ uiItemR(layout, ptr, "text", DEFAULT_FLAGS, NULL, ICON_NONE);
}
#define NODE_REROUTE_SIZE 8.0f
@@ -569,7 +573,7 @@ static void node_draw_reroute_prepare(const bContext *UNUSED(C),
}
static void node_draw_reroute(const bContext *C,
- ARegion *ar,
+ ARegion *region,
SpaceNode *UNUSED(snode),
bNodeTree *ntree,
bNode *node,
@@ -579,8 +583,8 @@ static void node_draw_reroute(const bContext *C,
rctf *rct = &node->totr;
/* skip if out of view */
- if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
- node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax) {
+ if (node->totr.xmax < region->v2d.cur.xmin || node->totr.xmin > region->v2d.cur.xmax ||
+ node->totr.ymax < region->v2d.cur.ymin || node->totr.ymin > region->v2d.cur.ymax) {
UI_block_end(C, node->block);
node->block = NULL;
return;
@@ -638,7 +642,7 @@ static void node_draw_reroute(const bContext *C,
/* only draw input socket. as they all are placed on the same position.
* highlight also if node itself is selected, since we don't display the node body separately!
*/
- node_draw_sockets(&ar->v2d, C, ntree, node, false, node->flag & SELECT);
+ node_draw_sockets(&region->v2d, C, ntree, node, false, node->flag & SELECT);
UI_block_end(C, node->block);
UI_block_draw(C, node->block);
@@ -651,7 +655,7 @@ static void node_draw_reroute(const bContext *C,
static int node_tweak_area_reroute(bNode *node, int x, int y)
{
/* square of tweak radius */
- const float tweak_radius_sq = SQUARE(24);
+ const float tweak_radius_sq = square_f(24.0f);
bNodeSocket *sock = node->inputs.first;
float dx = sock->locx - x;
@@ -697,7 +701,7 @@ static void node_buts_image_user(uiLayout *layout,
col = uiLayoutColumn(layout, false);
- uiItemR(col, imaptr, "source", 0, "", ICON_NONE);
+ uiItemR(col, imaptr, "source", DEFAULT_FLAGS, "", ICON_NONE);
source = RNA_enum_get(imaptr, "source");
@@ -716,23 +720,23 @@ static void node_buts_image_user(uiLayout *layout,
if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "frame_duration", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "frame_start", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "frame_offset", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "use_cyclic", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "use_auto_refresh", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "frame_duration", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "frame_start", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "frame_offset", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_cyclic", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_auto_refresh", DEFAULT_FLAGS, NULL, ICON_NONE);
}
if (compositor && RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER &&
RNA_boolean_get(ptr, "has_layers")) {
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "layer", DEFAULT_FLAGS, NULL, ICON_NONE);
}
uiLayout *split = uiLayoutSplit(layout, 0.5f, true);
PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings");
uiItemL(split, IFACE_("Color Space"), ICON_NONE);
- uiItemR(split, &colorspace_settings_ptr, "name", 0, "", ICON_NONE);
+ uiItemR(split, &colorspace_settings_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE);
/* Avoid losing changes image is painted. */
if (BKE_image_is_dirty(imaptr->data)) {
@@ -742,29 +746,35 @@ static void node_buts_image_user(uiLayout *layout,
static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "vector_type", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS, NULL, ICON_NONE);
+}
+
+static void node_shader_buts_vector_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "rotation_type", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, 0);
}
static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- uiItemR(layout, ptr, "convert_from", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "convert_to", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "convert_from", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "convert_to", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "attribute_name", 0, IFACE_("Name"), ICON_NONE);
+ uiItemR(layout, ptr, "attribute_name", DEFAULT_FLAGS, IFACE_("Name"), ICON_NONE);
}
static void node_shader_buts_wireframe(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "use_pixel_size", 0, NULL, 0);
+ uiItemR(layout, ptr, "use_pixel_size", DEFAULT_FLAGS, NULL, 0);
}
static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -783,14 +793,14 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
UI_TEMPLATE_ID_FILTER_ALL,
false,
NULL);
- uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE);
if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) {
- uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE);
+ uiItemR(layout, ptr, "projection_blend", DEFAULT_FLAGS, "Blend", ICON_NONE);
}
- uiItemR(layout, ptr, "extension", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "extension", DEFAULT_FLAGS, "", ICON_NONE);
/* note: image user properties used directly here, unlike compositor image node,
* which redefines them in the node struct RNA to get proper updates.
@@ -821,8 +831,8 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
false,
NULL);
- uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE);
node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
}
@@ -832,29 +842,29 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P
PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
- uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE);
- uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, IFACE_("Interpolation"), ICON_NONE);
+ uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, IFACE_("Projection"), ICON_NONE);
}
static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "sky_type", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "sky_type", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "sun_direction", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NEW) {
- uiItemR(layout, ptr, "ground_albedo", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "ground_albedo", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "gradient_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "gradient_type", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "turbulence_depth", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "turbulence_depth", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -862,40 +872,48 @@ static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), Po
uiLayout *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "offset", UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE);
- uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE);
+ uiItemR(col, ptr, "offset", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE);
+ uiItemR(col, ptr, "offset_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE);
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE);
- uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE);
+ uiItemR(col, ptr, "squash", DEFAULT_FLAGS, IFACE_("Squash"), ICON_NONE);
+ uiItemR(col, ptr, "squash_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE);
}
static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "wave_profile", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "wave_type", DEFAULT_FLAGS, "", ICON_NONE);
+ int type = RNA_enum_get(ptr, "wave_type");
+ if (type == SHD_WAVE_BANDS) {
+ uiItemR(layout, ptr, "bands_direction", DEFAULT_FLAGS, "", ICON_NONE);
+ }
+ else { /* SHD_WAVE_RINGS */
+ uiItemR(layout, ptr, "rings_direction", DEFAULT_FLAGS, "", ICON_NONE);
+ }
+
+ uiItemR(layout, ptr, "wave_profile", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "musgrave_dimensions", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "musgrave_dimensions", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "musgrave_type", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "voronoi_dimensions", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "feature", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "voronoi_dimensions", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "feature", DEFAULT_FLAGS, "", ICON_NONE);
int feature = RNA_enum_get(ptr, "feature");
if (!ELEM(feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS) &&
RNA_enum_get(ptr, "voronoi_dimensions") != 1) {
- uiItemR(layout, ptr, "distance", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, "", ICON_NONE);
}
}
static void node_shader_buts_tex_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "noise_dimensions", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "noise_dimensions", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_tex_pointdensity(uiLayout *layout,
@@ -911,7 +929,7 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout,
RNA_id_pointer_create(ob ? (ID *)ob->data : NULL, &obdata_ptr);
uiItemR(layout, ptr, "point_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "object", DEFAULT_FLAGS, NULL, ICON_NONE);
if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
PointerRNA dataptr;
@@ -919,15 +937,15 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout,
uiItemPointerR(layout, ptr, "particle_system", &dataptr, "particle_systems", NULL, ICON_NONE);
}
- uiItemR(layout, ptr, "space", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "radius", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "interpolation", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "resolution", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "space", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "radius", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "resolution", DEFAULT_FLAGS, NULL, ICON_NONE);
if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
- uiItemR(layout, ptr, "particle_color_source", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "particle_color_source", DEFAULT_FLAGS, NULL, ICON_NONE);
}
else {
- uiItemR(layout, ptr, "vertex_color_source", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "vertex_color_source", DEFAULT_FLAGS, NULL, ICON_NONE);
if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTWEIGHT) {
if (ob_ptr.data) {
uiItemPointerR(
@@ -945,18 +963,18 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout,
static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "object", 0, NULL, 0);
- uiItemR(layout, ptr, "from_instancer", 0, NULL, 0);
+ uiItemR(layout, ptr, "object", DEFAULT_FLAGS, NULL, 0);
+ uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, NULL, 0);
}
static void node_shader_buts_bump(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "invert", 0, NULL, 0);
+ uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, 0);
}
static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiItemR(layout, ptr, "from_instancer", 0, NULL, 0);
+ uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, NULL, 0);
if (!RNA_boolean_get(ptr, "from_instancer")) {
PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
@@ -982,12 +1000,12 @@ static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, Pointer
static void node_shader_buts_uvalongstroke(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "use_tips", 0, NULL, 0);
+ uiItemR(layout, ptr, "use_tips", DEFAULT_FLAGS, NULL, 0);
}
static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- uiItemR(layout, ptr, "space", 0, "", 0);
+ uiItemR(layout, ptr, "space", DEFAULT_FLAGS, "", 0);
if (RNA_enum_get(ptr, "space") == SHD_SPACE_TANGENT) {
PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
@@ -997,14 +1015,14 @@ static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRN
uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
}
else {
- uiItemR(layout, ptr, "uv_map", 0, "", 0);
+ uiItemR(layout, ptr, "uv_map", DEFAULT_FLAGS, "", 0);
}
}
}
static void node_shader_buts_displacement(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "space", 0, "", 0);
+ uiItemR(layout, ptr, "space", DEFAULT_FLAGS, "", 0);
}
static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -1013,7 +1031,7 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *
split = uiLayoutSplit(layout, 0.0f, false);
- uiItemR(split, ptr, "direction_type", 0, "", 0);
+ uiItemR(split, ptr, "direction_type", DEFAULT_FLAGS, "", 0);
row = uiLayoutRow(split, false);
@@ -1025,50 +1043,50 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *
uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
}
else {
- uiItemR(row, ptr, "uv_map", 0, "", 0);
+ uiItemR(row, ptr, "uv_map", DEFAULT_FLAGS, "", 0);
}
}
else {
- uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, 0);
+ uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, 0);
}
}
static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_principled(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "subsurface_method", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "subsurface_method", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_anisotropic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_subsurface(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "falloff", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "falloff", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_toon(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "component", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "component", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_principled_hair(uiLayout *layout,
bContext *UNUSED(C),
PointerRNA *ptr)
{
- uiItemR(layout, ptr, "parametrization", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "parametrization", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1076,15 +1094,15 @@ static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerR
uiLayout *row;
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
row = uiLayoutRow(layout, true);
if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL) {
- uiItemR(row, ptr, "ies", 0, "", ICON_NONE);
+ uiItemR(row, ptr, "ies", DEFAULT_FLAGS, "", ICON_NONE);
}
else {
- uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
+ uiItemR(row, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE);
}
}
@@ -1093,15 +1111,15 @@ static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), Point
uiLayout *row;
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
row = uiLayoutRow(layout, true);
if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_INTERNAL) {
- uiItemR(row, ptr, "script", 0, "", ICON_NONE);
+ uiItemR(row, ptr, "script", DEFAULT_FLAGS, "", ICON_NONE);
}
else {
- uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
+ uiItemR(row, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE);
}
uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update");
@@ -1115,14 +1133,14 @@ static void node_shader_buts_script_ex(uiLayout *layout, bContext *C, PointerRNA
#if 0 /* not implemented yet */
if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) {
- uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_auto_update", DEFAULT_FLAGS, NULL, ICON_NONE);
}
#endif
}
static void node_buts_output_shader(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "target", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "target", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1131,32 +1149,32 @@ static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), Po
col = uiLayoutColumn(layout, false);
row = uiLayoutRow(col, true);
- uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE);
- uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_shader_buts_ambient_occlusion(uiLayout *layout,
bContext *UNUSED(C),
PointerRNA *ptr)
{
- uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "inside", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "inside", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "only_local", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_shader_buts_white_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "noise_dimensions", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "noise_dimensions", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_shader_buts_output_aov(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "name", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "name", DEFAULT_FLAGS, NULL, ICON_NONE);
}
/* only once called */
@@ -1199,6 +1217,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_VECTOR_MATH:
ntype->draw_buttons = node_shader_buts_vect_math;
break;
+ case SH_NODE_VECTOR_ROTATE:
+ ntype->draw_buttons = node_shader_buts_vector_rotate;
+ break;
case SH_NODE_VECT_TRANSFORM:
ntype->draw_buttons = node_shader_buts_vect_transform;
break;
@@ -1338,10 +1359,10 @@ static void node_buts_image_views(uiLayout *layout,
if (RNA_boolean_get(ptr, "has_views")) {
if (RNA_enum_get(ptr, "view") == 0) {
- uiItemR(col, ptr, "view", 0, NULL, ICON_CAMERA_STEREO);
+ uiItemR(col, ptr, "view", DEFAULT_FLAGS, NULL, ICON_CAMERA_STEREO);
}
else {
- uiItemR(col, ptr, "view", 0, NULL, ICON_SCENE);
+ uiItemR(col, ptr, "view", DEFAULT_FLAGS, NULL, ICON_SCENE);
}
}
}
@@ -1402,7 +1423,7 @@ static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, Pointer
col = uiLayoutColumn(layout, false);
row = uiLayoutRow(col, true);
- uiItemR(row, ptr, "layer", 0, "", ICON_NONE);
+ uiItemR(row, ptr, "layer", DEFAULT_FLAGS, "", ICON_NONE);
prop = RNA_struct_find_property(ptr, "layer");
if (!(RNA_property_enum_identifier(
@@ -1429,56 +1450,56 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point
filter = RNA_enum_get(ptr, "filter_type");
reference = RNA_boolean_get(ptr, "use_variable_size");
- uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE);
+ uiItemR(col, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE);
if (filter != R_FILTER_FAST_GAUSS) {
- uiItemR(col, ptr, "use_variable_size", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_variable_size", DEFAULT_FLAGS, NULL, ICON_NONE);
if (!reference) {
- uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_bokeh", DEFAULT_FLAGS, NULL, ICON_NONE);
}
- uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_gamma_correction", DEFAULT_FLAGS, NULL, ICON_NONE);
}
- uiItemR(col, ptr, "use_relative", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_relative", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_boolean_get(ptr, "use_relative")) {
uiItemL(col, IFACE_("Aspect Correction"), ICON_NONE);
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "aspect_correction", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, ptr, "aspect_correction", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "factor_x", 0, IFACE_("X"), ICON_NONE);
- uiItemR(col, ptr, "factor_y", 0, IFACE_("Y"), ICON_NONE);
+ uiItemR(col, ptr, "factor_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE);
+ uiItemR(col, ptr, "factor_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE);
}
else {
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "size_x", 0, IFACE_("X"), ICON_NONE);
- uiItemR(col, ptr, "size_y", 0, IFACE_("Y"), ICON_NONE);
+ uiItemR(col, ptr, "size_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE);
+ uiItemR(col, ptr, "size_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE);
}
- uiItemR(col, ptr, "use_extended_bounds", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_extended_bounds", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *col;
- uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "use_wrap", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_wrap", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(layout, true);
uiItemL(col, IFACE_("Center:"), ICON_NONE);
- uiItemR(col, ptr, "center_x", 0, IFACE_("X"), ICON_NONE);
- uiItemR(col, ptr, "center_y", 0, IFACE_("Y"), ICON_NONE);
+ uiItemR(col, ptr, "center_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE);
+ uiItemR(col, ptr, "center_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE);
uiItemS(layout);
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE);
uiItemS(layout);
- uiItemR(layout, ptr, "spin", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "zoom", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "spin", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "zoom", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_bilateralblur(uiLayout *layout,
@@ -1488,9 +1509,9 @@ static void node_composit_buts_bilateralblur(uiLayout *layout,
uiLayout *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "sigma_color", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "sigma_space", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "sigma_color", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "sigma_space", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -1499,60 +1520,60 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA
col = uiLayoutColumn(layout, false);
uiItemL(col, IFACE_("Bokeh Type:"), ICON_NONE);
- uiItemR(col, ptr, "bokeh", 0, "", ICON_NONE);
- uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "bokeh", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(col, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE);
- uiItemR(layout, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_gamma_correction", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(layout, false);
uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer") == true);
- uiItemR(col, ptr, "f_stop", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "f_stop", DEFAULT_FLAGS, NULL, ICON_NONE);
- uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_preview", DEFAULT_FLAGS, NULL, ICON_NONE);
uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_zbuffer", DEFAULT_FLAGS, NULL, ICON_NONE);
sub = uiLayoutColumn(col, false);
uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer") == false);
- uiItemR(sub, ptr, "z_scale", 0, NULL, ICON_NONE);
+ uiItemR(sub, ptr, "z_scale", DEFAULT_FLAGS, NULL, ICON_NONE);
}
/* qdn: glare node */
static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "glare_type", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "quality", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "glare_type", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "quality", DEFAULT_FLAGS, "", ICON_NONE);
if (RNA_enum_get(ptr, "glare_type") != 1) {
- uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "glare_type") != 0) {
- uiItemR(layout, ptr, "color_modulation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "color_modulation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
}
- uiItemR(layout, ptr, "mix", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "mix", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "glare_type") == 2) {
- uiItemR(layout, ptr, "streaks", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "angle_offset", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "streaks", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "angle_offset", DEFAULT_FLAGS, NULL, ICON_NONE);
}
if (RNA_enum_get(ptr, "glare_type") == 0 || RNA_enum_get(ptr, "glare_type") == 2) {
- uiItemR(layout, ptr, "fade", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "fade", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "glare_type") == 0) {
- uiItemR(layout, ptr, "use_rotate_45", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_rotate_45", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
if (RNA_enum_get(ptr, "glare_type") == 1) {
- uiItemR(layout, ptr, "size", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "size", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
@@ -1561,17 +1582,17 @@ static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), Po
uiLayout *col;
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "tonemap_type", 0, "", ICON_NONE);
+ uiItemR(col, ptr, "tonemap_type", DEFAULT_FLAGS, "", ICON_NONE);
if (RNA_enum_get(ptr, "tonemap_type") == 0) {
- uiItemR(col, ptr, "key", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "gamma", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "key", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE);
}
else {
- uiItemR(col, ptr, "intensity", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "adaptation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "correction", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "intensity", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "adaptation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "correction", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
}
@@ -1580,12 +1601,12 @@ static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), P
uiLayout *col;
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "use_projector", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_projector", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(col, false);
uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector") == false);
- uiItemR(col, ptr, "use_jitter", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "use_fit", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_jitter", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_fit", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1593,46 +1614,46 @@ static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), Po
uiLayout *col;
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "samples", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "factor", 0, IFACE_("Blur"), ICON_NONE);
+ uiItemR(col, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "factor", DEFAULT_FLAGS, IFACE_("Blur"), ICON_NONE);
col = uiLayoutColumn(layout, true);
uiItemL(col, IFACE_("Speed:"), ICON_NONE);
- uiItemR(col, ptr, "speed_min", 0, IFACE_("Min"), ICON_NONE);
- uiItemR(col, ptr, "speed_max", 0, IFACE_("Max"), ICON_NONE);
+ uiItemR(col, ptr, "speed_min", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
+ uiItemR(col, ptr, "speed_max", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
- uiItemR(layout, ptr, "use_curved", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_curved", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_filter(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_flip(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "axis", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "axis", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *col;
- uiItemR(layout, ptr, "use_crop_size", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "relative", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_crop_size", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "relative", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(layout, true);
if (RNA_boolean_get(ptr, "relative")) {
- uiItemR(col, ptr, "rel_min_x", 0, IFACE_("Left"), ICON_NONE);
- uiItemR(col, ptr, "rel_max_x", 0, IFACE_("Right"), ICON_NONE);
- uiItemR(col, ptr, "rel_min_y", 0, IFACE_("Up"), ICON_NONE);
- uiItemR(col, ptr, "rel_max_y", 0, IFACE_("Down"), ICON_NONE);
+ uiItemR(col, ptr, "rel_min_x", DEFAULT_FLAGS, IFACE_("Left"), ICON_NONE);
+ uiItemR(col, ptr, "rel_max_x", DEFAULT_FLAGS, IFACE_("Right"), ICON_NONE);
+ uiItemR(col, ptr, "rel_min_y", DEFAULT_FLAGS, IFACE_("Up"), ICON_NONE);
+ uiItemR(col, ptr, "rel_max_y", DEFAULT_FLAGS, IFACE_("Down"), ICON_NONE);
}
else {
- uiItemR(col, ptr, "min_x", 0, IFACE_("Left"), ICON_NONE);
- uiItemR(col, ptr, "max_x", 0, IFACE_("Right"), ICON_NONE);
- uiItemR(col, ptr, "min_y", 0, IFACE_("Up"), ICON_NONE);
- uiItemR(col, ptr, "max_y", 0, IFACE_("Down"), ICON_NONE);
+ uiItemR(col, ptr, "min_x", DEFAULT_FLAGS, IFACE_("Left"), ICON_NONE);
+ uiItemR(col, ptr, "max_x", DEFAULT_FLAGS, IFACE_("Right"), ICON_NONE);
+ uiItemR(col, ptr, "min_y", DEFAULT_FLAGS, IFACE_("Up"), ICON_NONE);
+ uiItemR(col, ptr, "max_y", DEFAULT_FLAGS, IFACE_("Down"), ICON_NONE);
}
}
@@ -1642,8 +1663,8 @@ static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C)
col = uiLayoutColumn(layout, false);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- uiItemR(col, ptr, "factor", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(col, ptr, "factor", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_double_edge_mask(uiLayout *layout,
@@ -1655,9 +1676,9 @@ static void node_composit_buts_double_edge_mask(uiLayout *layout,
col = uiLayoutColumn(layout, false);
uiItemL(col, IFACE_("Inner Edge:"), ICON_NONE);
- uiItemR(col, ptr, "inner_mode", 0, "", ICON_NONE);
+ uiItemR(col, ptr, "inner_mode", DEFAULT_FLAGS, "", ICON_NONE);
uiItemL(col, IFACE_("Buffer Edge:"), ICON_NONE);
- uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE);
+ uiItemR(col, ptr, "edge_mode", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1665,7 +1686,7 @@ static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C),
uiLayout *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1673,20 +1694,20 @@ static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C),
uiLayout *sub, *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "size", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "size", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "use_min", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_min", DEFAULT_FLAGS, NULL, ICON_NONE);
sub = uiLayoutColumn(col, false);
uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
- uiItemR(sub, ptr, "min", 0, "", ICON_NONE);
+ uiItemR(sub, ptr, "min", DEFAULT_FLAGS, "", ICON_NONE);
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "use_max", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_max", DEFAULT_FLAGS, NULL, ICON_NONE);
sub = uiLayoutColumn(col, false);
uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
- uiItemR(sub, ptr, "max", 0, "", ICON_NONE);
+ uiItemR(sub, ptr, "max", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1694,8 +1715,8 @@ static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C),
uiLayout *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "use_premultiply", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "premul", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_premultiply", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "premul", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1703,27 +1724,27 @@ static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), P
uiLayout *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "use_alpha", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "use_antialias_z", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_antialias_z", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE);
switch (RNA_enum_get(ptr, "mode")) {
case CMP_NODE_DILATEERODE_DISTANCE_THRESH:
- uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "edge", DEFAULT_FLAGS, NULL, ICON_NONE);
break;
case CMP_NODE_DILATEERODE_DISTANCE_FEATHER:
- uiItemR(layout, ptr, "falloff", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "falloff", DEFAULT_FLAGS, NULL, ICON_NONE);
break;
}
}
static void node_composit_buts_inpaint(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1731,8 +1752,8 @@ static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C),
uiLayout *col;
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "threshold_neighbor", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "threshold_neighbor", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1740,8 +1761,8 @@ static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C),
uiLayout *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_distance_matte(uiLayout *layout,
@@ -1754,10 +1775,10 @@ static void node_composit_buts_distance_matte(uiLayout *layout,
uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1766,23 +1787,23 @@ static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C)
uiItemL(layout, IFACE_("Despill Channel:"), ICON_NONE);
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "limit_method") == 0) {
uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
}
- uiItemR(col, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "use_unspill", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "ratio", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_unspill", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_boolean_get(ptr, "use_unspill") == true) {
- uiItemR(col, ptr, "unspill_red", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "unspill_green", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "unspill_blue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "unspill_red", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "unspill_green", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "unspill_blue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
}
@@ -1791,12 +1812,12 @@ static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C
uiLayout *col;
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "tolerance", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(layout, true);
/*uiItemR(col, ptr, "lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now */
- uiItemR(col, ptr, "gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
/*uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now*/
}
@@ -1805,9 +1826,9 @@ static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C)
uiLayout *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "color_hue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "color_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "color_value", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_channel_matte(uiLayout *layout,
@@ -1818,24 +1839,24 @@ static void node_composit_buts_channel_matte(uiLayout *layout,
uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "color_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, ptr, "color_space", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
col = uiLayoutColumn(layout, false);
uiItemL(col, IFACE_("Key Channel:"), ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "matte_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, ptr, "matte_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "limit_method") == 0) {
uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
}
- uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1843,19 +1864,19 @@ static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C),
uiLayout *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_map_uv(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "alpha", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "alpha", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "index", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "index", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_antialiasing", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1869,7 +1890,7 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C)
else {
uiItemL(layout, IFACE_("Base Path:"), ICON_NONE);
}
- uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "base_path", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
@@ -1955,7 +1976,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
uiItemL(col, IFACE_("Layer:"), ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &active_input_ptr, "name", 0, "", ICON_NONE);
+ uiItemR(row, &active_input_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE);
uiItemFullO(row,
"NODE_OT_output_file_remove_active_socket",
"",
@@ -1970,7 +1991,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
uiItemL(col, IFACE_("File Subpath:"), ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE);
+ uiItemR(row, &active_input_ptr, "path", DEFAULT_FLAGS, "", ICON_NONE);
uiItemFullO(row,
"NODE_OT_output_file_remove_active_socket",
"",
@@ -1985,7 +2006,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
col = uiLayoutColumn(layout, true);
uiItemL(col, IFACE_("Format:"), ICON_NONE);
- uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, ICON_NONE);
+ uiItemR(col, &active_input_ptr, "use_node_format", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(layout, false);
uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == false);
@@ -2000,20 +2021,20 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "space", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "space", DEFAULT_FLAGS, "", ICON_NONE);
if (RNA_enum_get(ptr, "space") == CMP_SCALE_RENDERPERCENT) {
uiLayout *row;
- uiItemR(layout, ptr, "frame_method", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "frame_method", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "offset_x", 0, "X", ICON_NONE);
- uiItemR(row, ptr, "offset_y", 0, "Y", ICON_NONE);
+ uiItemR(row, ptr, "offset_x", DEFAULT_FLAGS, "X", ICON_NONE);
+ uiItemR(row, ptr, "offset_y", DEFAULT_FLAGS, "Y", ICON_NONE);
}
}
static void node_composit_buts_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -2021,25 +2042,25 @@ static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), Poi
uiLayout *col;
col = uiLayoutColumn(layout, false);
- uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "invert_alpha", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "invert_rgb", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "invert_alpha", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_premulkey(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "mapping", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_view_levels(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
}
static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *split, *col, *row;
- uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "correction_method") == 0) {
@@ -2047,17 +2068,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C
col = uiLayoutColumn(split, false);
uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "lift", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(split, false);
uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(split, false);
uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "gain", DEFAULT_FLAGS, NULL, ICON_NONE);
}
else {
@@ -2065,46 +2086,46 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C
col = uiLayoutColumn(split, false);
uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "offset_basis", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "offset_basis", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(split, false);
uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "power", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "power", DEFAULT_FLAGS, NULL, ICON_NONE);
col = uiLayoutColumn(split, false);
uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1);
row = uiLayoutRow(col, false);
- uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "slope", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
static void node_composit_buts_colorbalance_ex(uiLayout *layout,
bContext *UNUSED(C),
PointerRNA *ptr)
{
- uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "correction_method") == 0) {
uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1);
- uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "lift", DEFAULT_FLAGS, NULL, ICON_NONE);
uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1);
- uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE);
uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1);
- uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "gain", DEFAULT_FLAGS, NULL, ICON_NONE);
}
else {
uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1);
- uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE);
uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1);
- uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "power", DEFAULT_FLAGS, NULL, ICON_NONE);
uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1);
- uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "slope", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
@@ -2126,7 +2147,7 @@ static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C),
static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -2163,19 +2184,19 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe
return;
}
- uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
- uiItemR(layout, ptr, "invert", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_translate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "use_relative", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "wrap_axis", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_relative", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "wrap_axis", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -2189,7 +2210,7 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po
return;
}
- uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "distortion_type", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_colorcorrection(uiLayout *layout,
@@ -2199,9 +2220,9 @@ static void node_composit_buts_colorcorrection(uiLayout *layout,
uiLayout *row;
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "red", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(row, ptr, "green", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(row, ptr, "blue", DEFAULT_FLAGS, NULL, ICON_NONE);
row = uiLayoutRow(layout, false);
uiItemL(row, "", ICON_NONE);
@@ -2213,39 +2234,39 @@ static void node_composit_buts_colorcorrection(uiLayout *layout,
row = uiLayoutRow(layout, false);
uiItemL(row, IFACE_("Master"), ICON_NONE);
- uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "master_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "master_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "master_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "master_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "master_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
row = uiLayoutRow(layout, false);
uiItemL(row, IFACE_("Highlights"), ICON_NONE);
- uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "highlights_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "highlights_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "highlights_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "highlights_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "highlights_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
row = uiLayoutRow(layout, false);
uiItemL(row, IFACE_("Midtones"), ICON_NONE);
- uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "midtones_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "midtones_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "midtones_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "midtones_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "midtones_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
row = uiLayoutRow(layout, false);
uiItemL(row, IFACE_("Shadows"), ICON_NONE);
- uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
- uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "shadows_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "shadows_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "shadows_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "shadows_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
+ uiItemR(row, ptr, "shadows_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE);
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "midtones_start", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_colorcorrection_ex(uiLayout *layout,
@@ -2255,48 +2276,48 @@ static void node_composit_buts_colorcorrection_ex(uiLayout *layout,
uiLayout *row;
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "red", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(row, ptr, "green", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(row, ptr, "blue", DEFAULT_FLAGS, NULL, ICON_NONE);
row = layout;
uiItemL(row, IFACE_("Saturation"), ICON_NONE);
- uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "master_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "highlights_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "shadows_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
uiItemL(row, IFACE_("Contrast"), ICON_NONE);
- uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "master_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "highlights_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "shadows_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
uiItemL(row, IFACE_("Gamma"), ICON_NONE);
- uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "master_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "highlights_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "shadows_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
uiItemL(row, IFACE_("Gain"), ICON_NONE);
- uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "master_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "highlights_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "shadows_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
uiItemL(row, IFACE_("Lift"), ICON_NONE);
- uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "master_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "highlights_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "shadows_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
row = uiLayoutRow(layout, false);
- uiItemR(row, ptr, "midtones_start", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "midtones_end", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "check", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_switch_view_ex(uiLayout *layout,
@@ -2318,32 +2339,32 @@ static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), Po
uiLayout *row;
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "x", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(row, ptr, "y", DEFAULT_FLAGS, NULL, ICON_NONE);
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_bokehimage(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "flaps", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "rounding", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(layout, ptr, "catadioptric", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(layout, ptr, "shift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "flaps", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "rounding", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "catadioptric", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "shift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_bokehblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "use_variable_size", 0, NULL, ICON_NONE);
- // uiItemR(layout, ptr, "f_stop", 0, NULL, ICON_NONE); // UNUSED
- uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "use_extended_bounds", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_variable_size", DEFAULT_FLAGS, NULL, ICON_NONE);
+ // uiItemR(layout, ptr, "f_stop", DEFAULT_FLAGS, NULL, ICON_NONE); // UNUSED
+ uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_extended_bounds", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_backdrop_viewer(
@@ -2469,36 +2490,36 @@ static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C)
{
uiLayout *row;
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
- uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "x", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(row, ptr, "y", DEFAULT_FLAGS, NULL, ICON_NONE);
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_composite(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_viewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_viewer_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *col;
- uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "tile_order", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "tile_order", DEFAULT_FLAGS, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "tile_order") == 0) {
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "center_x", 0, NULL, ICON_NONE);
- uiItemR(col, ptr, "center_y", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "center_x", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(col, ptr, "center_y", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
@@ -2507,19 +2528,19 @@ static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *p
bNode *node = ptr->data;
uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL);
- uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_feather", DEFAULT_FLAGS, NULL, ICON_NONE);
- uiItemR(layout, ptr, "size_source", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "size_source", DEFAULT_FLAGS, "", ICON_NONE);
if (node->custom1 & (CMP_NODEFLAG_MASK_FIXED | CMP_NODEFLAG_MASK_FIXED_SCENE)) {
- uiItemR(layout, ptr, "size_x", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "size_y", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "size_x", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "size_y", DEFAULT_FLAGS, NULL, ICON_NONE);
}
- uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, NULL, ICON_NONE);
if (node->custom1 & CMP_NODEFLAG_MASK_MOTION_BLUR) {
- uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
@@ -2545,18 +2566,18 @@ static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), Poi
{
/* bNode *node = ptr->data; */ /* UNUSED */
- uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "screen_balance", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "despill_factor", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "despill_balance", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "edge_kernel_radius", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "edge_kernel_tolerance", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "clip_white", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "dilate_distance", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "feather_falloff", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "feather_distance", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "blur_post", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "blur_pre", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "screen_balance", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "despill_factor", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "despill_balance", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "edge_kernel_radius", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "edge_kernel_tolerance", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "clip_black", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "clip_white", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "dilate_distance", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "feather_falloff", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "feather_distance", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "blur_post", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -2588,13 +2609,13 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA);
}
else {
- uiItemR(layout, ptr, "track_name", 0, "", ICON_ANIM_DATA);
+ uiItemR(layout, ptr, "track_name", DEFAULT_FLAGS, "", ICON_ANIM_DATA);
}
- uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "position", DEFAULT_FLAGS, NULL, ICON_NONE);
if (ELEM(node->custom1, CMP_TRACKPOS_RELATIVE_FRAME, CMP_TRACKPOS_ABSOLUTE_FRAME)) {
- uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "frame_relative", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
}
@@ -2633,10 +2654,10 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P
}
}
- uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, NULL, ICON_NONE);
if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
- uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, NULL, ICON_NONE);
}
}
@@ -2648,8 +2669,8 @@ static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout),
static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "source", UI_ITEM_R_EXPAND, "", ICON_NONE);
- uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "source", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, "", ICON_NONE);
+ uiItemR(layout, ptr, "ray_length", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -2662,7 +2683,7 @@ static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *UNUSED(C)
uiTemplateCryptoPicker(row, ptr, "add");
uiTemplateCryptoPicker(row, ptr, "remove");
- uiItemR(col, ptr, "matte_id", 0, "", ICON_NONE);
+ uiItemR(col, ptr, "matte_id", DEFAULT_FLAGS, "", ICON_NONE);
}
static void node_composit_buts_cryptomatte_ex(uiLayout *layout,
@@ -2677,7 +2698,7 @@ static void node_composit_buts_brightcontrast(uiLayout *layout,
bContext *UNUSED(C),
PointerRNA *ptr)
{
- uiItemR(layout, ptr, "use_premultiply", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_premultiply", DEFAULT_FLAGS, NULL, ICON_NONE);
}
static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -2690,7 +2711,7 @@ static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), Po
}
#endif
- uiItemR(layout, ptr, "use_hdr", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_hdr", DEFAULT_FLAGS, NULL, ICON_NONE);
}
/* only once called */
@@ -2940,12 +2961,12 @@ static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), Poin
uiLayout *col;
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "offset", UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE);
- uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE);
+ uiItemR(col, ptr, "offset", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE);
+ uiItemR(col, ptr, "offset_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE);
col = uiLayoutColumn(layout, true);
- uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE);
- uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE);
+ uiItemR(col, ptr, "squash", DEFAULT_FLAGS, IFACE_("Squash"), ICON_NONE);
+ uiItemR(col, ptr, "squash_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE);
}
static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -2962,68 +2983,73 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe
switch (tex->type) {
case TEX_BLEND:
- uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "progression", DEFAULT_FLAGS, "", ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "use_flip_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, &tex_ptr, "use_flip_axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
break;
case TEX_MARBLE:
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "marble_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, &tex_ptr, "marble_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
+ uiItemR(row, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
break;
case TEX_MAGIC:
- uiItemR(col, &tex_ptr, "noise_depth", 0, NULL, ICON_NONE);
+ uiItemR(col, &tex_ptr, "noise_depth", DEFAULT_FLAGS, NULL, ICON_NONE);
break;
case TEX_STUCCI:
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "stucci_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, &tex_ptr, "stucci_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
+ uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
break;
case TEX_WOOD:
- uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
- uiItemR(col, &tex_ptr, "wood_type", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "wood_type", DEFAULT_FLAGS, "", ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
row = uiLayoutRow(col, false);
uiLayoutSetActive(row, !(ELEM(tex->stype, TEX_BAND, TEX_RING)));
- uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
break;
case TEX_CLOUDS:
- uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "cloud_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(row, &tex_ptr, "cloud_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
row = uiLayoutRow(col, false);
- uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
- uiItemR(col, &tex_ptr, "noise_depth", UI_ITEM_R_EXPAND, IFACE_("Depth"), ICON_NONE);
+ uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(col,
+ &tex_ptr,
+ "noise_depth",
+ DEFAULT_FLAGS | UI_ITEM_R_EXPAND,
+ IFACE_("Depth"),
+ ICON_NONE);
break;
case TEX_DISTNOISE:
- uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
- uiItemR(col, &tex_ptr, "noise_distortion", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "noise_distortion", DEFAULT_FLAGS, "", ICON_NONE);
break;
case TEX_MUSGRAVE:
- uiItemR(col, &tex_ptr, "musgrave_type", 0, "", ICON_NONE);
- uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "musgrave_type", DEFAULT_FLAGS, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
break;
case TEX_VORONOI:
- uiItemR(col, &tex_ptr, "distance_metric", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "distance_metric", DEFAULT_FLAGS, "", ICON_NONE);
if (tex->vn_distm == TEX_MINKOVSKY) {
- uiItemR(col, &tex_ptr, "minkovsky_exponent", 0, NULL, ICON_NONE);
+ uiItemR(col, &tex_ptr, "minkovsky_exponent", DEFAULT_FLAGS, NULL, ICON_NONE);
}
- uiItemR(col, &tex_ptr, "color_mode", 0, "", ICON_NONE);
+ uiItemR(col, &tex_ptr, "color_mode", DEFAULT_FLAGS, "", ICON_NONE);
break;
}
}
@@ -3053,7 +3079,7 @@ static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA
static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE);
}
/* only once called */
@@ -3105,6 +3131,96 @@ static void node_texture_set_butfunc(bNodeType *ntype)
}
}
+/* ****************** BUTTON CALLBACKS FOR SIMULATION NODES ***************** */
+
+static void node_simulation_buts_particle_simulation(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "name", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_simulation_buts_particle_time_step_event(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_simulation_buts_particle_attribute(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_simulation_buts_set_particle_attribute(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_simulation_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_simulation_set_butfunc(bNodeType *ntype)
+{
+ switch (ntype->type) {
+ case SIM_NODE_PARTICLE_SIMULATION:
+ ntype->draw_buttons = node_simulation_buts_particle_simulation;
+ break;
+ case SIM_NODE_PARTICLE_TIME_STEP_EVENT:
+ ntype->draw_buttons = node_simulation_buts_particle_time_step_event;
+ break;
+ case SIM_NODE_PARTICLE_ATTRIBUTE:
+ ntype->draw_buttons = node_simulation_buts_particle_attribute;
+ break;
+ case SIM_NODE_SET_PARTICLE_ATTRIBUTE:
+ ntype->draw_buttons = node_simulation_buts_set_particle_attribute;
+ break;
+ case SIM_NODE_TIME:
+ ntype->draw_buttons = node_simulation_buts_time;
+ break;
+ }
+}
+
+/* ****************** BUTTON CALLBACKS FOR FUNCTION NODES ***************** */
+
+static void node_function_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_function_buts_float_compare(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_function_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_function_set_butfunc(bNodeType *ntype)
+{
+ switch (ntype->type) {
+ case FN_NODE_BOOLEAN_MATH:
+ ntype->draw_buttons = node_function_buts_boolean_math;
+ break;
+ case FN_NODE_FLOAT_COMPARE:
+ ntype->draw_buttons = node_function_buts_float_compare;
+ break;
+ case FN_NODE_SWITCH:
+ ntype->draw_buttons = node_function_buts_switch;
+ break;
+ }
+}
+
/* ****** init draw callbacks for all tree types, only called in usiblender.c, once ************ */
static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -3116,7 +3232,7 @@ static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), Poin
static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocketTemplate *stemp)
{
- StructRNA *srna = ntype->ext.srna;
+ StructRNA *srna = ntype->rna_ext.srna;
PropertyRNA *prop = RNA_struct_type_find_property(srna, stemp->identifier);
if (prop) {
@@ -3213,6 +3329,8 @@ void ED_node_init_butfuncs(void)
node_composit_set_butfunc(ntype);
node_shader_set_butfunc(ntype);
node_texture_set_butfunc(ntype);
+ node_simulation_set_butfunc(ntype);
+ node_function_set_butfunc(ntype);
/* define update callbacks for socket properties */
node_template_properties_update(ntype);
@@ -3223,6 +3341,7 @@ void ED_node_init_butfuncs(void)
ntreeType_Composite->ui_icon = ICON_NODE_COMPOSITING;
ntreeType_Shader->ui_icon = ICON_NODE_MATERIAL;
ntreeType_Texture->ui_icon = ICON_NODE_TEXTURE;
+ ntreeType_Simulation->ui_icon = ICON_PHYSICS; /* TODO: Use correct icon. */
}
void ED_init_custom_node_type(bNodeType *ntype)
@@ -3251,6 +3370,12 @@ static const float std_node_socket_colors[][4] = {
{0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */
{0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */
{0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */
+ {0.40, 0.10, 0.10, 1.0}, /* SOCK_OBJECT */
+ {0.10, 0.40, 0.10, 1.0}, /* SOCK_IMAGE */
+ {0.80, 0.80, 0.20, 1.0}, /* SOCK_EMITTERS */
+ {0.80, 0.20, 0.80, 1.0}, /* SOCK_EVENTS */
+ {0.20, 0.80, 0.80, 1.0}, /* SOCK_FORCES */
+ {0.30, 0.30, 0.30, 1.0}, /* SOCK_CONTROL_FLOW */
};
/* common color callbacks for standard types */
@@ -3345,7 +3470,7 @@ static void std_node_socket_draw(
case SOCK_FLOAT:
case SOCK_INT:
case SOCK_BOOLEAN:
- uiItemR(layout, ptr, "default_value", 0, text, 0);
+ uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
break;
case SOCK_VECTOR:
if (sock->flag & SOCK_COMPACT) {
@@ -3353,11 +3478,11 @@ static void std_node_socket_draw(
}
else {
if (sock->typeinfo->subtype == PROP_DIRECTION) {
- uiItemR(layout, ptr, "default_value", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
}
else {
uiLayout *column = uiLayoutColumn(layout, true);
- uiItemR(column, ptr, "default_value", 0, text, ICON_NONE);
+ uiItemR(column, ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE);
}
}
break;
@@ -3365,7 +3490,15 @@ static void std_node_socket_draw(
case SOCK_STRING: {
uiLayout *row = uiLayoutSplit(layout, 0.5f, false);
uiItemL(row, text, 0);
- uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiItemR(row, ptr, "default_value", DEFAULT_FLAGS, "", 0);
+ break;
+ }
+ case SOCK_OBJECT: {
+ uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
+ break;
+ }
+ case SOCK_IMAGE: {
+ uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
break;
}
default:
@@ -3383,32 +3516,32 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
switch (type) {
case SOCK_FLOAT: {
uiLayout *row;
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
+ uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, NULL, 0);
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0);
- uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
+ uiItemR(row, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), 0);
+ uiItemR(row, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), 0);
break;
}
case SOCK_INT: {
uiLayout *row;
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
+ uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, NULL, 0);
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0);
- uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
+ uiItemR(row, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), 0);
+ uiItemR(row, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), 0);
break;
}
case SOCK_VECTOR: {
uiLayout *row;
- uiItemR(layout, ptr, "default_value", UI_ITEM_R_EXPAND, NULL, 0);
+ uiItemR(layout, ptr, "default_value", UI_ITEM_R_EXPAND, NULL, DEFAULT_FLAGS);
row = uiLayoutRow(layout, true);
- uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0);
- uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
+ uiItemR(row, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), 0);
+ uiItemR(row, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), 0);
break;
}
case SOCK_BOOLEAN:
case SOCK_RGBA:
case SOCK_STRING: {
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
+ uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, NULL, 0);
break;
}
}
@@ -3440,7 +3573,7 @@ void ED_init_node_socket_type_virtual(bNodeSocketType *stype)
/* ************** Generic drawing ************** */
void draw_nodespace_back_pix(const bContext *C,
- ARegion *ar,
+ ARegion *region,
SpaceNode *snode,
bNodeInstanceKey parent_key)
{
@@ -3454,9 +3587,9 @@ void draw_nodespace_back_pix(const bContext *C,
GPU_matrix_push_projection();
GPU_matrix_push();
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
GPU_matrix_identity_set();
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_BACKDROP);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_BACKDROP);
GPU_matrix_pop_projection();
GPU_matrix_pop();
@@ -3468,7 +3601,7 @@ void draw_nodespace_back_pix(const bContext *C,
return;
}
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
float x, y;
@@ -3477,13 +3610,13 @@ void draw_nodespace_back_pix(const bContext *C,
GPU_matrix_push();
/* somehow the offset has to be calculated inverse */
- wmOrtho2_region_pixelspace(ar);
+ wmOrtho2_region_pixelspace(region);
- x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
- y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
+ x = (region->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
+ y = (region->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
if (ibuf->rect || ibuf->rect_float) {
- unsigned char *display_buffer = NULL;
+ uchar *display_buffer = NULL;
void *cache_handle = NULL;
if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) {
@@ -3639,7 +3772,7 @@ static bool node_link_bezier_handles(View2D *v2d,
deltay = vec[3][1] - vec[0][1];
/* check direction later, for top sockets */
if (fromreroute) {
- if (ABS(deltax) > ABS(deltay)) {
+ if (fabsf(deltax) > fabsf(deltay)) {
vec[1][1] = vec[0][1];
vec[1][0] = vec[0][0] + (deltax > 0 ? dist : -dist);
}
@@ -3653,7 +3786,7 @@ static bool node_link_bezier_handles(View2D *v2d,
vec[1][1] = vec[0][1];
}
if (toreroute) {
- if (ABS(deltax) > ABS(deltay)) {
+ if (fabsf(deltax) > fabsf(deltay)) {
vec[2][1] = vec[3][1];
vec[2][0] = vec[3][0] + (deltax > 0 ? -dist : dist);
}
@@ -3707,11 +3840,11 @@ static struct {
GPUBatch *batch; /* for batching line together */
GPUBatch *batch_single; /* for single line */
GPUVertBuf *inst_vbo;
- unsigned int p0_id, p1_id, p2_id, p3_id;
- unsigned int colid_id;
+ uint p0_id, p1_id, p2_id, p3_id;
+ uint colid_id;
GPUVertBufRaw p0_step, p1_step, p2_step, p3_step;
GPUVertBufRaw colid_step;
- unsigned int count;
+ uint count;
bool enabled;
} g_batch_link = {0};
@@ -3727,11 +3860,11 @@ static void nodelink_batch_reset(void)
}
static void set_nodelink_vertex(GPUVertBuf *vbo,
- unsigned int uv_id,
- unsigned int pos_id,
- unsigned int exp_id,
- unsigned int v,
- const unsigned char uv[2],
+ uint uv_id,
+ uint pos_id,
+ uint exp_id,
+ uint v,
+ const uchar uv[2],
const float pos[2],
const float exp[2])
{
@@ -3756,7 +3889,7 @@ static void nodelink_batch_init(void)
int v = 0;
for (int k = 0; k < 2; k++) {
- unsigned char uv[2] = {0, 0};
+ uchar uv[2] = {0, 0};
float pos[2] = {0.0f, 0.0f};
float exp[2] = {0.0f, 1.0f};
@@ -4000,8 +4133,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
// node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
}
-void ED_node_draw_snap(
- View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos)
+void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, uint pos)
{
immBegin(GPU_PRIM_LINES, 4);
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 664349b3c3b..1d73937d762 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -32,7 +32,7 @@
#include "BKE_context.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
@@ -40,8 +40,8 @@
#include "BKE_texture.h"
#include "ED_node.h" /* own include */
-#include "ED_screen.h"
#include "ED_render.h"
+#include "ED_screen.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -215,7 +215,7 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C,
static int add_reroute_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bNodeTree *ntree = snode->edittree;
float mcoords[256][2];
int i = 0;
@@ -226,7 +226,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
RNA_float_get_array(&itemptr, "loc", loc);
UI_view2d_region_to_view(
- &ar->v2d, (short)loc[0], (short)loc[1], &mcoords[i][0], &mcoords[i][1]);
+ &region->v2d, (short)loc[0], (short)loc[1], &mcoords[i][0], &mcoords[i][1]);
i++;
if (i >= 256) {
break;
@@ -368,12 +368,12 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(
- &ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]);
+ &region->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]);
snode->cursor[0] /= UI_DPI_FAC;
snode->cursor[1] /= UI_DPI_FAC;
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index 072a67dee6c..8fc343a9ed4 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -25,8 +25,8 @@
#include "DNA_node_types.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLT_translation.h"
@@ -66,13 +66,13 @@ static bool node_sockets_poll(const bContext *C, PanelType *UNUSED(pt))
return (snode && snode->nodetree && G.debug_value == 777);
}
-static void node_sockets_panel(const bContext *C, Panel *pa)
+static void node_sockets_panel(const bContext *C, Panel *panel)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = (snode) ? snode->edittree : NULL;
bNode *node = (ntree) ? nodeGetActive(ntree) : NULL;
bNodeSocket *sock;
- uiLayout *layout = pa->layout, *split;
+ uiLayout *layout = panel->layout, *split;
char name[UI_MAX_NAME_STR];
if (ELEM(NULL, ntree, node)) {
@@ -84,7 +84,7 @@ static void node_sockets_panel(const bContext *C, Panel *pa)
split = uiLayoutSplit(layout, 0.35f, false);
uiItemL(split, name, ICON_NONE);
- uiTemplateNodeLink(split, ntree, node, sock);
+ uiTemplateNodeLink(split, (bContext *)C, ntree, node, sock);
}
}
@@ -119,13 +119,13 @@ static bool node_tree_find_active_socket(bNodeTree *ntree, bNodeSocket **r_sock,
return false;
}
-static void node_tree_interface_panel(const bContext *C, Panel *pa)
+static void node_tree_interface_panel(const bContext *C, Panel *panel)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = (snode) ? snode->edittree : NULL;
bNodeSocket *sock;
int in_out;
- uiLayout *layout = pa->layout, *row, *split, *col;
+ uiLayout *layout = panel->layout, *row, *split, *col;
PointerRNA ptr, sockptr, opptr;
wmOperatorType *ot;
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 2081c69a1a4..bd8950c5085 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -23,21 +23,21 @@
*/
#include "DNA_light_types.h"
-#include "DNA_node_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
+#include "DNA_node_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
-#include "DNA_linestyle_types.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -47,17 +47,17 @@
#include "BIF_glutil.h"
+#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
-#include "GPU_framebuffer.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_node.h"
#include "ED_gpencil.h"
+#include "ED_node.h"
#include "ED_space_api.h"
#include "UI_resources.h"
@@ -94,23 +94,11 @@ void ED_node_tree_update(const bContext *C)
static bNodeTree *node_tree_from_ID(ID *id)
{
if (id) {
- short idtype = GS(id->name);
-
- switch (idtype) {
- case ID_NT:
- return (bNodeTree *)id;
- case ID_MA:
- return ((Material *)id)->nodetree;
- case ID_LA:
- return ((Light *)id)->nodetree;
- case ID_WO:
- return ((World *)id)->nodetree;
- case ID_SCE:
- return ((Scene *)id)->nodetree;
- case ID_TE:
- return ((Tex *)id)->nodetree;
- case ID_LS:
- return ((FreestyleLineStyle *)id)->nodetree;
+ if (GS(id->name) == ID_NT) {
+ return (bNodeTree *)id;
+ }
+ else {
+ return ntreeFromID(id);
}
}
@@ -396,7 +384,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
NODE_WIDTH(node) - NODE_DY,
NODE_DY,
0,
- UI_style_get());
+ UI_style_get_dpi());
if (node->flag & NODE_MUTED) {
uiLayoutSetActive(layout, false);
@@ -409,8 +397,8 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* align output buttons to the right */
row = uiLayoutRow(layout, 1);
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
-
- nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
+ const char *socket_label = nodeSocketLabel(nsock);
+ nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
UI_block_align_end(node->block);
UI_block_layout_resolve(node->block, NULL, &buty);
@@ -491,7 +479,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
node->butr.xmax,
0,
0,
- UI_style_get());
+ UI_style_get_dpi());
if (node->flag & NODE_MUTED) {
uiLayoutSetActive(layout, false);
@@ -523,7 +511,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
NODE_WIDTH(node) - NODE_DY,
NODE_DY,
0,
- UI_style_get());
+ UI_style_get_dpi());
if (node->flag & NODE_MUTED) {
uiLayoutSetActive(layout, false);
@@ -535,7 +523,8 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
row = uiLayoutRow(layout, 1);
- nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
+ const char *socket_label = nodeSocketLabel(nsock);
+ nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
UI_block_align_end(node->block);
UI_block_layout_resolve(node->block, NULL, &buty);
@@ -718,39 +707,19 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
#define MARKER_SHAPE_CIRCLE 0x2
#define MARKER_SHAPE_INNER_DOT 0x10
-static void node_socket_draw(const bContext *C,
- bNodeTree *ntree,
- PointerRNA node_ptr,
- bNodeSocket *sock,
- unsigned pos_id,
- unsigned col_id,
- unsigned shape_id,
- unsigned size_id,
- unsigned outline_col_id,
+static void node_socket_draw(const bNodeSocket *sock,
+ const float color[4],
+ const float color_outline[4],
float size,
- bool selected)
+ int locx,
+ int locy,
+ uint pos_id,
+ uint col_id,
+ uint shape_id,
+ uint size_id,
+ uint outline_col_id)
{
- PointerRNA ptr;
- float color[4];
- float outline_color[4];
- unsigned int flags = 0;
-
- RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
- sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
-
- bNode *node = node_ptr.data;
- if (node->flag & NODE_MUTED) {
- color[3] *= 0.25f;
- }
-
- if (selected) {
- UI_GetThemeColor4fv(TH_TEXT_HI, outline_color);
- outline_color[3] = 0.9f;
- }
- else {
- copy_v4_fl(outline_color, 0.0f);
- outline_color[3] = 0.6f;
- }
+ int flags;
/* sets shape flags */
switch (sock->display_shape) {
@@ -779,8 +748,120 @@ static void node_socket_draw(const bContext *C,
immAttr4fv(col_id, color);
immAttr1u(shape_id, flags);
immAttr1f(size_id, size);
- immAttr4fv(outline_col_id, outline_color);
- immVertex2f(pos_id, sock->locx, sock->locy);
+ immAttr4fv(outline_col_id, color_outline);
+ immVertex2f(pos_id, locx, locy);
+}
+
+static void node_socket_outline_color_get(bool selected, float r_outline_color[4])
+{
+ if (selected) {
+ UI_GetThemeColor4fv(TH_TEXT_HI, r_outline_color);
+ r_outline_color[3] = 0.9f;
+ }
+ else {
+ copy_v4_fl(r_outline_color, 0.0f);
+ r_outline_color[3] = 0.6f;
+ }
+}
+
+/* Usual convention here would be node_socket_get_color(), but that's already used (for setting a
+ * color property socket). */
+void node_socket_color_get(
+ bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4])
+{
+ PointerRNA ptr;
+
+ BLI_assert(RNA_struct_is_a(node_ptr->type, &RNA_Node));
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+
+ sock->typeinfo->draw_color(C, &ptr, node_ptr, r_color);
+
+ bNode *node = node_ptr->data;
+ if (node->flag & NODE_MUTED) {
+ r_color[3] *= 0.25f;
+ }
+}
+
+static void node_socket_draw_nested(const bContext *C,
+ bNodeTree *ntree,
+ PointerRNA *node_ptr,
+ bNodeSocket *sock,
+ uint pos_id,
+ uint col_id,
+ uint shape_id,
+ uint size_id,
+ uint outline_col_id,
+ float size,
+ bool selected)
+{
+ float color[4];
+ float outline_color[4];
+
+ node_socket_color_get((bContext *)C, ntree, node_ptr, sock, color);
+ node_socket_outline_color_get(selected, outline_color);
+
+ node_socket_draw(sock,
+ color,
+ outline_color,
+ size,
+ sock->locx,
+ sock->locy,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id);
+}
+
+/**
+ * Draw a single node socket at default size.
+ * \note this is only called from external code, internally #node_socket_draw_nested() is used for
+ * optimized drawing of multiple/all sockets of a node.
+ */
+void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale)
+{
+ const float size = 2.25f * NODE_SOCKSIZE * scale;
+ rcti draw_rect = *rect;
+ float outline_color[4] = {0};
+
+ node_socket_outline_color_get(sock->flag & SELECT, outline_color);
+
+ BLI_rcti_resize(&draw_rect, size, size);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint outline_col_id = GPU_vertformat_attr_add(
+ format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+
+ gpuPushAttr(GPU_BLEND_BIT);
+ GPU_blend(true);
+ GPU_program_point_size(true);
+
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ immUniform1f("outline_scale", 0.7f);
+ immUniform2f("ViewportSize", -1.0f, -1.0f);
+
+ /* Single point */
+ immBegin(GPU_PRIM_POINTS, 1);
+ node_socket_draw(sock,
+ color,
+ outline_color,
+ BLI_rcti_size_y(&draw_rect),
+ BLI_rcti_cent_x(&draw_rect),
+ BLI_rcti_cent_y(&draw_rect),
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id);
+ immEnd();
+
+ immUnbindProgram();
+ GPU_program_point_size(false);
+ gpuPopAttr();
}
/* ************** Socket callbacks *********** */
@@ -973,17 +1054,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
- node_socket_draw(C,
- ntree,
- node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
+ node_socket_draw_nested(C,
+ ntree,
+ &node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
}
/* socket outputs */
@@ -998,17 +1079,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
- node_socket_draw(C,
- ntree,
- node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
+ node_socket_draw_nested(C,
+ ntree,
+ &node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
}
}
@@ -1031,17 +1112,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
if (select_all || (sock->flag & SELECT)) {
- node_socket_draw(C,
- ntree,
- node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
+ node_socket_draw_nested(C,
+ ntree,
+ &node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
if (--selected_input_len == 0) {
break; /* stop as soon as last one is drawn */
}
@@ -1056,17 +1137,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
if (select_all || (sock->flag & SELECT)) {
- node_socket_draw(C,
- ntree,
- node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
+ node_socket_draw_nested(C,
+ ntree,
+ &node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
if (--selected_output_len == 0) {
break; /* stop as soon as last one is drawn */
}
@@ -1084,7 +1165,7 @@ void node_draw_sockets(View2D *v2d,
}
static void node_draw_basis(const bContext *C,
- ARegion *ar,
+ ARegion *region,
SpaceNode *snode,
bNodeTree *ntree,
bNode *node,
@@ -1098,7 +1179,7 @@ static void node_draw_basis(const bContext *C,
int color_id = node_get_colorid(node);
float color[4];
char showname[128]; /* 128 used below */
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
/* skip if out of view */
if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) {
@@ -1180,6 +1261,25 @@ static void node_draw_basis(const bContext *C,
UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_group_edit");
UI_block_emboss_set(node->block, UI_EMBOSS);
}
+ if (node->type == NODE_CUSTOM && node->typeinfo->ui_icon != ICON_NONE) {
+ iconofs -= iconbutw;
+ UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
+ uiDefIconBut(node->block,
+ UI_BTYPE_BUT,
+ 0,
+ node->typeinfo->ui_icon,
+ iconofs,
+ rct->ymax - NODE_DY,
+ iconbutw,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_block_emboss_set(node->block, UI_EMBOSS);
+ }
/* title */
if (node->flag & SELECT) {
@@ -1295,7 +1395,7 @@ static void node_draw_basis(const bContext *C,
}
static void node_draw_hidden(const bContext *C,
- ARegion *ar,
+ ARegion *region,
SpaceNode *snode,
bNodeTree *ntree,
bNode *node,
@@ -1307,7 +1407,7 @@ static void node_draw_hidden(const bContext *C,
int color_id = node_get_colorid(node);
float color[4];
char showname[128]; /* 128 is used below */
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
float scale;
UI_view2d_scale_get(v2d, &scale, NULL);
@@ -1340,14 +1440,14 @@ static void node_draw_hidden(const bContext *C,
GPU_blend(true);
GPU_line_smooth(true);
- UI_draw_roundbox_3fvAlpha(false,
- rct->xmin + 1,
- rct->ymin + 1,
- rct->xmax - 1,
- rct->ymax - 1,
- hiddenrad,
- node->color,
- 1.0f);
+ UI_draw_roundbox_3fv_alpha(false,
+ rct->xmin + 1,
+ rct->ymin + 1,
+ rct->xmax - 1,
+ rct->ymax - 1,
+ hiddenrad,
+ node->color,
+ 1.0f);
GPU_line_smooth(false);
GPU_blend(false);
@@ -1391,7 +1491,7 @@ static void node_draw_hidden(const bContext *C,
/* disable lines */
if (node->flag & NODE_MUTED) {
- node_draw_mute_line(&ar->v2d, snode, node);
+ node_draw_mute_line(&region->v2d, snode, node);
}
nodeLabel(ntree, node, showname, sizeof(showname));
@@ -1498,17 +1598,17 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
}
void node_draw_default(const bContext *C,
- ARegion *ar,
+ ARegion *region,
SpaceNode *snode,
bNodeTree *ntree,
bNode *node,
bNodeInstanceKey key)
{
if (node->flag & NODE_HIDDEN) {
- node_draw_hidden(C, ar, snode, ntree, node, key);
+ node_draw_hidden(C, region, snode, ntree, node, key);
}
else {
- node_draw_basis(C, ar, snode, ntree, node, key);
+ node_draw_basis(C, region, snode, ntree, node, key);
}
}
@@ -1533,21 +1633,21 @@ void node_update_nodetree(const bContext *C, bNodeTree *ntree)
}
static void node_draw(const bContext *C,
- ARegion *ar,
+ ARegion *region,
SpaceNode *snode,
bNodeTree *ntree,
bNode *node,
bNodeInstanceKey key)
{
if (node->typeinfo->draw_nodetype) {
- node->typeinfo->draw_nodetype(C, ar, snode, ntree, node, key);
+ node->typeinfo->draw_nodetype(C, region, snode, ntree, node, key);
}
}
#define USE_DRAW_TOT_UPDATE
void node_draw_nodetree(const bContext *C,
- ARegion *ar,
+ ARegion *region,
SpaceNode *snode,
bNodeTree *ntree,
bNodeInstanceKey parent_key)
@@ -1562,7 +1662,7 @@ void node_draw_nodetree(const bContext *C,
#ifdef USE_DRAW_TOT_UPDATE
if (ntree->nodes.first) {
- BLI_rctf_init_minmax(&ar->v2d.tot);
+ BLI_rctf_init_minmax(&region->v2d.tot);
}
#endif
@@ -1573,7 +1673,7 @@ void node_draw_nodetree(const bContext *C,
#ifdef USE_DRAW_TOT_UPDATE
/* unrelated to background nodes, update the v2d->tot,
* can be anywhere before we draw the scroll bars */
- BLI_rctf_union(&ar->v2d.tot, &node->totr);
+ BLI_rctf_union(&region->v2d.tot, &node->totr);
#endif
if (!(node->flag & NODE_BACKGROUND)) {
@@ -1582,7 +1682,7 @@ void node_draw_nodetree(const bContext *C,
key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
- node_draw(C, ar, snode, ntree, node, key);
+ node_draw(C, region, snode, ntree, node, key);
}
/* node lines */
@@ -1590,7 +1690,7 @@ void node_draw_nodetree(const bContext *C,
nodelink_batch_start(snode);
for (link = ntree->links.first; link; link = link->next) {
if (!nodeLinkIsHidden(link)) {
- node_draw_link(&ar->v2d, snode, link);
+ node_draw_link(&region->v2d, snode, link);
}
}
nodelink_batch_end(snode);
@@ -1605,7 +1705,7 @@ void node_draw_nodetree(const bContext *C,
key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
- node_draw(C, ar, snode, ntree, node, key);
+ node_draw(C, region, snode, ntree, node, key);
}
}
@@ -1620,21 +1720,21 @@ static void draw_tree_path(SpaceNode *snode)
BLF_draw_default(1.5f * UI_UNIT_X, 1.5f * UI_UNIT_Y, 0.0f, info, sizeof(info));
}
-static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, const float center[2])
+static void snode_setup_v2d(SpaceNode *snode, ARegion *region, const float center[2])
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
/* shift view to node tree center */
UI_view2d_center_set(v2d, center[0], center[1]);
UI_view2d_view_ortho(v2d);
/* aspect+font, set each time */
- snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
+ snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)region->winx;
// XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
}
static void draw_nodetree(const bContext *C,
- ARegion *ar,
+ ARegion *region,
bNodeTree *ntree,
bNodeInstanceKey parent_key)
{
@@ -1643,13 +1743,13 @@ static void draw_nodetree(const bContext *C,
node_uiblocks_init(C, ntree);
node_update_nodetree(C, ntree);
- node_draw_nodetree(C, ar, snode, ntree, parent_key);
+ node_draw_nodetree(C, region, snode, ntree, parent_key);
}
/* shade the parent node group and add a uiBlock to clip mouse events */
-static void draw_group_overlay(const bContext *C, ARegion *ar)
+static void draw_group_overlay(const bContext *C, ARegion *region)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
rctf rect = v2d->cur;
uiBlock *block;
float color[4];
@@ -1663,18 +1763,18 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
GPU_blend(false);
/* set the block bounds to clip mouse events from underlying nodes */
- block = UI_block_begin(C, ar, "node tree bounds block", UI_EMBOSS);
+ block = UI_block_begin(C, region, "node tree bounds block", UI_EMBOSS);
UI_block_bounds_set_explicit(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
UI_block_flag_enable(block, UI_BLOCK_CLIP_EVENTS);
UI_block_end(C, block);
}
-void drawnodespace(const bContext *C, ARegion *ar)
+void drawnodespace(const bContext *C, ARegion *region)
{
wmWindow *win = CTX_wm_window(C);
View2DScrollers *scrollers;
SpaceNode *snode = CTX_wm_space_node(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
UI_ThemeClearColor(TH_BACK);
GPU_clear(GPU_COLOR_BIT);
@@ -1682,15 +1782,17 @@ void drawnodespace(const bContext *C, ARegion *ar)
UI_view2d_view_ortho(v2d);
/* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */
- UI_view2d_region_to_view(&ar->v2d,
- win->eventstate->x - ar->winrct.xmin,
- win->eventstate->y - ar->winrct.ymin,
+ UI_view2d_region_to_view(&region->v2d,
+ win->eventstate->x - region->winrct.xmin,
+ win->eventstate->y - region->winrct.ymin,
&snode->cursor[0],
&snode->cursor[1]);
snode->cursor[0] /= UI_DPI_FAC;
snode->cursor[1] /= UI_DPI_FAC;
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ int grid_levels = UI_GetThemeValueType(TH_NODE_GRID_LEVELS, SPACE_NODE);
+
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
/* only set once */
GPU_blend_set_func_separate(
@@ -1738,25 +1840,28 @@ void drawnodespace(const bContext *C, ARegion *ar)
for (curdepth = depth; curdepth > 0; path = path->next, curdepth--) {
ntree = path->nodetree;
if (ntree) {
- snode_setup_v2d(snode, ar, path->view_center);
+ snode_setup_v2d(snode, region, path->view_center);
- draw_nodetree(C, ar, ntree, path->parent_key);
+ draw_nodetree(C, region, ntree, path->parent_key);
- draw_group_overlay(C, ar);
+ draw_group_overlay(C, region);
}
}
/* top-level edit tree */
ntree = path->nodetree;
if (ntree) {
- snode_setup_v2d(snode, ar, center);
+ snode_setup_v2d(snode, region, center);
/* grid, uses theme color based on node path depth */
- UI_view2d_multi_grid_draw(
- v2d, (depth > 0 ? TH_NODE_GROUP : TH_BACK), ED_node_grid_size(), NODE_GRID_STEPS, 2);
+ UI_view2d_multi_grid_draw(v2d,
+ (depth > 0 ? TH_NODE_GROUP : TH_BACK),
+ ED_node_grid_size(),
+ NODE_GRID_STEPS,
+ grid_levels);
/* backdrop */
- draw_nodespace_back_pix(C, ar, snode, path->parent_key);
+ draw_nodespace_back_pix(C, region, snode, path->parent_key);
{
float original_proj[4][4];
@@ -1765,15 +1870,15 @@ void drawnodespace(const bContext *C, ARegion *ar)
GPU_matrix_push();
GPU_matrix_identity_set();
- wmOrtho2_pixelspace(ar->winx, ar->winy);
+ wmOrtho2_pixelspace(region->winx, region->winy);
- WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
+ WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
GPU_matrix_pop();
GPU_matrix_projection_set(original_proj);
}
- draw_nodetree(C, ar, ntree, path->parent_key);
+ draw_nodetree(C, region, ntree, path->parent_key);
}
/* temporary links */
@@ -1794,13 +1899,13 @@ void drawnodespace(const bContext *C, ARegion *ar)
}
else {
/* default grid */
- UI_view2d_multi_grid_draw(v2d, TH_BACK, ED_node_grid_size(), NODE_GRID_STEPS, 2);
+ UI_view2d_multi_grid_draw(v2d, TH_BACK, ED_node_grid_size(), NODE_GRID_STEPS, grid_levels);
/* backdrop */
- draw_nodespace_back_pix(C, ar, snode, NODE_INSTANCE_KEY_NONE);
+ draw_nodespace_back_pix(C, region, snode, NODE_INSTANCE_KEY_NONE);
}
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
/* reset view matrix */
UI_view2d_view_restore(C);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 9623d89e030..bd5ce135f82 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -29,14 +29,15 @@
#include "DNA_text_types.h"
#include "DNA_world_types.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -49,9 +50,9 @@
#include "RE_pipeline.h"
#include "ED_node.h" /* own include */
-#include "ED_select_utils.h"
-#include "ED_screen.h"
#include "ED_render.h"
+#include "ED_screen.h"
+#include "ED_select_utils.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -66,10 +67,11 @@
#include "IMB_imbuf_types.h"
-#include "node_intern.h" /* own include */
#include "NOD_composite.h"
#include "NOD_shader.h"
+#include "NOD_simulation.h"
#include "NOD_texture.h"
+#include "node_intern.h" /* own include */
#define USE_ESC_COMPO
@@ -126,12 +128,12 @@ static int compo_get_recalc_flags(const bContext *C)
int recalc_flags = 0;
for (win = wm->windows.first; win; win = win->next) {
- const bScreen *sc = WM_window_get_active_screen(win);
- ScrArea *sa;
+ const bScreen *screen = WM_window_get_active_screen(win);
+ ScrArea *area;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
+ for (area = screen->areabase.first; area; area = area->next) {
+ if (area->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = area->spacedata.first;
if (sima->image) {
if (sima->image->type == IMA_TYPE_R_RESULT) {
recalc_flags |= COM_RECALC_COMPOSITE;
@@ -141,8 +143,8 @@ static int compo_get_recalc_flags(const bContext *C)
}
}
}
- else if (sa->spacetype == SPACE_NODE) {
- SpaceNode *snode = sa->spacedata.first;
+ else if (area->spacetype == SPACE_NODE) {
+ SpaceNode *snode = area->spacedata.first;
if (snode->flag & SNODE_BACKDRAW) {
recalc_flags |= COM_RECALC_VIEWER;
}
@@ -319,7 +321,7 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene
#endif
BKE_image_backup_render(
- scene, BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"), false);
+ scene, BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"), false);
wm_job = WM_jobs_get(CTX_wm_manager(C),
CTX_wm_window(C),
@@ -437,85 +439,77 @@ bool ED_node_is_texture(struct SpaceNode *snode)
return STREQ(snode->tree_idname, ntreeType_Texture->idname);
}
+bool ED_node_is_simulation(struct SpaceNode *snode)
+{
+ return STREQ(snode->tree_idname, ntreeType_Simulation->idname);
+}
+
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
void ED_node_shader_default(const bContext *C, ID *id)
{
- bNode *in, *out;
- bNodeSocket *fromsock, *tosock, *sock;
- bNodeTree *ntree;
- int output_type, shader_type;
- float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}, strength = 1.0f;
-
- ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
-
- switch (GS(id->name)) {
- case ID_MA: {
- Material *ma = (Material *)id;
- ma->nodetree = ntree;
+ Main *bmain = CTX_data_main(C);
- output_type = SH_NODE_OUTPUT_MATERIAL;
- shader_type = SH_NODE_BSDF_PRINCIPLED;
+ if (GS(id->name) == ID_MA) {
+ /* Materials */
+ Object *ob = CTX_data_active_object(C);
+ Material *ma = (Material *)id;
+ Material *ma_default;
- copy_v3_v3(color, &ma->r);
- strength = 0.0f;
- break;
+ if (ob && ob->type == OB_VOLUME) {
+ ma_default = BKE_material_default_volume();
}
- case ID_WO: {
- World *wo = (World *)id;
- wo->nodetree = ntree;
-
- output_type = SH_NODE_OUTPUT_WORLD;
- shader_type = SH_NODE_BACKGROUND;
-
- copy_v3_v3(color, &wo->horr);
- strength = 1.0f;
- break;
+ else {
+ ma_default = BKE_material_default_surface();
}
- case ID_LA: {
- Light *la = (Light *)id;
- la->nodetree = ntree;
- output_type = SH_NODE_OUTPUT_LIGHT;
- shader_type = SH_NODE_EMISSION;
-
- copy_v3_fl3(color, 1.0f, 1.0f, 1.0f);
- strength = 1.0f;
- break;
- }
- default:
- printf("ED_node_shader_default called on wrong ID type.\n");
- return;
+ ma->nodetree = ntreeCopyTree(bmain, ma_default->nodetree);
+ ntreeUpdateTree(bmain, ma->nodetree);
}
+ else if (ELEM(GS(id->name), ID_WO, ID_LA)) {
+ /* Emission */
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ bNode *shader, *output;
- out = nodeAddStaticNode(C, ntree, output_type);
- out->locx = 300.0f;
- out->locy = 300.0f;
+ if (GS(id->name) == ID_WO) {
+ World *world = (World *)id;
+ world->nodetree = ntree;
- in = nodeAddStaticNode(C, ntree, shader_type);
- in->locx = 10.0f;
- in->locy = 300.0f;
- nodeSetActive(ntree, in);
+ shader = nodeAddStaticNode(NULL, ntree, SH_NODE_BACKGROUND);
+ output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_WORLD);
+ nodeAddLink(ntree,
+ shader,
+ nodeFindSocket(shader, SOCK_OUT, "Background"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
- /* only a link from color to color */
- fromsock = in->outputs.first;
- tosock = out->inputs.first;
- nodeAddLink(ntree, in, fromsock, out, tosock);
-
- /* default values */
- PointerRNA sockptr;
- sock = in->inputs.first;
- RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
+ bNodeSocket *color_sock = nodeFindSocket(shader, SOCK_IN, "Color");
+ copy_v3_v3(((bNodeSocketValueRGBA *)color_sock->default_value)->value, &world->horr);
+ }
+ else {
+ Light *light = (Light *)id;
+ light->nodetree = ntree;
- RNA_float_set_array(&sockptr, "default_value", color);
+ shader = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION);
+ output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_LIGHT);
+ nodeAddLink(ntree,
+ shader,
+ nodeFindSocket(shader, SOCK_OUT, "Emission"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+ }
- if (strength != 0.0f) {
- sock = in->inputs.last;
- RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
- RNA_float_set(&sockptr, "default_value", strength);
+ shader->locx = 10.0f;
+ shader->locy = 300.0f;
+ output->locx = 300.0f;
+ output->locy = 300.0f;
+ nodeSetActive(ntree, output);
+ ntreeUpdateTree(bmain, ntree);
+ }
+ else {
+ printf("ED_node_shader_default called on wrong ID type.\n");
+ return;
}
-
- ntreeUpdateTree(CTX_data_main(C), ntree);
}
/* assumes nothing being done in ntree yet, sets the default in/out node */
@@ -748,7 +742,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
}
/* addnode() doesn't link this yet... */
- node->id = (ID *)BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ node->id = (ID *)BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
}
else if (node->type == CMP_NODE_COMPOSITE) {
if (was_output == 0) {
@@ -831,7 +825,7 @@ static int edit_node_invoke_properties(bContext *C, wmOperator *op)
}
static void edit_node_properties_get(
- wmOperator *op, bNodeTree *ntree, bNode **rnode, bNodeSocket **rsock, int *rin_out)
+ wmOperator *op, bNodeTree *ntree, bNode **r_node, bNodeSocket **r_sock, int *r_in_out)
{
bNode *node;
bNodeSocket *sock = NULL;
@@ -854,14 +848,14 @@ static void edit_node_properties_get(
break;
}
- if (rnode) {
- *rnode = node;
+ if (r_node) {
+ *r_node = node;
}
- if (rsock) {
- *rsock = sock;
+ if (r_sock) {
+ *r_sock = sock;
}
- if (rin_out) {
- *rin_out = in_out;
+ if (r_in_out) {
+ *r_in_out = in_out;
}
}
#endif
@@ -916,10 +910,24 @@ static void node_resize_init(
WM_event_add_modal_handler(C, op);
}
-static void node_resize_exit(bContext *C, wmOperator *op, bool UNUSED(cancel))
+static void node_resize_exit(bContext *C, wmOperator *op, bool cancel)
{
WM_cursor_modal_restore(CTX_wm_window(C));
+ /* Restore old data on cancel. */
+ if (cancel) {
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+ NodeSizeWidget *nsw = op->customdata;
+
+ node->locx = nsw->oldlocx;
+ node->locy = nsw->oldlocy;
+ node->offsetx = nsw->oldoffsetx;
+ node->offsety = nsw->oldoffsety;
+ node->width = nsw->oldwidth;
+ node->height = nsw->oldheight;
+ }
+
MEM_freeN(op->customdata);
op->customdata = NULL;
}
@@ -927,7 +935,7 @@ static void node_resize_exit(bContext *C, wmOperator *op, bool UNUSED(cancel))
static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bNode *node = nodeGetActive(snode->edittree);
NodeSizeWidget *nsw = op->customdata;
float mx, my, dx, dy;
@@ -935,7 +943,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case MOUSEMOVE:
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &mx, &my);
dx = (mx - nsw->mxstart) / UI_DPI_FAC;
dy = (my - nsw->mystart) / UI_DPI_FAC;
@@ -1001,7 +1009,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
@@ -1014,6 +1022,12 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
+ else if (event->val == KM_PRESS) {
+ node_resize_exit(C, op, true);
+ ED_region_tag_redraw(region);
+
+ return OPERATOR_CANCELLED;
+ }
break;
}
@@ -1023,7 +1037,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bNode *node = nodeGetActive(snode->edittree);
int dir;
@@ -1031,7 +1045,7 @@ static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
float cursor[2];
/* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]);
if (dir != 0) {
node_resize_init(C, op, event, node, dir);
@@ -1318,7 +1332,7 @@ void NODE_OT_duplicate(wmOperatorType *ot)
bool ED_node_select_check(ListBase *lb)
{
- for (bNode *node = lb->first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, lb) {
if (node->flag & NODE_SELECT) {
return true;
}
@@ -1338,7 +1352,7 @@ void ED_node_select_all(ListBase *lb, int action)
}
}
- for (bNode *node = lb->first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, lb) {
switch (action) {
case SEL_SELECT:
nodeSetSelected(node, true);
@@ -2451,7 +2465,7 @@ void NODE_OT_tree_socket_move(wmOperatorType *ot)
static bool node_shader_script_update_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- RenderEngineType *type = RE_engines_find(scene->r.engine);
+ const RenderEngineType *type = RE_engines_find(scene->r.engine);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
Text *text;
@@ -2599,7 +2613,7 @@ void NODE_OT_shader_script_update(wmOperatorType *ot)
/* ********************** Viewer border ******************/
static void viewer_border_corner_to_backdrop(SpaceNode *snode,
- ARegion *ar,
+ ARegion *region,
int x,
int y,
int backdrop_width,
@@ -2612,8 +2626,8 @@ static void viewer_border_corner_to_backdrop(SpaceNode *snode,
bufx = backdrop_width * snode->zoom;
bufy = backdrop_height * snode->zoom;
- *fx = (bufx > 0.0f ? ((float)x - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
- *fy = (bufy > 0.0f ? ((float)y - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
+ *fx = (bufx > 0.0f ? ((float)x - 0.5f * region->winx - snode->xof) / bufx + 0.5f : 0.0f);
+ *fy = (bufy > 0.0f ? ((float)y - 0.5f * region->winy - snode->yof) / bufy + 0.5f : 0.0f);
}
static int viewer_border_exec(bContext *C, wmOperator *op)
@@ -2625,11 +2639,11 @@ static int viewer_border_exec(bContext *C, wmOperator *op)
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *btree = snode->nodetree;
rcti rect;
@@ -2640,10 +2654,10 @@ static int viewer_border_exec(bContext *C, wmOperator *op)
/* convert border to unified space within backdrop image */
viewer_border_corner_to_backdrop(
- snode, ar, rect.xmin, rect.ymin, ibuf->x, ibuf->y, &rectf.xmin, &rectf.ymin);
+ snode, region, rect.xmin, rect.ymin, ibuf->x, ibuf->y, &rectf.xmin, &rectf.ymin);
viewer_border_corner_to_backdrop(
- snode, ar, rect.xmax, rect.ymax, ibuf->x, ibuf->y, &rectf.xmax, &rectf.ymax);
+ snode, region, rect.xmax, rect.ymax, ibuf->x, ibuf->y, &rectf.xmax, &rectf.ymax);
/* clamp coordinates */
rectf.xmin = max_ff(rectf.xmin, 0.0f);
diff --git a/source/blender/editors/space_node/node_gizmo.c b/source/blender/editors/space_node/node_gizmo.c
index 76e8b5ca7df..28d7e1b8d04 100644
--- a/source/blender/editors/space_node/node_gizmo.c
+++ b/source/blender/editors/space_node/node_gizmo.c
@@ -20,17 +20,17 @@
#include <math.h>
-#include "BLI_utildefines.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_rect.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_image.h"
#include "BKE_main.h"
-#include "ED_screen.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
#include "IMB_imbuf_types.h"
@@ -48,26 +48,26 @@
* \{ */
static void node_gizmo_calc_matrix_space(const SpaceNode *snode,
- const ARegion *ar,
+ const ARegion *region,
float matrix_space[4][4])
{
unit_m4(matrix_space);
mul_v3_fl(matrix_space[0], snode->zoom);
mul_v3_fl(matrix_space[1], snode->zoom);
- matrix_space[3][0] = (ar->winx / 2) + snode->xof;
- matrix_space[3][1] = (ar->winy / 2) + snode->yof;
+ matrix_space[3][0] = (region->winx / 2) + snode->xof;
+ matrix_space[3][1] = (region->winy / 2) + snode->yof;
}
static void node_gizmo_calc_matrix_space_with_image_dims(const SpaceNode *snode,
- const ARegion *ar,
+ const ARegion *region,
const float image_dims[2],
float matrix_space[4][4])
{
unit_m4(matrix_space);
mul_v3_fl(matrix_space[0], snode->zoom * image_dims[0]);
mul_v3_fl(matrix_space[1], snode->zoom * image_dims[1]);
- matrix_space[3][0] = ((ar->winx / 2) + snode->xof) - ((image_dims[0] / 2.0f) * snode->zoom);
- matrix_space[3][1] = ((ar->winy / 2) + snode->yof) - ((image_dims[1] / 2.0f) * snode->zoom);
+ matrix_space[3][0] = ((region->winx / 2) + snode->xof) - ((image_dims[0] / 2.0f) * snode->zoom);
+ matrix_space[3][1] = ((region->winy / 2) + snode->yof) - ((image_dims[1] / 2.0f) * snode->zoom);
}
/** \} */
@@ -138,12 +138,12 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *
{
Main *bmain = CTX_data_main(C);
wmGizmo *cage = ((wmGizmoWrapper *)gzgroup->customdata)->gizmo;
- const ARegion *ar = CTX_wm_region(C);
+ const ARegion *region = CTX_wm_region(C);
/* center is always at the origin */
- const float origin[3] = {ar->winx / 2, ar->winy / 2};
+ const float origin[3] = {region->winx / 2, region->winy / 2};
void *lock;
- Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
@@ -352,12 +352,12 @@ static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup
static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
wmGizmo *gz = gzgroup->gizmos.first;
SpaceNode *snode = CTX_wm_space_node(C);
- node_gizmo_calc_matrix_space(snode, ar, gz->matrix_space);
+ node_gizmo_calc_matrix_space(snode, region, gz->matrix_space);
}
static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *gzgroup)
@@ -367,7 +367,7 @@ static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *gzgro
wmGizmo *gz = crop_group->border;
void *lock;
- Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
@@ -459,7 +459,7 @@ static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
- gz->scale_basis = 0.05f;
+ gz->scale_basis = 0.05f / 75.0f;
gzgroup->customdata = sbeam_group;
}
@@ -467,13 +467,13 @@ static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup
static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
wmGizmo *gz = gzgroup->gizmos.first;
SpaceNode *snode = CTX_wm_space_node(C);
node_gizmo_calc_matrix_space_with_image_dims(
- snode, ar, sbeam_group->state.dims, gz->matrix_space);
+ snode, region, sbeam_group->state.dims, gz->matrix_space);
}
static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgroup)
@@ -483,7 +483,7 @@ static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgr
wmGizmo *gz = sbeam_group->gizmo;
void *lock;
- Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
@@ -566,7 +566,7 @@ static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmo
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
- gz->scale_basis = 0.01f;
+ gz->scale_basis = 0.01f / 75.0;
}
gzgroup->customdata = cpin_group;
@@ -575,12 +575,13 @@ static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmo
static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
float matrix_space[4][4];
- node_gizmo_calc_matrix_space_with_image_dims(snode, ar, cpin_group->state.dims, matrix_space);
+ node_gizmo_calc_matrix_space_with_image_dims(
+ snode, region, cpin_group->state.dims, matrix_space);
for (int i = 0; i < 4; i++) {
wmGizmo *gz = cpin_group->gizmos[i];
@@ -594,7 +595,7 @@ static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup
struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
void *lock;
- Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 5d020ff5ab4..2617384d046 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -25,11 +25,11 @@
#include "MEM_guardedalloc.h"
-#include "DNA_node_types.h"
#include "DNA_anim_types.h"
+#include "DNA_node_types.h"
-#include "BLI_listbase.h"
#include "BLI_linklist.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLT_translation.h"
@@ -37,15 +37,15 @@
#include "BKE_action.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "DEG_depsgraph_build.h"
#include "ED_node.h" /* own include */
-#include "ED_screen.h"
#include "ED_render.h"
+#include "ED_screen.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -55,8 +55,8 @@
#include "UI_resources.h"
-#include "node_intern.h" /* own include */
#include "NOD_common.h"
+#include "node_intern.h" /* own include */
static bool node_group_operator_active(bContext *C)
{
@@ -69,7 +69,8 @@ static bool node_group_operator_active(bContext *C)
*/
if (STREQ(snode->tree_idname, "ShaderNodeTree") ||
STREQ(snode->tree_idname, "CompositorNodeTree") ||
- STREQ(snode->tree_idname, "TextureNodeTree")) {
+ STREQ(snode->tree_idname, "TextureNodeTree") ||
+ STREQ(snode->tree_idname, "SimulationNodeTree")) {
return true;
}
}
@@ -85,7 +86,8 @@ static bool node_group_operator_editable(bContext *C)
* Disabled otherwise to allow pynodes define their own operators
* with same keymap.
*/
- if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode)) {
+ if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode) ||
+ ED_node_is_simulation(snode)) {
return true;
}
}
@@ -111,6 +113,9 @@ static const char *group_node_idname(bContext *C)
else if (ED_node_is_texture(snode)) {
return "TextureNodeGroup";
}
+ else if (ED_node_is_simulation(snode)) {
+ return "SimulationNodeGroup";
+ }
return "";
}
@@ -193,11 +198,11 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
}
/* wgroup is a temporary copy of the NodeTree we're merging in
- * - all of wgroup's nodes are transferred across to their new home
+ * - all of wgroup's nodes are copied across to their new home
* - ngroup (i.e. the source NodeTree) is left unscathed
- * - temp copy. don't change ID usercount
+ * - temp copy. do change ID usercount for the copies
*/
- wgroup = ntreeCopyTree_ex_new_pointers(ngroup, bmain, false);
+ wgroup = ntreeCopyTree_ex_new_pointers(ngroup, bmain, true);
/* Add the nodes into the ntree */
for (node = wgroup->nodes.first; node; node = nextnode) {
@@ -351,8 +356,8 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
nodeRemoveNode(bmain, ntree, node, false);
}
- /* delete the group instance */
- nodeRemoveNode(bmain, ntree, gnode, false);
+ /* delete the group instance and dereference group tree */
+ nodeRemoveNode(bmain, ntree, gnode, true);
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 1825396805c..04186c3a727 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -24,9 +24,9 @@
#ifndef __NODE_INTERN_H__
#define __NODE_INTERN_H__
-#include <stddef.h> /* for size_t */
#include "BKE_node.h"
#include "UI_interface.h"
+#include <stddef.h> /* for size_t */
/* internal exports only */
@@ -38,6 +38,7 @@ struct bContext;
struct bNode;
struct bNodeLink;
struct bNodeSocket;
+struct wmGizmoGroupType;
struct wmKeyConfig;
struct wmWindow;
@@ -63,7 +64,7 @@ int node_get_colorid(struct bNode *node);
int node_get_resize_cursor(int directions);
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha);
void node_draw_default(const struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
struct SpaceNode *snode,
struct bNodeTree *ntree,
struct bNode *node,
@@ -77,13 +78,18 @@ void node_draw_sockets(struct View2D *v2d,
void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
int node_select_area_default(struct bNode *node, int x, int y);
int node_tweak_area_default(struct bNode *node, int x, int y);
+void node_socket_color_get(struct bContext *C,
+ struct bNodeTree *ntree,
+ struct PointerRNA *node_ptr,
+ struct bNodeSocket *sock,
+ float r_color[4]);
void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree);
void node_draw_nodetree(const struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
struct SpaceNode *snode,
struct bNodeTree *ntree,
bNodeInstanceKey parent_key);
-void drawnodespace(const bContext *C, ARegion *ar);
+void drawnodespace(const bContext *C, ARegion *region);
void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]);
/* DPI scaled coords */
@@ -122,8 +128,8 @@ void NODE_OT_find_node(struct wmOperatorType *ot);
/* node_view.c */
int space_node_view_flag(struct bContext *C,
- SpaceNode *snode,
- ARegion *ar,
+ struct SpaceNode *snode,
+ ARegion *region,
const int node_flag,
const int smooth_viewtx);
@@ -162,7 +168,7 @@ void node_draw_link_straight(View2D *v2d,
int th_col3);
#endif
void draw_nodespace_back_pix(const struct bContext *C,
- struct ARegion *ar,
+ struct ARegion *region,
struct SpaceNode *snode,
bNodeInstanceKey parent_key);
@@ -196,7 +202,7 @@ void NODE_OT_detach(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot);
-void NODE_OT_insert_offset(wmOperatorType *ot);
+void NODE_OT_insert_offset(struct wmOperatorType *ot);
/* node_edit.c */
void snode_notify(struct bContext *C, struct SpaceNode *snode);
@@ -207,8 +213,8 @@ void snode_update(struct SpaceNode *snode, struct bNode *node);
bool composite_node_active(struct bContext *C);
bool composite_node_editable(struct bContext *C);
-int node_has_hidden_sockets(bNode *node);
-void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set);
+int node_has_hidden_sockets(struct bNode *node);
+void node_set_hidden_sockets(struct SpaceNode *snode, bNode *node, int set);
int node_render_changed_exec(bContext *, struct wmOperator *);
int node_find_indicated_socket(struct SpaceNode *snode,
struct bNode **nodep,
@@ -271,7 +277,7 @@ extern const char *node_context_dir[];
#define NODE_SOCKDY (0.08f * U.widget_unit)
#define NODE_WIDTH(node) (node->width * UI_DPI_FAC)
#define NODE_HEIGHT(node) (node->height * UI_DPI_FAC)
-#define NODE_MARGIN_X (0.75f * U.widget_unit)
+#define NODE_MARGIN_X (0.95f * U.widget_unit)
#define NODE_SOCKSIZE (0.25f * U.widget_unit)
#define NODE_RESIZE_MARGIN (0.20f * U.widget_unit)
#define NODE_LINK_RESOL 12
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 357ef31c51f..144e3bd3506 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -26,19 +26,19 @@
#include "DNA_anim_types.h"
#include "DNA_node_types.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_easing.h"
+#include "BLI_math.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "ED_node.h" /* own include */
-#include "ED_screen.h"
#include "ED_render.h"
+#include "ED_screen.h"
#include "ED_util.h"
#include "RNA_access.h"
@@ -47,8 +47,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_view2d.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "BLT_translation.h"
@@ -466,7 +466,7 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
if (tonode) {
/* Find a selected socket that overrides the socket to connect to */
- for (bNodeSocket *sock2 = tonode->outputs.first; sock2; sock2 = sock2->next) {
+ LISTBASE_FOREACH (bNodeSocket *, sock2, &tonode->outputs) {
if (!nodeSocketIsHidden(sock2) && sock2->flag & SELECT) {
sock = sock2;
break;
@@ -588,6 +588,8 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link)
bNodeLink *tlink, *tlink_next;
int to_count = node_count_links(ntree, to);
int from_count = node_count_links(ntree, from);
+ int to_link_limit = nodeSocketLinkLimit(to);
+ int from_link_limit = nodeSocketLinkLimit(from);
for (tlink = ntree->links.first; tlink; tlink = tlink_next) {
tlink_next = tlink->next;
@@ -596,7 +598,7 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link)
}
if (tlink && tlink->fromsock == from) {
- if (from_count > from->limit) {
+ if (from_count > from_link_limit) {
nodeRemLink(ntree, tlink);
tlink = NULL;
from_count--;
@@ -604,7 +606,7 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link)
}
if (tlink && tlink->tosock == to) {
- if (to_count > to->limit) {
+ if (to_count > to_link_limit) {
nodeRemLink(ntree, tlink);
tlink = NULL;
to_count--;
@@ -748,17 +750,17 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2])
static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
bNodeLinkDrag *nldrag = op->customdata;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float cursor[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
switch (event->type) {
case MOUSEMOVE:
node_link_find_socket(C, op, cursor);
node_link_update_header(C, nldrag);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case LEFTMOUSE:
@@ -768,7 +770,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
node_link_exit(C, op, true);
ED_workspace_status_text(C, NULL);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
break;
@@ -793,7 +795,8 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor
nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
num_links = nodeCountSocketLinks(snode->edittree, sock);
- if (num_links > 0 && (num_links >= sock->limit || detach)) {
+ int link_limit = nodeSocketLinkLimit(sock);
+ if (num_links > 0 && (num_links >= link_limit || detach)) {
/* dragged links are fixed on input side */
nldrag->in_out = SOCK_IN;
/* detach current links and store them in the operator data */
@@ -844,7 +847,8 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor
nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
num_links = nodeCountSocketLinks(snode->edittree, sock);
- if (num_links > 0 && (num_links >= sock->limit || detach)) {
+ int link_limit = nodeSocketLinkLimit(sock);
+ if (num_links > 0 && (num_links >= link_limit || detach)) {
/* dragged links are fixed on output side */
nldrag->in_out = SOCK_OUT;
/* detach current links and store them in the operator data */
@@ -896,13 +900,13 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bNodeLinkDrag *nldrag;
float cursor[2];
bool detach = RNA_boolean_get(op->ptr, "detach");
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
@@ -1019,7 +1023,7 @@ static int cut_links_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float mcoords[256][2];
int i = 0;
bool do_tag_update = false;
@@ -1028,7 +1032,8 @@ static int cut_links_exec(bContext *C, wmOperator *op)
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
- UI_view2d_region_to_view(&ar->v2d, (int)loc[0], (int)loc[1], &mcoords[i][0], &mcoords[i][1]);
+ UI_view2d_region_to_view(
+ &region->v2d, (int)loc[0], (int)loc[1], &mcoords[i][0], &mcoords[i][1]);
i++;
if (i >= 256) {
break;
@@ -1282,13 +1287,15 @@ void NODE_OT_join(wmOperatorType *ot)
/* ****************** Attach ******************* */
-static bNode *node_find_frame_to_attach(ARegion *ar, const bNodeTree *ntree, const int mouse_xy[2])
+static bNode *node_find_frame_to_attach(ARegion *region,
+ const bNodeTree *ntree,
+ const int mouse_xy[2])
{
bNode *frame;
float cursor[2];
/* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, UNPACK2(mouse_xy), &cursor[0], &cursor[1]);
+ UI_view2d_region_to_view(&region->v2d, UNPACK2(mouse_xy), &cursor[0], &cursor[1]);
/* check nodes front to back */
for (frame = ntree->nodes.last; frame; frame = frame->prev) {
@@ -1306,10 +1313,10 @@ static bNode *node_find_frame_to_attach(ARegion *ar, const bNodeTree *ntree, con
static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *frame = node_find_frame_to_attach(ar, ntree, event->mval);
+ bNode *frame = node_find_frame_to_attach(region, ntree, event->mval);
if (frame) {
bNode *node, *parent;
@@ -1439,9 +1446,12 @@ void NODE_OT_detach(wmOperatorType *ot)
/* ********************* automatic node insert on dragging ******************* */
/* prevent duplicate testing code below */
-static bool ed_node_link_conditions(ScrArea *sa, bool test, SpaceNode **r_snode, bNode **r_select)
+static bool ed_node_link_conditions(ScrArea *area,
+ bool test,
+ SpaceNode **r_snode,
+ bNode **r_select)
{
- SpaceNode *snode = sa ? sa->spacedata.first : NULL;
+ SpaceNode *snode = area ? area->spacedata.first : NULL;
bNode *node, *select = NULL;
bNodeLink *link;
@@ -1449,7 +1459,7 @@ static bool ed_node_link_conditions(ScrArea *sa, bool test, SpaceNode **r_snode,
*r_select = NULL;
/* no unlucky accidents */
- if (sa == NULL || sa->spacetype != SPACE_NODE) {
+ if (area == NULL || area->spacetype != SPACE_NODE) {
return false;
}
@@ -1494,14 +1504,14 @@ static bool ed_node_link_conditions(ScrArea *sa, bool test, SpaceNode **r_snode,
}
/* test == 0, clear all intersect flags */
-void ED_node_link_intersect_test(ScrArea *sa, int test)
+void ED_node_link_intersect_test(ScrArea *area, int test)
{
bNode *select;
SpaceNode *snode;
bNodeLink *link, *selink = NULL;
float dist_best = FLT_MAX;
- if (!ed_node_link_conditions(sa, test, &snode, &select)) {
+ if (!ed_node_link_conditions(area, test, &snode, &select)) {
return;
}
@@ -1612,8 +1622,8 @@ static void node_parent_offset_apply(NodeInsertOfsData *data, bNode *parent, con
node_offset_apply(parent, offset_x);
- /* flag all childs as offset to prevent them from being offset
- * separately (they've already moved with the parent) */
+ /* Flag all children as offset to prevent them from being offset
+ * separately (they've already moved with the parent). */
for (node = data->ntree->nodes.first; node; node = node->next) {
if (nodeIsChildOf(parent, node)) {
/* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
@@ -1647,7 +1657,7 @@ static bool node_link_insert_offset_frame_chain_cb(bNode *fromnode,
}
/**
- * Applies NodeInsertOfsData.offset_x to all childs of \a parent
+ * Applies #NodeInsertOfsData.offset_x to all children of \a parent.
*/
static void node_link_insert_offset_frame_chains(const bNodeTree *ntree,
const bNode *parent,
@@ -1700,7 +1710,7 @@ static bool node_link_insert_offset_chain_cb(bNode *fromnode,
}
static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd,
- ARegion *ar,
+ ARegion *region,
const int mouse_xy[2],
const bool right_alignment)
{
@@ -1726,7 +1736,7 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd,
/* frame attachment wasn't handled yet
* so we search the frame that the node will be attached to later */
- insert->parent = node_find_frame_to_attach(ar, ntree, mouse_xy);
+ insert->parent = node_find_frame_to_attach(region, ntree, mouse_xy);
/* this makes sure nodes are also correctly offset when inserting a node on top of a frame
* without actually making it a part of the frame (because mouse isn't intersecting it)
@@ -1912,14 +1922,14 @@ void NODE_OT_insert_offset(wmOperatorType *ot)
}
/* assumes link with NODE_LINKFLAG_HILITE set */
-void ED_node_link_insert(Main *bmain, ScrArea *sa)
+void ED_node_link_insert(Main *bmain, ScrArea *area)
{
bNode *node, *select;
SpaceNode *snode;
bNodeLink *link;
bNodeSocket *sockto;
- if (!ed_node_link_conditions(sa, true, &snode, &select)) {
+ if (!ed_node_link_conditions(area, true, &snode, &select)) {
return;
}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index e22ef389516..9eabcc44d80 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -25,12 +25,13 @@
#include "DNA_node_types.h"
-#include "BLI_utildefines.h"
-#include "BLI_rect.h"
#include "BLI_lasso_2d.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -50,6 +51,8 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "DEG_depsgraph.h"
+
#include "MEM_guardedalloc.h"
#include "node_intern.h" /* own include */
@@ -104,9 +107,9 @@ static bool is_position_over_node_or_socket(SpaceNode *snode, float mouse[2])
static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float mouse[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mouse[0], &mouse[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &mouse[0], &mouse[1]);
return is_position_over_node_or_socket(snode, mouse);
}
@@ -284,7 +287,7 @@ static bool node_select_grouped_name(SpaceNode *snode, bNode *node_act, const bo
{
bNode *node;
bool changed = false;
- const unsigned int delims[] = {'.', '-', '_', '\0'};
+ const uint delims[] = {'.', '-', '_', '\0'};
size_t pref_len_act, pref_len_curr;
const char *sep, *suf_act, *suf_curr;
@@ -436,7 +439,7 @@ static int node_mouse_select(bContext *C,
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bNode *node, *tnode;
bNodeSocket *sock = NULL;
bNodeSocket *tsock;
@@ -454,7 +457,7 @@ static int node_mouse_select(bContext *C,
}
/* get mouse coordinates in view2d space */
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
/* first do socket selection, these generally overlap with nodes. */
if (socket_select) {
@@ -548,6 +551,7 @@ static int node_mouse_select(bContext *C,
}
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
+ DEG_id_tag_update(&snode->edittree->id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
@@ -610,11 +614,11 @@ void NODE_OT_select(wmOperatorType *ot)
static int node_box_select_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
rctf rectf;
WM_operator_properties_border_to_rctf(op, &rectf);
- UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf);
+ UI_view2d_region_to_view_rctf(&region->v2d, &rectf, &rectf);
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
const bool select = (sel_op != SEL_OP_SUB);
@@ -622,7 +626,7 @@ static int node_box_select_exec(bContext *C, wmOperator *op)
ED_node_select_all(&snode->edittree->nodes, SEL_DESELECT);
}
- for (bNode *node = snode->edittree->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
bool is_inside;
if (node->type == NODE_FRAME) {
is_inside = BLI_rctf_inside_rctf(&rectf, &node->totr);
@@ -692,13 +696,14 @@ void NODE_OT_select_box(wmOperatorType *ot)
static int node_circleselect_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bNode *node;
int x, y, radius;
float offset[2];
- float zoom = (float)(BLI_rcti_size_x(&ar->winrct)) / (float)(BLI_rctf_size_x(&ar->v2d.cur));
+ float zoom = (float)(BLI_rcti_size_x(&region->winrct)) /
+ (float)(BLI_rctf_size_x(&region->v2d.cur));
const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
WM_gesture_is_modal_first(op->customdata));
@@ -712,7 +717,7 @@ static int node_circleselect_exec(bContext *C, wmOperator *op)
y = RNA_int_get(op->ptr, "y");
radius = RNA_int_get(op->ptr, "radius");
- UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
+ UI_view2d_region_to_view(&region->v2d, x, y, &offset[0], &offset[1]);
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (BLI_rctf_isect_circle(&node->totr, offset, radius / zoom)) {
@@ -764,12 +769,15 @@ static int node_lasso_select_invoke(bContext *C, wmOperator *op, const wmEvent *
return WM_gesture_lasso_invoke(C, op, event);
}
-static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves, eSelectOp sel_op)
+static bool do_lasso_select_node(bContext *C,
+ const int mcoords[][2],
+ const int mcoords_len,
+ eSelectOp sel_op)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
rcti rect;
bool changed = false;
@@ -781,7 +789,7 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves
}
/* get rectangle from operator */
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
/* do actual selection */
for (node = snode->edittree->nodes.first; node; node = node->next) {
@@ -794,9 +802,10 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves
const float cent[2] = {BLI_rctf_cent_x(&node->totr), BLI_rctf_cent_y(&node->totr)};
/* marker in screen coords */
- if (UI_view2d_view_to_region_clip(&ar->v2d, cent[0], cent[1], &screen_co[0], &screen_co[1]) &&
+ if (UI_view2d_view_to_region_clip(
+ &region->v2d, cent[0], cent[1], &screen_co[0], &screen_co[1]) &&
BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
- BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) {
+ BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co[0], screen_co[1], INT_MAX)) {
nodeSetSelected(node, select);
changed = true;
}
@@ -811,15 +820,15 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves
static int node_lasso_select_exec(bContext *C, wmOperator *op)
{
- int mcords_tot;
- const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+ int mcoords_len;
+ const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len);
- if (mcords) {
+ if (mcoords) {
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- do_lasso_select_node(C, mcords, mcords_tot, sel_op);
+ do_lasso_select_node(C, mcoords, mcoords_len, sel_op);
- MEM_freeN((void *)mcords);
+ MEM_freeN((void *)mcoords);
return OPERATOR_FINISHED;
}
@@ -1004,7 +1013,7 @@ void NODE_OT_select_linked_from(wmOperatorType *ot)
static int node_select_same_type_step_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bNode **node_array;
bNode *active = nodeGetActive(snode->edittree);
int totnodes;
@@ -1072,10 +1081,10 @@ static int node_select_same_type_step_exec(bContext *C, wmOperator *op)
node_select_single(C, active);
/* is note outside view? */
- if (active->totr.xmax < ar->v2d.cur.xmin || active->totr.xmin > ar->v2d.cur.xmax ||
- active->totr.ymax < ar->v2d.cur.ymin || active->totr.ymin > ar->v2d.cur.ymax) {
+ if (active->totr.xmax < region->v2d.cur.xmin || active->totr.xmin > region->v2d.cur.xmax ||
+ active->totr.ymax < region->v2d.cur.ymin || active->totr.ymin > region->v2d.cur.ymax) {
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- space_node_view_flag(C, snode, ar, NODE_SELECT, smooth_viewtx);
+ space_node_view_flag(C, snode, region, NODE_SELECT, smooth_viewtx);
}
}
@@ -1110,10 +1119,10 @@ void NODE_OT_select_same_type_step(wmOperatorType *ot)
* \{ */
/* generic search invoke */
-static void node_find_cb(const struct bContext *C,
- void *UNUSED(arg),
- const char *str,
- uiSearchItems *items)
+static void node_find_update_fn(const struct bContext *C,
+ void *UNUSED(arg),
+ const char *str,
+ uiSearchItems *items)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
@@ -1129,38 +1138,38 @@ static void node_find_cb(const struct bContext *C,
else {
BLI_strncpy(name, node->name, 256);
}
- if (false == UI_search_item_add(items, name, node, 0)) {
+ if (!UI_search_item_add(items, name, node, ICON_NONE, 0)) {
break;
}
}
}
}
-static void node_find_call_cb(struct bContext *C, void *UNUSED(arg1), void *arg2)
+static void node_find_exec_fn(struct bContext *C, void *UNUSED(arg1), void *arg2)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNode *active = arg2;
if (active) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
node_select_single(C, active);
/* is note outside view? */
- if (active->totr.xmax < ar->v2d.cur.xmin || active->totr.xmin > ar->v2d.cur.xmax ||
- active->totr.ymax < ar->v2d.cur.ymin || active->totr.ymin > ar->v2d.cur.ymax) {
- space_node_view_flag(C, snode, ar, NODE_SELECT, U.smooth_viewtx);
+ if (active->totr.xmax < region->v2d.cur.xmin || active->totr.xmin > region->v2d.cur.xmax ||
+ active->totr.ymax < region->v2d.cur.ymin || active->totr.ymin > region->v2d.cur.ymax) {
+ space_node_view_flag(C, snode, region, NODE_SELECT, U.smooth_viewtx);
}
}
}
-static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
+static uiBlock *node_find_menu(bContext *C, ARegion *region, void *arg_op)
{
static char search[256] = "";
uiBlock *block;
uiBut *but;
wmOperator *op = (wmOperator *)arg_op;
- block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
@@ -1176,7 +1185,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
0,
0,
"");
- UI_but_func_search_set(but, NULL, node_find_cb, op->type, false, node_find_call_cb, NULL);
+ UI_but_func_search_set(but, NULL, node_find_update_fn, op->type, NULL, node_find_exec_fn, NULL);
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
/* fake button, it holds space for search items */
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index c6994dab72d..87b1f662b59 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -33,7 +33,7 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_scene.h"
@@ -41,10 +41,11 @@
#include "NOD_socket.h"
-#include "UI_interface.h"
#include "../interface/interface_intern.h" /* XXX bad level */
+#include "UI_interface.h"
#include "ED_node.h" /* own include */
+#include "node_intern.h"
#include "ED_undo.h"
@@ -263,7 +264,7 @@ static void node_socket_add_replace(const bContext *C,
for (sock_prev = node_prev->inputs.first; sock_prev; sock_prev = sock_prev->next) {
for (sock_from = node_from->inputs.first; sock_from; sock_from = sock_from->next) {
- if (nodeCountSocketLinks(ntree, sock_from) >= sock_from->limit) {
+ if (nodeCountSocketLinks(ntree, sock_from) >= nodeSocketLinkLimit(sock_from)) {
continue;
}
@@ -662,17 +663,23 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group"));
}
-void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
+void uiTemplateNodeLink(
+ uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
{
uiBlock *block = uiLayoutGetBlock(layout);
NodeLinkArg *arg;
uiBut *but;
+ float socket_col[4];
arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg");
arg->ntree = ntree;
arg->node = node;
arg->sock = sock;
+ PointerRNA node_ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ node_socket_color_get(C, ntree, &node_ptr, sock, socket_col);
+
UI_block_layout_set_current(block, layout);
if (sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) {
@@ -687,8 +694,9 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo
}
UI_but_type_set_menu_from_pulldown(but);
+ UI_but_node_link_set(but, sock, socket_col);
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
- but->flag |= UI_BUT_NODE_LINK;
but->poin = (char *)but;
but->func_argN = arg;
@@ -708,18 +716,14 @@ static void ui_node_draw_node(
uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth)
{
bNodeSocket *input;
- uiLayout *col, *split;
PointerRNA nodeptr;
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
if (node->typeinfo->draw_buttons) {
if (node->type != NODE_GROUP) {
- split = uiLayoutSplit(layout, 0.5f, false);
- col = uiLayoutColumn(split, false);
- col = uiLayoutColumn(split, false);
-
- node->typeinfo->draw_buttons(col, C, &nodeptr);
+ uiLayoutSetPropSep(layout, true);
+ node->typeinfo->draw_buttons(layout, C, &nodeptr);
}
}
@@ -733,12 +737,9 @@ static void ui_node_draw_input(
{
PointerRNA inputptr, nodeptr;
uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *bt;
- uiLayout *split, *row, *col;
+ uiLayout *row = NULL;
bNode *lnode;
- char label[UI_MAX_NAME_STR];
- int i, indent = (depth > 1) ? 2 * (depth - 1) : 0;
- int dependency_loop;
+ bool dependency_loop;
if (input->flag & SOCK_UNAVAIL) {
return;
@@ -757,48 +758,43 @@ static void ui_node_draw_input(
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
- /* indented label */
- for (i = 0; i < indent; i++) {
- label[i] = ' ';
- }
- label[indent] = '\0';
- BLI_snprintf(label + indent, UI_MAX_NAME_STR - indent, "%s", IFACE_(input->name));
+ row = uiLayoutRow(layout, true);
+ /* Decorations are added manually here. */
+ uiLayoutSetPropDecorate(row, false);
- /* split in label and value */
- split = uiLayoutSplit(layout, 0.5f, false);
+ uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(row);
+ /* Empty decorator item for alignment. */
+ bool add_dummy_decorator = false;
- row = uiLayoutRow(split, true);
+ {
+ uiLayout *sub = uiLayoutRow(split_wrapper.label_column, true);
- if (depth > 0) {
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ if (depth > 0) {
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
- if (lnode &&
- (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) {
- int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT :
- ICON_DISCLOSURE_TRI_DOWN;
- uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon);
- }
- else {
- uiItemL(row, "", ICON_BLANK1);
- }
+ if (lnode &&
+ (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) {
+ int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT :
+ ICON_DISCLOSURE_TRI_DOWN;
+ uiItemR(sub, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon);
+ }
- bt = block->buttons.last;
- bt->rect.xmax = UI_UNIT_X / 2;
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
- UI_block_emboss_set(block, UI_EMBOSS);
+ sub = uiLayoutRow(sub, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
+ uiItemL(sub, IFACE_(input->name), ICON_NONE);
}
- uiItemL(row, label, ICON_NONE);
- bt = block->buttons.last;
- bt->drawflag = UI_BUT_TEXT_RIGHT;
-
if (dependency_loop) {
- row = uiLayoutRow(split, false);
uiItemL(row, IFACE_("Dependency Loop"), ICON_ERROR);
+ add_dummy_decorator = true;
}
else if (lnode) {
/* input linked to a node */
- uiTemplateNodeLink(split, ntree, node, input);
+ uiTemplateNodeLink(row, C, ntree, node, input);
+ add_dummy_decorator = true;
if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) {
if (depth == 0) {
@@ -809,33 +805,41 @@ static void ui_node_draw_input(
}
}
else {
+ row = uiLayoutRow(row, true);
+
+ uiTemplateNodeLink(row, C, ntree, node, input);
+
+ if (input->flag & SOCK_HIDE_VALUE) {
+ add_dummy_decorator = true;
+ }
/* input not linked, show value */
- if (!(input->flag & SOCK_HIDE_VALUE)) {
+ else {
+ uiLayout *sub = row;
+
switch (input->type) {
+ case SOCK_VECTOR:
+ if (input->type == SOCK_VECTOR) {
+ uiItemS(row);
+ sub = uiLayoutColumn(row, true);
+ }
+ ATTR_FALLTHROUGH;
case SOCK_FLOAT:
case SOCK_INT:
case SOCK_BOOLEAN:
case SOCK_RGBA:
case SOCK_STRING:
- row = uiLayoutRow(split, true);
- uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
- break;
- case SOCK_VECTOR:
- row = uiLayoutRow(split, false);
- col = uiLayoutColumn(row, false);
- uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
+ uiItemR(sub, &inputptr, "default_value", 0, "", ICON_NONE);
+ uiItemDecoratorR(
+ split_wrapper.decorate_column, &inputptr, "default_value", RNA_NO_INDEX);
break;
-
default:
- row = uiLayoutRow(split, false);
- break;
+ add_dummy_decorator = true;
}
}
- else {
- row = uiLayoutRow(split, false);
- }
+ }
- uiTemplateNodeLink(row, ntree, node, input);
+ if (add_dummy_decorator) {
+ uiItemDecoratorR(split_wrapper.decorate_column, NULL, NULL, 0);
}
/* clear */
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index f12d972f30c..740d090e641 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -23,9 +23,9 @@
#include "DNA_node_types.h"
+#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
-#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_image.h"
@@ -33,10 +33,10 @@
#include "BKE_node.h"
#include "BKE_screen.h"
+#include "ED_image.h"
#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_space_api.h"
-#include "ED_image.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -52,13 +52,13 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "node_intern.h" /* own include */
#include "NOD_composite.h"
+#include "node_intern.h" /* own include */
/* **************** View All Operator ************** */
int space_node_view_flag(
- bContext *C, SpaceNode *snode, ARegion *ar, const int node_flag, const int smooth_viewtx)
+ bContext *C, SpaceNode *snode, ARegion *region, const int node_flag, const int smooth_viewtx)
{
bNode *node;
rctf cur_new;
@@ -67,8 +67,8 @@ int space_node_view_flag(
int tot = 0;
bool has_frame = false;
- oldwidth = BLI_rctf_size_x(&ar->v2d.cur);
- oldheight = BLI_rctf_size_y(&ar->v2d.cur);
+ oldwidth = BLI_rctf_size_x(&region->v2d.cur);
+ oldheight = BLI_rctf_size_y(&region->v2d.cur);
oldasp = oldwidth / oldheight;
@@ -114,7 +114,7 @@ int space_node_view_flag(
BLI_rctf_scale(&cur_new, 1.1f);
}
- UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
+ UI_view2d_smooth_view(C, region, &cur_new, smooth_viewtx);
}
return (tot != 0);
@@ -122,7 +122,7 @@ int space_node_view_flag(
static int node_view_all_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
@@ -130,7 +130,7 @@ static int node_view_all_exec(bContext *C, wmOperator *op)
snode->xof = 0;
snode->yof = 0;
- if (space_node_view_flag(C, snode, ar, 0, smooth_viewtx)) {
+ if (space_node_view_flag(C, snode, region, 0, smooth_viewtx)) {
return OPERATOR_FINISHED;
}
else {
@@ -141,7 +141,7 @@ static int node_view_all_exec(bContext *C, wmOperator *op)
void NODE_OT_view_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->idname = "NODE_OT_view_all";
ot->description = "Resize view so you can see all nodes";
@@ -155,11 +155,11 @@ void NODE_OT_view_all(wmOperatorType *ot)
static int node_view_selected_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- if (space_node_view_flag(C, snode, ar, NODE_SELECT, smooth_viewtx)) {
+ if (space_node_view_flag(C, snode, region, NODE_SELECT, smooth_viewtx)) {
return OPERATOR_FINISHED;
}
else {
@@ -170,7 +170,7 @@ static int node_view_selected_exec(bContext *C, wmOperator *op)
void NODE_OT_view_selected(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Selected";
+ ot->name = "Frame Selected";
ot->idname = "NODE_OT_view_selected";
ot->description = "Resize view so you can see selected nodes";
@@ -192,7 +192,7 @@ typedef struct NodeViewMove {
static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
NodeViewMove *nvm = op->customdata;
switch (event->type) {
@@ -207,7 +207,7 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *e
CLAMP(snode->xof, nvm->xmin, nvm->xmax);
CLAMP(snode->yof, nvm->ymin, nvm->ymax);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL);
break;
@@ -230,7 +230,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
NodeViewMove *nvm;
Image *ima;
ImBuf *ibuf;
@@ -238,7 +238,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *
void *lock;
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf == NULL) {
@@ -251,10 +251,10 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *
nvm->mvalo[0] = event->mval[0];
nvm->mvalo[1] = event->mval[1];
- nvm->xmin = -(ar->winx / 2) - (ibuf->x * (0.5f * snode->zoom)) + pad;
- nvm->xmax = (ar->winx / 2) + (ibuf->x * (0.5f * snode->zoom)) - pad;
- nvm->ymin = -(ar->winy / 2) - (ibuf->y * (0.5f * snode->zoom)) + pad;
- nvm->ymax = (ar->winy / 2) + (ibuf->y * (0.5f * snode->zoom)) - pad;
+ nvm->xmin = -(region->winx / 2) - (ibuf->x * (0.5f * snode->zoom)) + pad;
+ nvm->xmax = (region->winx / 2) + (ibuf->x * (0.5f * snode->zoom)) - pad;
+ nvm->ymin = -(region->winy / 2) - (ibuf->y * (0.5f * snode->zoom)) + pad;
+ nvm->ymax = (region->winy / 2) + (ibuf->y * (0.5f * snode->zoom)) - pad;
BKE_image_release_ibuf(ima, ibuf, lock);
@@ -290,11 +290,11 @@ void NODE_OT_backimage_move(wmOperatorType *ot)
static int backimage_zoom_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float fac = RNA_float_get(op->ptr, "factor");
snode->zoom *= fac;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL);
return OPERATOR_FINISHED;
@@ -323,7 +323,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Image *ima;
ImBuf *ibuf;
@@ -334,7 +334,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
float facx, facy;
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if ((ibuf == NULL) || (ibuf->x == 0) || (ibuf->y == 0)) {
@@ -342,8 +342,8 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- facx = 1.0f * (ar->sizex - pad) / (ibuf->x * snode->zoom);
- facy = 1.0f * (ar->sizey - pad) / (ibuf->y * snode->zoom);
+ facx = 1.0f * (region->sizex - pad) / (ibuf->x * snode->zoom);
+ facy = 1.0f * (region->sizey - pad) / (ibuf->y * snode->zoom);
BKE_image_release_ibuf(ima, ibuf, lock);
@@ -352,7 +352,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
snode->xof = 0;
snode->yof = 0;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL);
return OPERATOR_FINISHED;
@@ -382,7 +382,7 @@ typedef struct ImageSampleInfo {
int x, y;
int channels;
- unsigned char col[4];
+ uchar col[4];
float colf[4];
float linearcol[4];
@@ -396,14 +396,14 @@ typedef struct ImageSampleInfo {
int color_manage;
} ImageSampleInfo;
-static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
+static void sample_draw(const bContext *C, ARegion *region, void *arg_info)
{
Scene *scene = CTX_data_scene(C);
ImageSampleInfo *info = arg_info;
if (info->draw) {
ED_image_draw_info(scene,
- ar,
+ region,
info->color_manage,
false,
info->channels,
@@ -421,7 +421,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
* And here we've got recursion in the comments tips...
*/
bool ED_space_node_color_sample(
- Main *bmain, SpaceNode *snode, ARegion *ar, int mval[2], float r_col[3])
+ Main *bmain, SpaceNode *snode, ARegion *region, int mval[2], float r_col[3])
{
void *lock;
Image *ima;
@@ -436,7 +436,7 @@ bool ED_space_node_color_sample(
return false;
}
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (!ibuf) {
return false;
@@ -445,12 +445,12 @@ bool ED_space_node_color_sample(
/* map the mouse coords to the backdrop image space */
bufx = ibuf->x * snode->zoom;
bufy = ibuf->y * snode->zoom;
- fx = (bufx > 0.0f ? ((float)mval[0] - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
- fy = (bufy > 0.0f ? ((float)mval[1] - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
+ fx = (bufx > 0.0f ? ((float)mval[0] - 0.5f * region->winx - snode->xof) / bufx + 0.5f : 0.0f);
+ fy = (bufy > 0.0f ? ((float)mval[1] - 0.5f * region->winy - snode->yof) / bufy + 0.5f : 0.0f);
if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
const float *fp;
- unsigned char *cp;
+ uchar *cp;
int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
CLAMP(x, 0, ibuf->x - 1);
@@ -463,7 +463,7 @@ bool ED_space_node_color_sample(
ret = true;
}
else if (ibuf->rect) {
- cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
+ cp = (uchar *)(ibuf->rect + y * ibuf->x + x);
rgb_uchar_to_float(r_col, cp);
IMB_colormanagement_colorspace_to_scene_linear_v3(r_col, ibuf->rect_colorspace);
ret = true;
@@ -479,14 +479,14 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ImageSampleInfo *info = op->customdata;
void *lock;
Image *ima;
ImBuf *ibuf;
float fx, fy, bufx, bufy;
- ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (!ibuf) {
info->draw = 0;
@@ -500,12 +500,14 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
/* map the mouse coords to the backdrop image space */
bufx = ibuf->x * snode->zoom;
bufy = ibuf->y * snode->zoom;
- fx = (bufx > 0.0f ? ((float)event->mval[0] - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
- fy = (bufy > 0.0f ? ((float)event->mval[1] - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
+ fx = (bufx > 0.0f ? ((float)event->mval[0] - 0.5f * region->winx - snode->xof) / bufx + 0.5f :
+ 0.0f);
+ fy = (bufy > 0.0f ? ((float)event->mval[1] - 0.5f * region->winy - snode->yof) / bufy + 0.5f :
+ 0.0f);
if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
const float *fp;
- unsigned char *cp;
+ uchar *cp;
int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
CLAMP(x, 0, ibuf->x - 1);
@@ -520,7 +522,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
info->zfp = NULL;
if (ibuf->rect) {
- cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
+ cp = (uchar *)(ibuf->rect + y * ibuf->x + x);
info->col[0] = cp[0];
info->col[1] = cp[1];
@@ -583,7 +585,7 @@ static void sample_exit(bContext *C, wmOperator *op)
static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ImageSampleInfo *info;
if (!ED_node_is_compositor(snode) || !(snode->flag & SNODE_BACKDRAW)) {
@@ -591,9 +593,9 @@ static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
- info->art = ar->type;
+ info->art = region->type;
info->draw_handle = ED_region_draw_cb_activate(
- ar->type, sample_draw, info, REGION_DRAW_POST_PIXEL);
+ region->type, sample_draw, info, REGION_DRAW_POST_PIXEL);
op->customdata = info;
sample_apply(C, op, event);
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index e114c3dbc05..f339d11b842 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -33,15 +33,15 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
+#include "BKE_node.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BKE_node.h"
-#include "ED_space_api.h"
#include "ED_node.h"
#include "ED_render.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -246,7 +246,7 @@ void snode_group_offset(SpaceNode *snode, float *x, float *y)
static SpaceLink *node_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceNode *snode;
snode = MEM_callocN(sizeof(SpaceNode), "initnode");
@@ -265,53 +265,53 @@ static SpaceLink *node_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
NODE_TREE_TYPES_END;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for node");
+ region = MEM_callocN(sizeof(ARegion), "header for node");
- BLI_addtail(&snode->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&snode->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* buttons/list view */
- ar = MEM_callocN(sizeof(ARegion), "buttons for node");
+ region = MEM_callocN(sizeof(ARegion), "buttons for node");
- BLI_addtail(&snode->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_RIGHT;
+ BLI_addtail(&snode->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_RIGHT;
/* toolbar */
- ar = MEM_callocN(sizeof(ARegion), "node tools");
+ region = MEM_callocN(sizeof(ARegion), "node tools");
- BLI_addtail(&snode->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOLS;
- ar->alignment = RGN_ALIGN_LEFT;
+ BLI_addtail(&snode->regionbase, region);
+ region->regiontype = RGN_TYPE_TOOLS;
+ region->alignment = RGN_ALIGN_LEFT;
- ar->flag = RGN_FLAG_HIDDEN;
+ region->flag = RGN_FLAG_HIDDEN;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for node");
+ region = MEM_callocN(sizeof(ARegion), "main region for node");
- BLI_addtail(&snode->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&snode->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.tot.xmin = -12.8f * U.widget_unit;
- ar->v2d.tot.ymin = -12.8f * U.widget_unit;
- ar->v2d.tot.xmax = 38.4f * U.widget_unit;
- ar->v2d.tot.ymax = 38.4f * U.widget_unit;
+ region->v2d.tot.xmin = -12.8f * U.widget_unit;
+ region->v2d.tot.ymin = -12.8f * U.widget_unit;
+ region->v2d.tot.xmax = 38.4f * U.widget_unit;
+ region->v2d.tot.ymax = 38.4f * U.widget_unit;
- ar->v2d.cur = ar->v2d.tot;
+ region->v2d.cur = region->v2d.tot;
- ar->v2d.min[0] = 1.0f;
- ar->v2d.min[1] = 1.0f;
+ region->v2d.min[0] = 1.0f;
+ region->v2d.min[1] = 1.0f;
- ar->v2d.max[0] = 32000.0f;
- ar->v2d.max[1] = 32000.0f;
+ region->v2d.max[0] = 32000.0f;
+ region->v2d.max[1] = 32000.0f;
- ar->v2d.minzoom = 0.09f;
- ar->v2d.maxzoom = 2.31f;
+ region->v2d.minzoom = 0.09f;
+ region->v2d.maxzoom = 2.31f;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
- ar->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT;
- ar->v2d.keeptot = 0;
+ region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ region->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT;
+ region->v2d.keeptot = 0;
return (SpaceLink *)snode;
}
@@ -328,17 +328,17 @@ static void node_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
static void node_area_listener(wmWindow *UNUSED(win),
- ScrArea *sa,
+ ScrArea *area,
wmNotifier *wmn,
Scene *UNUSED(scene))
{
/* note, ED_area_tag_refresh will re-execute compositor */
- SpaceNode *snode = sa->spacedata.first;
+ SpaceNode *snode = area->spacedata.first;
/* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */
short shader_type = snode->shaderfrom;
@@ -347,32 +347,32 @@ static void node_area_listener(wmWindow *UNUSED(win),
case NC_SCENE:
switch (wmn->data) {
case ND_NODES: {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
bNodeTreePath *path = snode->treepath.last;
/* shift view to node tree center */
- if (ar && path) {
- UI_view2d_center_set(&ar->v2d, path->view_center[0], path->view_center[1]);
+ if (region && path) {
+ UI_view2d_center_set(&region->v2d, path->view_center[0], path->view_center[1]);
}
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
}
case ND_FRAME:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case ND_COMPO_RESULT:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case ND_TRANSFORM_DONE:
if (ED_node_is_compositor(snode)) {
if (snode->flag & SNODE_AUTO_RENDER) {
snode->recalc = 1;
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
}
break;
case ND_LAYER_CONTENT:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
}
break;
@@ -381,13 +381,13 @@ static void node_area_listener(wmWindow *UNUSED(win),
case NC_MATERIAL:
if (ED_node_is_shader(snode)) {
if (wmn->data == ND_SHADING) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
else if (wmn->data == ND_SHADING_DRAW) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
else if (wmn->data == ND_SHADING_LINKS) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
else if (wmn->action == NA_ADDED && snode->edittree) {
nodeSetActiveID(snode->edittree, ID_MA, wmn->reference);
@@ -397,49 +397,49 @@ static void node_area_listener(wmWindow *UNUSED(win),
case NC_TEXTURE:
if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
if (wmn->data == ND_NODES) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
}
break;
case NC_WORLD:
if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
break;
case NC_OBJECT:
if (ED_node_is_shader(snode)) {
if (wmn->data == ND_OB_SHADING) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_NODE) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
else if (wmn->data == ND_SPACE_NODE_VIEW) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
case NC_NODE:
if (wmn->action == NA_EDITED) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
else if (wmn->action == NA_SELECTED) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
case NC_SCREEN:
switch (wmn->data) {
case ND_ANIMPLAY:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
}
break;
case NC_MASK:
if (wmn->action == NA_EDITED) {
if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
}
break;
@@ -451,7 +451,7 @@ static void node_area_listener(wmWindow *UNUSED(win),
* scenes so really this is just to know if the images is used in the compo else
* painting on images could become very slow when the compositor is open. */
if (nodeUpdateID(snode->nodetree, wmn->reference)) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
}
}
@@ -461,7 +461,7 @@ static void node_area_listener(wmWindow *UNUSED(win),
if (wmn->action == NA_EDITED) {
if (ED_node_is_compositor(snode)) {
if (nodeUpdateID(snode->nodetree, wmn->reference)) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
}
}
@@ -469,26 +469,26 @@ static void node_area_listener(wmWindow *UNUSED(win),
case NC_LINESTYLE:
if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_LINESTYLE) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
break;
case NC_WM:
if (wmn->data == ND_UNDO) {
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
}
break;
case NC_GPENCIL:
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
}
}
-static void node_area_refresh(const struct bContext *C, ScrArea *sa)
+static void node_area_refresh(const struct bContext *C, ScrArea *area)
{
/* default now: refresh node is starting preview */
- SpaceNode *snode = sa->spacedata.first;
+ SpaceNode *snode = area->spacedata.first;
snode_set_context(C);
@@ -497,19 +497,19 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
if (GS(snode->id->name) == ID_MA) {
Material *ma = (Material *)snode->id;
if (ma->use_nodes) {
- ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
+ ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
}
}
else if (GS(snode->id->name) == ID_LA) {
Light *la = (Light *)snode->id;
if (la->use_nodes) {
- ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
+ ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
}
}
else if (GS(snode->id->name) == ID_WO) {
World *wo = (World *)snode->id;
if (wo->use_nodes) {
- ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
+ ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
}
}
}
@@ -529,7 +529,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
else if (snode->nodetree->type == NTREE_TEXTURE) {
Tex *tex = (Tex *)snode->id;
if (tex->use_nodes) {
- ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
+ ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
}
}
}
@@ -554,45 +554,45 @@ static SpaceLink *node_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar)
+static void node_buttons_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void node_buttons_region_draw(const bContext *C, ARegion *ar)
+static void node_buttons_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar)
+static void node_toolbar_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void node_toolbar_region_draw(const bContext *C, ARegion *ar)
+static void node_toolbar_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
-static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
+static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region)
{
- SpaceNode *snode = sa->spacedata.first;
+ SpaceNode *snode = area->spacedata.first;
/* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d,
- win->eventstate->x - ar->winrct.xmin,
- win->eventstate->y - ar->winrct.ymin,
+ UI_view2d_region_to_view(&region->v2d,
+ win->eventstate->x - region->winrct.xmin,
+ win->eventstate->y - region->winrct.ymin,
&snode->cursor[0],
&snode->cursor[1]);
@@ -605,29 +605,29 @@ static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
}
/* Initialize main region, setting handlers. */
-static void node_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void node_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
ListBase *lb;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
/* own keymaps */
keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Node Editor", SPACE_NODE, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
/* add drop boxes */
lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
- WM_event_add_dropbox_handler(&ar->handlers, lb);
+ WM_event_add_dropbox_handler(&region->handlers, lb);
}
-static void node_main_region_draw(const bContext *C, ARegion *ar)
+static void node_main_region_draw(const bContext *C, ARegion *region)
{
- drawnodespace(C, ar);
+ drawnodespace(C, region);
}
/* ************* dropboxes ************* */
@@ -635,7 +635,7 @@ static void node_main_region_draw(const bContext *C, ARegion *ar)
static bool node_ima_drop_poll(bContext *UNUSED(C),
wmDrag *drag,
const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
if (drag->type == WM_DRAG_PATH) {
/* rule might not work? */
@@ -649,7 +649,7 @@ static bool node_ima_drop_poll(bContext *UNUSED(C),
static bool node_mask_drop_poll(bContext *UNUSED(C),
wmDrag *drag,
const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
return WM_drag_ID(drag, ID_MSK) != NULL;
}
@@ -687,34 +687,34 @@ static void node_dropboxes(void)
/* ************* end drop *********** */
/* add handlers, stuff you only do once or on area/region changes */
-static void node_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void node_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void node_header_region_draw(const bContext *C, ARegion *ar)
+static void node_header_region_draw(const bContext *C, ARegion *region)
{
/* find and set the context */
snode_set_context(C);
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
/* used for header + main region */
static void node_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
- wmGizmoMap *gzmap = ar->gizmo_map;
+ wmGizmoMap *gzmap = region->gizmo_map;
/* context changes */
switch (wmn->category) {
case NC_SPACE:
switch (wmn->data) {
case ND_SPACE_NODE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_SPACE_NODE_VIEW:
WM_gizmomap_tag_refresh(gzmap);
@@ -728,23 +728,23 @@ static void node_region_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_ANIMPLAY:
case ND_LAYER:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_WM:
if (wmn->data == ND_JOB) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
if (wmn->data == ND_RENDER_RESULT) {
WM_gizmomap_tag_refresh(gzmap);
}
break;
case NC_NODE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
WM_gizmomap_tag_refresh(gzmap);
}
@@ -753,24 +753,24 @@ static void node_region_listener(wmWindow *UNUSED(win),
case NC_TEXTURE:
case NC_WORLD:
case NC_LINESTYLE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_OBJECT:
if (wmn->data == ND_OB_SHADING) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_GPENCIL:
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
else if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -851,23 +851,21 @@ static void node_widgets(void)
WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_corner_pin);
}
-static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void node_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceNode *snode = (SpaceNode *)slink;
- if (GS(old_id->name) == ID_SCE) {
- if (snode->id == old_id) {
- /* nasty DNA logic for SpaceNode:
- * ideally should be handled by editor code, but would be bad level call
- */
- BLI_freelistN(&snode->treepath);
-
- /* XXX Untested in case new_id != NULL... */
- snode->id = new_id;
- snode->from = NULL;
- snode->nodetree = NULL;
- snode->edittree = NULL;
- }
+ if (snode->id == old_id) {
+ /* nasty DNA logic for SpaceNode:
+ * ideally should be handled by editor code, but would be bad level call
+ */
+ BLI_freelistN(&snode->treepath);
+
+ /* XXX Untested in case new_id != NULL... */
+ snode->id = new_id;
+ snode->from = NULL;
+ snode->nodetree = NULL;
+ snode->edittree = NULL;
}
else if (GS(old_id->name) == ID_OB) {
if (snode->from == old_id) {
@@ -890,8 +888,7 @@ static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
for (path = snode->treepath.first; path; path = path->next) {
if ((ID *)path->nodetree == old_id) {
path->nodetree = (bNodeTree *)new_id;
- id_us_min(old_id);
- id_us_plus(new_id);
+ id_us_ensure_real(new_id);
}
if (path == snode->treepath.first) {
/* first nodetree in path is same as snode->nodetree */
@@ -922,15 +919,15 @@ static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
}
}
-static int node_space_subtype_get(ScrArea *sa)
+static int node_space_subtype_get(ScrArea *area)
{
- SpaceNode *snode = sa->spacedata.first;
+ SpaceNode *snode = area->spacedata.first;
return rna_node_tree_idname_to_enum(snode->tree_idname);
}
-static void node_space_subtype_set(ScrArea *sa, int value)
+static void node_space_subtype_set(ScrArea *area, int value)
{
- SpaceNode *snode = sa->spacedata.first;
+ SpaceNode *snode = area->spacedata.first;
ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
}
@@ -939,6 +936,11 @@ static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item,
bool free;
const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free);
for (const EnumPropertyItem *item_iter = item_src; item_iter->identifier; item_iter++) {
+#ifndef WITH_NEW_SIMULATION_TYPE
+ if (STREQ(item_iter->identifier, "SimulationNodeTree")) {
+ continue;
+ }
+#endif
RNA_enum_item_add(item, totitem, item_iter);
}
if (free) {
@@ -981,6 +983,7 @@ void ED_spacetype_node(void)
art->listener = node_region_listener;
art->cursor = node_cursor;
art->event_cursor = true;
+ art->clip_gizmo_events_by_ui = true;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 183a96d1325..82ff9e06194 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -20,16 +20,16 @@
#include <string.h>
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "DNA_collection_types.h"
#include "DNA_object_types.h"
-#include "BKE_context.h"
#include "BKE_collection.h"
+#include "BKE_context.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -41,8 +41,8 @@
#include "ED_screen.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -53,6 +53,8 @@
#include "outliner_intern.h" /* own include */
/* -------------------------------------------------------------------- */
+/** \name Utility API
+ * \{ */
bool outliner_is_collection_tree_element(const TreeElement *te)
{
@@ -133,8 +135,30 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom
return TRAVERSE_CONTINUE;
}
+/**
+ * Populates the \param objects: ListBase with all the outliner selected objects
+ * We store it as (Object *)LinkData->data
+ * \param objects: expected to be empty
+ */
+void ED_outliner_selected_objects_get(const bContext *C, ListBase *objects)
+{
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ struct IDsSelectedData data = {{NULL}};
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
+ LISTBASE_FOREACH (LinkData *, link, &data.selected_array) {
+ TreeElement *ten_selected = (TreeElement *)link->data;
+ Object *ob = (Object *)TREESTORE(ten_selected)->id;
+ BLI_addtail(objects, BLI_genericNodeN(ob));
+ }
+ BLI_freelistN(&data.selected_array);
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Poll functions. */
+/** \name Poll Functions
+ * \{ */
bool ED_outliner_collections_editor_poll(bContext *C)
{
@@ -148,7 +172,11 @@ static bool outliner_view_layer_collections_editor_poll(bContext *C)
return (so != NULL) && (so->outlinevis == SO_VIEW_LAYER);
}
-/********************************* New Collection ****************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name New Collection
+ * \{ */
struct CollectionNewData {
bool error;
@@ -176,7 +204,7 @@ static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void
static int collection_new_exec(bContext *C, wmOperator *op)
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -187,7 +215,7 @@ static int collection_new_exec(bContext *C, wmOperator *op)
};
if (RNA_boolean_get(op->ptr, "nested")) {
- outliner_build_tree(bmain, scene, view_layer, soops, ar);
+ outliner_build_tree(bmain, scene, view_layer, soops, region);
outliner_tree_traverse(
soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
@@ -237,7 +265,11 @@ void OUTLINER_OT_collection_new(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/**************************** Delete Collection ******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Collection
+ * \{ */
struct CollectionEditData {
Scene *scene;
@@ -268,19 +300,15 @@ static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *c
return TRAVERSE_CONTINUE;
}
-static int collection_delete_exec(bContext *C, wmOperator *op)
+void outliner_collection_delete(
+ bContext *C, Main *bmain, Scene *scene, ReportList *reports, bool hierarchy)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const Base *basact_prev = BASACT(view_layer);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
+
struct CollectionEditData data = {
.scene = scene,
.soops = soops,
};
- bool hierarchy = RNA_boolean_get(op->ptr, "hierarchy");
data.collections_to_edit = BLI_gset_ptr_new(__func__);
@@ -304,8 +332,7 @@ static int collection_delete_exec(bContext *C, wmOperator *op)
skip = true;
}
else {
- for (CollectionParent *cparent = collection->parents.first; cparent;
- cparent = cparent->next) {
+ LISTBASE_FOREACH (CollectionParent *, cparent, &collection->parents) {
Collection *parent = cparent->collection;
if (ID_IS_LINKED(parent)) {
skip = true;
@@ -327,7 +354,7 @@ static int collection_delete_exec(bContext *C, wmOperator *op)
}
else {
BKE_reportf(
- op->reports,
+ reports,
RPT_WARNING,
"Cannot delete linked collection '%s', it is used by other linked scenes/collections",
collection->id.name + 2);
@@ -336,6 +363,17 @@ static int collection_delete_exec(bContext *C, wmOperator *op)
}
BLI_gset_free(data.collections_to_edit, NULL);
+}
+
+static int collection_hierarchy_delete_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ const Base *basact_prev = BASACT(view_layer);
+
+ outliner_collection_delete(C, bmain, scene, op->reports, true);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
DEG_relations_tag_update(bmain);
@@ -346,30 +384,31 @@ static int collection_delete_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
}
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_delete(wmOperatorType *ot)
+void OUTLINER_OT_collection_hierarchy_delete(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Delete Collection";
- ot->idname = "OUTLINER_OT_collection_delete";
- ot->description = "Delete selected collections";
+ ot->name = "Delete Hierarchy";
+ ot->idname = "OUTLINER_OT_collection_hierarchy_delete";
+ ot->description = "Delete selected collection hierarchies";
/* api callbacks */
- ot->exec = collection_delete_exec;
+ ot->exec = collection_hierarchy_delete_exec;
ot->poll = ED_outliner_collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- PropertyRNA *prop = RNA_def_boolean(
- ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/****************************** Select Objects *******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select/Deselect Collection Objects
+ * \{ */
struct CollectionObjectsSelectData {
bool error;
@@ -423,6 +462,7 @@ static int collection_objects_select_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
return OPERATOR_FINISHED;
}
@@ -457,7 +497,11 @@ void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/************************** Duplicate Collection *****************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Duplicate Collection
+ * \{ */
struct CollectionDuplicateData {
TreeElement *te;
@@ -541,6 +585,7 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
+ ED_outliner_select_sync_from_object_tag(C);
return OPERATOR_FINISHED;
}
@@ -578,7 +623,11 @@ void OUTLINER_OT_collection_duplicate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**************************** Link Collection ******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Link Collection
+ * \{ */
static int collection_link_exec(bContext *C, wmOperator *op)
{
@@ -636,7 +685,11 @@ void OUTLINER_OT_collection_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/************************** Instance Collection ******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Instance Collection
+ * \{ */
static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -703,7 +756,11 @@ void OUTLINER_OT_collection_instance(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/************************** Exclude Collection ******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Exclude Collection
+ * \{ */
static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, void *customdata)
{
@@ -794,20 +851,6 @@ static bool collections_indirect_only_clear_poll(bContext *C)
return collections_view_layer_poll(C, true, LAYER_COLLECTION_INDIRECT_ONLY);
}
-static void layer_collection_flag_recursive_set(LayerCollection *lc, int flag)
-{
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- if (lc->flag & flag) {
- nlc->flag |= flag;
- }
- else {
- nlc->flag &= ~flag;
- }
-
- layer_collection_flag_recursive_set(nlc, flag);
- }
-}
-
static int collection_view_layer_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -832,15 +875,7 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op)
GSetIterator collections_to_edit_iter;
GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
-
- if (clear) {
- lc->flag &= ~flag;
- }
- else {
- lc->flag |= flag;
- }
-
- layer_collection_flag_recursive_set(lc, flag);
+ BKE_layer_collection_set_flag(lc, flag, !clear);
}
BLI_gset_free(data.collections_to_edit, NULL);
@@ -945,7 +980,11 @@ void OUTLINER_OT_collection_indirect_only_clear(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/************************** Visibility Operators ******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Visibility for Collection Operators
+ * \{ */
static int collection_isolate_exec(bContext *C, wmOperator *op)
{
@@ -1129,6 +1168,12 @@ void OUTLINER_OT_collection_hide_inside(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Enable/Disable Collection Operators
+ * \{ */
+
static bool collection_flag_poll(bContext *C, bool clear, int flag)
{
if (!ED_outliner_collections_editor_poll(C)) {
@@ -1310,6 +1355,12 @@ struct OutlinerHideEditData {
GSet *bases_to_edit;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Visibility for Collection & Object Operators
+ * \{ */
+
static TreeTraversalAction outliner_hide_find_data_to_edit(TreeElement *te, void *customdata)
{
struct OutlinerHideEditData *data = customdata;
@@ -1400,14 +1451,12 @@ static int outliner_unhide_all_exec(bContext *C, wmOperator *UNUSED(op))
/* Unhide all the collections. */
LayerCollection *lc_master = view_layer->layer_collections.first;
- for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter;
- lc_iter = lc_iter->next) {
- lc_iter->flag &= ~LAYER_COLLECTION_HIDE;
- layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_HIDE);
+ LISTBASE_FOREACH (LayerCollection *, lc_iter, &lc_master->layer_collections) {
+ BKE_layer_collection_set_flag(lc_iter, LAYER_COLLECTION_HIDE, false);
}
/* Unhide all objects. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
base->flag &= ~BASE_HIDDEN;
}
@@ -1433,21 +1482,4 @@ void OUTLINER_OT_unhide_all(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**
- * Populates the \param objects: ListBase with all the outliner selected objects
- * We store it as (Object *)LinkData->data
- * \param objects: expected to be empty
- */
-void ED_outliner_selected_objects_get(const bContext *C, ListBase *objects)
-{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
- struct IDsSelectedData data = {{NULL}};
- outliner_tree_traverse(
- soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
- LISTBASE_FOREACH (LinkData *, link, &data.selected_array) {
- TreeElement *ten_selected = (TreeElement *)link->data;
- Object *ob = (Object *)TREESTORE(ten_selected)->id;
- BLI_addtail(objects, BLI_genericNodeN(ob));
- }
- BLI_freelistN(&data.selected_array);
-}
+/** \} */
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
index 602031a6854..c2c9f3a5bfb 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -38,7 +38,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
@@ -107,10 +107,10 @@ static TreeElement *outliner_dropzone_find(const SpaceOutliner *soops,
static TreeElement *outliner_drop_find(bContext *C, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
float fmval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
return outliner_dropzone_find(soops, fmval, true);
}
@@ -134,11 +134,12 @@ static TreeElement *outliner_drop_insert_find(bContext *C,
TreeElementInsertType *r_insert_type)
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
TreeElement *te_hovered;
float view_mval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
te_hovered = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
if (te_hovered) {
@@ -236,7 +237,7 @@ static TreeElement *outliner_drop_insert_collection_find(bContext *C,
/* ******************** Parent Drop Operator *********************** */
-static bool parent_drop_allowed(SpaceOutliner *soops, TreeElement *te, Object *potential_child)
+static bool parent_drop_allowed(TreeElement *te, Object *potential_child)
{
TreeStoreElem *tselem = TREESTORE(te);
if (te->idcode != ID_OB || tselem->type != 0) {
@@ -256,14 +257,13 @@ static bool parent_drop_allowed(SpaceOutliner *soops, TreeElement *te, Object *p
}
/* check that parent/child are both in the same scene */
- Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
+ Scene *scene = (Scene *)outliner_search_back(te, ID_SCE);
/* currently outliner organized in a way that if there's no parent scene
* element for object it means that all displayed objects belong to
* active scene and parenting them is allowed (sergey) */
if (scene) {
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer;
- view_layer = view_layer->next) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
if (BKE_view_layer_base_find(view_layer, potential_child)) {
return true;
}
@@ -290,7 +290,7 @@ static bool allow_parenting_without_modifier_key(SpaceOutliner *soops)
static bool parent_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
@@ -315,7 +315,7 @@ static bool parent_drop_poll(bContext *C,
return false;
}
- if (parent_drop_allowed(soops, te, potential_child)) {
+ if (parent_drop_allowed(te, potential_child)) {
TREESTORE(te)->flag |= TSE_DRAG_INTO;
ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
return true;
@@ -324,14 +324,18 @@ static bool parent_drop_poll(bContext *C,
return false;
}
-static void parent_drop_set_parents(
- bContext *C, ReportList *reports, wmDragID *drag, Object *parent, short parent_type)
+static void parent_drop_set_parents(bContext *C,
+ ReportList *reports,
+ wmDragID *drag,
+ Object *parent,
+ short parent_type,
+ const bool keep_transform)
{
Main *bmain = CTX_data_main(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te = outliner_find_id(soops, &soops->tree, &parent->id);
- Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
+ Scene *scene = (Scene *)outliner_search_back(te, ID_SCE);
if (scene == NULL) {
/* currently outliner organized in a way, that if there's no parent scene
@@ -356,7 +360,7 @@ static void parent_drop_set_parents(
}
if (ED_object_parent_set(
- reports, C, scene, object, parent, parent_type, false, false, NULL)) {
+ reports, C, scene, object, parent, parent_type, false, keep_transform, NULL)) {
parent_set = true;
}
}
@@ -399,7 +403,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ListBase *lb = event->customdata;
wmDrag *drag = lb->first;
- parent_drop_set_parents(C, op->reports, drag->ids.first, par, PAR_OBJECT);
+ parent_drop_set_parents(C, op->reports, drag->ids.first, par, PAR_OBJECT, event->alt);
return OPERATOR_FINISHED;
}
@@ -407,7 +411,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OUTLINER_OT_parent_drop(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Drop to Set Parent";
+ ot->name = "Drop to Set Parent [+Alt keeps transforms]";
ot->description = "Drag to parent in Outliner";
ot->idname = "OUTLINER_OT_parent_drop";
@@ -425,7 +429,7 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
static bool parent_clear_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
@@ -476,11 +480,11 @@ static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEven
ListBase *lb = event->customdata;
wmDrag *drag = lb->first;
- for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) {
+ LISTBASE_FOREACH (wmDragID *, drag_id, &drag->ids) {
if (GS(drag_id->id->name) == ID_OB) {
Object *object = (Object *)drag_id->id;
- ED_object_parent_clear(object, 0);
+ ED_object_parent_clear(object, event->alt ? CLEAR_PARENT_KEEP_TRANSFORM : CLEAR_PARENT_ALL);
}
}
@@ -493,7 +497,7 @@ static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEven
void OUTLINER_OT_parent_clear(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Drop to Clear Parent";
+ ot->name = "Drop to Clear Parent [+Alt keeps transforms]";
ot->description = "Drag to clear parent in Outliner";
ot->idname = "OUTLINER_OT_parent_clear";
@@ -511,7 +515,7 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot)
static bool scene_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
/* Ensure item under cursor is valid drop target */
Object *ob = (Object *)WM_drag_ID(drag, ID_OB);
@@ -543,8 +547,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
BKE_collection_object_add(bmain, collection, ob);
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer;
- view_layer = view_layer->next) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (base) {
ED_object_base_select(base, BA_SELECT);
@@ -580,7 +583,7 @@ void OUTLINER_OT_scene_drop(wmOperatorType *ot)
static bool material_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
/* Ensure item under cursor is valid drop target */
Material *ma = (Material *)WM_drag_ID(drag, ID_MA);
@@ -602,7 +605,7 @@ static int material_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
return OPERATOR_CANCELLED;
}
- assign_material(bmain, ob, ma, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
+ BKE_object_material_assign(bmain, ob, ma, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
@@ -672,6 +675,10 @@ static bool collection_drop_init(bContext *C,
if (ID_IS_LINKED(to_collection)) {
return false;
}
+ /* Currently this should not be allowed (might be supported in the future though...). */
+ if (ID_IS_OVERRIDE_LIBRARY(to_collection)) {
+ return false;
+ }
/* Get drag datablocks. */
if (drag->type != WM_DRAG_ID) {
@@ -716,10 +723,10 @@ static bool collection_drop_init(bContext *C,
static bool collection_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **tooltip)
+ const char **r_tooltip)
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bool changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false);
CollectionDrop data;
@@ -729,7 +736,7 @@ static bool collection_drop_poll(bContext *C,
if (!data.from || event->ctrl) {
tselem->flag |= TSE_DRAG_INTO;
changed = true;
- *tooltip = TIP_("Link inside Collection");
+ *r_tooltip = TIP_("Link inside Collection");
}
else {
switch (data.insert_type) {
@@ -737,37 +744,37 @@ static bool collection_drop_poll(bContext *C,
tselem->flag |= TSE_DRAG_BEFORE;
changed = true;
if (te->prev && outliner_is_collection_tree_element(te->prev)) {
- *tooltip = TIP_("Move between collections");
+ *r_tooltip = TIP_("Move between collections");
}
else {
- *tooltip = TIP_("Move before collection");
+ *r_tooltip = TIP_("Move before collection");
}
break;
case TE_INSERT_AFTER:
tselem->flag |= TSE_DRAG_AFTER;
changed = true;
if (te->next && outliner_is_collection_tree_element(te->next)) {
- *tooltip = TIP_("Move between collections");
+ *r_tooltip = TIP_("Move between collections");
}
else {
- *tooltip = TIP_("Move after collection");
+ *r_tooltip = TIP_("Move after collection");
}
break;
case TE_INSERT_INTO:
tselem->flag |= TSE_DRAG_INTO;
changed = true;
- *tooltip = TIP_("Move inside collection (Ctrl to link, Shift to parent)");
+ *r_tooltip = TIP_("Move inside collection (Ctrl to link, Shift to parent)");
break;
}
}
if (changed) {
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
return true;
}
else {
if (changed) {
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
return false;
}
@@ -812,7 +819,7 @@ static int collection_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmE
TREESTORE(data.te)->flag &= ~TSE_CLOSED;
}
- for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) {
+ LISTBASE_FOREACH (wmDragID *, drag_id, &drag->ids) {
/* Ctrl enables linking, so we don't need a from collection then. */
Collection *from = (event->ctrl) ? NULL : collection_parent_from_ID(drag_id->from_parent);
@@ -867,12 +874,12 @@ void OUTLINER_OT_collection_drop(wmOperatorType *ot)
/* ********************* Outliner Drag Operator ******************** */
static TreeElement *outliner_item_drag_element_find(SpaceOutliner *soops,
- ARegion *ar,
+ ARegion *region,
const wmEvent *event)
{
/* note: using EVT_TWEAK_ events to trigger dragging is fine,
* it sends coordinates from where dragging was started */
- const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
+ const float my = UI_view2d_region_to_view_y(&region->v2d, event->mval[1]);
return outliner_find_item_at_y(soops, &soops->tree, my);
}
@@ -880,9 +887,9 @@ static int outliner_item_drag_drop_invoke(bContext *C,
wmOperator *UNUSED(op),
const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te = outliner_item_drag_element_find(soops, ar, event);
+ TreeElement *te = outliner_item_drag_element_find(soops, region, event);
if (!te) {
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
@@ -894,7 +901,8 @@ static int outliner_item_drag_drop_invoke(bContext *C,
}
float view_mval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
@@ -978,6 +986,8 @@ static int outliner_item_drag_drop_invoke(bContext *C,
WM_drag_add_ID(drag, data.drag_id, data.drag_parent);
}
+ ED_outliner_select_sync_from_all_tag(C);
+
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index a341be5bf65..13cbda5aad7 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -24,21 +24,21 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_collection_types.h"
-#include "DNA_gpencil_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_gpencil_modifier_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_light_types.h"
#include "DNA_lightprobe_types.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_object_force_types.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_mempool.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
-#include "BLI_mempool.h"
#include "BLT_translation.h"
@@ -46,8 +46,9 @@
#include "BKE_deform.h"
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
-#include "BKE_idcode.h"
+#include "BKE_idtype.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -90,7 +91,7 @@ static void outliner_tree_dimensions_impl(SpaceOutliner *soops,
int *width,
int *height)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
*width = MAX2(*width, te->xend);
if (height != NULL) {
*height += UI_UNIT_Y;
@@ -386,8 +387,7 @@ static void outliner_collection_set_flag_recursive(Scene *scene,
if (base_or_object_prop) {
/* Note: We can't use BKE_collection_object_cache_get()
* otherwise we would not take collection exclusion into account. */
- for (CollectionObject *cob = layer_collection->collection->gobject.first; cob;
- cob = cob->next) {
+ LISTBASE_FOREACH (CollectionObject *, cob, &layer_collection->collection->gobject) {
outliner_base_or_object_pointer_create(view_layer, collection, cob->ob, &ptr);
RNA_property_boolean_set(&ptr, base_or_object_prop, value);
@@ -400,7 +400,7 @@ static void outliner_collection_set_flag_recursive(Scene *scene,
/* Keep going recursively. */
ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children);
- for (Link *link = lb->first; link; link = link->next) {
+ LISTBASE_FOREACH (Link *, link, lb) {
LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : NULL;
Collection *collection_iter = layer_collection ?
(collection ? layer_collection_iter->collection : NULL) :
@@ -466,7 +466,7 @@ static bool outliner_collection_is_isolated(Scene *scene,
/* Keep going recursively. */
ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children);
- for (Link *link = lb->first; link; link = link->next) {
+ LISTBASE_FOREACH (Link *, link, lb) {
LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : NULL;
Collection *collection_iter = layer_collection ?
(collection ? layer_collection_iter->collection : NULL) :
@@ -541,8 +541,7 @@ void outliner_collection_isolate_flag(Scene *scene,
/* Make this collection direct parents also "visible". */
if (layer_collection) {
LayerCollection *lc_parent = layer_collection;
- for (LayerCollection *lc_iter = top_layer_collection->layer_collections.first; lc_iter;
- lc_iter = lc_iter->next) {
+ LISTBASE_FOREACH (LayerCollection *, lc_iter, &top_layer_collection->layer_collections) {
if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) {
lc_parent = lc_iter;
break;
@@ -554,8 +553,7 @@ void outliner_collection_isolate_flag(Scene *scene,
scene, lc_parent, collection ? lc_parent->collection : NULL, &ptr);
RNA_property_boolean_set(&ptr, layer_or_collection_prop, !is_hide);
- for (LayerCollection *lc_iter = lc_parent->layer_collections.first; lc_iter;
- lc_iter = lc_iter->next) {
+ LISTBASE_FOREACH (LayerCollection *, lc_iter, &lc_parent->layer_collections) {
if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) {
lc_parent = lc_iter;
break;
@@ -740,7 +738,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
else {
switch (tselem->type) {
case TSE_DEFGROUP:
- defgroup_unique_name(te->directdata, (Object *)tselem->id); // id = object
+ BKE_object_defgroup_unique_name(te->directdata, (Object *)tselem->id); // id = object
break;
case TSE_NLA_ACTION:
BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
@@ -816,7 +814,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
bGPDlayer *gpl = te->directdata;
/* always make layer active */
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
// XXX: name needs translation stuff
BLI_uniquename(
@@ -986,7 +984,7 @@ static bool outliner_restrict_properties_collection_set(Scene *scene,
static void outliner_draw_restrictbuts(uiBlock *block,
Scene *scene,
ViewLayer *view_layer,
- ARegion *ar,
+ ARegion *region,
SpaceOutliner *soops,
ListBase *lb,
RestrictPropertiesActive props_active_parent)
@@ -1053,11 +1051,11 @@ static void outliner_draw_restrictbuts(uiBlock *block,
/* Create buttons. */
uiBut *bt;
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
RestrictPropertiesActive props_active = props_active_parent;
- if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+ if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) {
if (tselem->type == TSE_R_LAYER && (soops->outlinevis == SO_SCENES)) {
if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
/* View layer render toggle. */
@@ -1068,7 +1066,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
VIEW_LAYER_RENDER,
0,
ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ (int)(region->v2d.cur.xmax - restrict_offsets.render),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1102,7 +1100,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.hide),
+ (int)(region->v2d.cur.xmax - restrict_offsets.hide),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1129,7 +1127,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ (int)(region->v2d.cur.xmax - restrict_offsets.select),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1154,7 +1152,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1179,7 +1177,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ (int)(region->v2d.cur.xmax - restrict_offsets.render),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1210,7 +1208,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.hide),
+ (int)(region->v2d.cur.xmax - restrict_offsets.hide),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1239,7 +1237,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1262,7 +1260,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ (int)(region->v2d.cur.xmax - restrict_offsets.render),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1291,7 +1289,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
BONE_HIDDEN_P,
0,
ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1312,7 +1310,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
BONE_UNSELECTABLE,
0,
ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ (int)(region->v2d.cur.xmax - restrict_offsets.select),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1336,7 +1334,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
BONE_HIDDEN_A,
0,
ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1357,7 +1355,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
BONE_UNSELECTABLE,
0,
ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ (int)(region->v2d.cur.xmax - restrict_offsets.select),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1382,7 +1380,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
GP_LAYER_HIDE,
0,
ICON_HIDE_OFF,
- (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1403,7 +1401,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
GP_LAYER_LOCKED,
0,
ICON_UNLOCKED,
- (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ (int)(region->v2d.cur.xmax - restrict_offsets.select),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1435,7 +1433,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.hide),
+ (int)(region->v2d.cur.xmax - restrict_offsets.hide),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1464,7 +1462,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.holdout),
+ (int)(region->v2d.cur.xmax - restrict_offsets.holdout),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1494,7 +1492,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.indirect_only),
+ (int)(region->v2d.cur.xmax - restrict_offsets.indirect_only),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1526,7 +1524,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1563,7 +1561,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ (int)(region->v2d.cur.xmax - restrict_offsets.render),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1598,7 +1596,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ (int)(region->v2d.cur.xmax - restrict_offsets.select),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1638,17 +1636,21 @@ static void outliner_draw_restrictbuts(uiBlock *block,
}
if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree, props_active);
+ outliner_draw_restrictbuts(
+ block, scene, view_layer, region, soops, &te->subtree, props_active);
}
}
}
-static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *soops, ListBase *lb)
+static void outliner_draw_userbuts(uiBlock *block,
+ ARegion *region,
+ SpaceOutliner *soops,
+ ListBase *lb)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
- if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+ if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) {
if (tselem->type == 0) {
uiBut *bt;
ID *id = tselem->id;
@@ -1666,7 +1668,7 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
UI_BTYPE_BUT,
1,
buf,
- (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
+ (int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1691,7 +1693,7 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
LIB_FAKEUSER,
1,
icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS),
+ (int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1709,7 +1711,7 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
LIB_FAKEUSER,
1,
(id->flag & LIB_FAKEUSER) ? "F" : " ",
- (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_FAKEUSER),
+ (int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_FAKEUSER),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1726,14 +1728,14 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
}
if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_userbuts(block, ar, soops, &te->subtree);
+ outliner_draw_userbuts(block, region, soops, &te->subtree);
}
}
}
-static void outliner_draw_rnacols(ARegion *ar, int sizex)
+static void outliner_draw_rnacols(ARegion *region, int sizex)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
float miny = v2d->cur.ymin;
if (miny < v2d->tot.ymin) {
@@ -1760,14 +1762,14 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
}
static void outliner_draw_rnabuts(
- uiBlock *block, ARegion *ar, SpaceOutliner *soops, int sizex, ListBase *lb)
+ uiBlock *block, ARegion *region, SpaceOutliner *soops, int sizex, ListBase *lb)
{
PointerRNA *ptr;
PropertyRNA *prop;
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
- if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
+ if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) {
if (tselem->type == TSE_RNA_PROPERTY) {
ptr = &te->rnaptr;
prop = te->directdata;
@@ -1830,14 +1832,14 @@ static void outliner_draw_rnabuts(
}
if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_rnabuts(block, ar, soops, sizex, &te->subtree);
+ outliner_draw_rnabuts(block, region, soops, sizex, &te->subtree);
}
}
}
static void outliner_buttons(const bContext *C,
uiBlock *block,
- ARegion *ar,
+ ARegion *region,
const float restrict_column_width,
TreeElement *te)
{
@@ -1871,7 +1873,7 @@ static void outliner_buttons(const bContext *C,
(soops->show_restrict_flags & SO_RESTRICT_ENABLE)) {
spx += UI_UNIT_X;
}
- dx = ar->v2d.cur.xmax - (spx + restrict_column_width + 0.2f * UI_UNIT_X);
+ dx = region->v2d.cur.xmax - (spx + restrict_column_width + 0.2f * UI_UNIT_X);
bt = uiDefBut(block,
UI_BTYPE_TEXT,
@@ -1890,7 +1892,7 @@ static void outliner_buttons(const bContext *C,
UI_but_func_rename_set(bt, namebutton_cb, tselem);
/* returns false if button got removed */
- if (false == UI_but_active_only(C, ar, block, bt)) {
+ if (false == UI_but_active_only(C, region, block, bt)) {
tselem->flag &= ~TSE_TEXTBUT;
/* bad! (notifier within draw) without this, we don't get a refresh */
@@ -2189,6 +2191,9 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case eModifierType_WeightedNormal:
data.icon = ICON_MOD_NORMALEDIT;
break;
+ case eModifierType_Simulation:
+ data.icon = ICON_PHYSICS; /* TODO: Use correct icon. */
+ break;
/* Default */
case eModifierType_None:
case eModifierType_ShapeKey:
@@ -2413,6 +2418,15 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case OB_LIGHTPROBE:
data.icon = ICON_OUTLINER_OB_LIGHTPROBE;
break;
+ case OB_HAIR:
+ data.icon = ICON_OUTLINER_OB_HAIR;
+ break;
+ case OB_POINTCLOUD:
+ data.icon = ICON_OUTLINER_OB_POINTCLOUD;
+ break;
+ case OB_VOLUME:
+ data.icon = ICON_OUTLINER_OB_VOLUME;
+ break;
case OB_EMPTY:
if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
@@ -2510,6 +2524,15 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case ID_GR:
data.icon = ICON_GROUP;
break;
+ case ID_HA:
+ data.icon = ICON_OUTLINER_DATA_HAIR;
+ break;
+ case ID_PT:
+ data.icon = ICON_OUTLINER_DATA_POINTCLOUD;
+ break;
+ case ID_VO:
+ data.icon = ICON_OUTLINER_DATA_VOLUME;
+ break;
case ID_LI:
if (tselem->id->tag & LIB_TAG_MISSING) {
data.icon = ICON_LIBRARY_DATA_BROKEN;
@@ -2561,6 +2584,10 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case ID_PC:
data.icon = ICON_CURVE_BEZCURVE;
break;
+ case ID_SIM:
+ /* TODO: Use correct icon. */
+ data.icon = ICON_PHYSICS;
+ break;
default:
break;
}
@@ -2700,9 +2727,9 @@ static void outliner_draw_iconrow_number(const uiFontStyle *fstyle,
color);
/* Now the numbers. */
- unsigned char text_col[4];
+ uchar text_col[4];
- UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
+ UI_GetThemeColor3ubv(TH_TEXT_HI, text_col);
text_col[3] = 255;
uiFontStyle fstyle_small = *fstyle;
@@ -2804,7 +2831,7 @@ int tree_element_id_type_to_index(TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
- const int id_index = tselem->type == 0 ? BKE_idcode_to_index(te->idcode) : INDEX_ID_GR;
+ const int id_index = tselem->type == 0 ? BKE_idtype_idcode_to_index(te->idcode) : INDEX_ID_GR;
if (id_index < INDEX_ID_OB) {
return id_index;
}
@@ -2838,7 +2865,7 @@ static void outliner_draw_iconrow(bContext *C,
{
eOLDrawState active = OL_DRAWSEL_NONE;
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
/* object hierarchy always, further constrained on level */
@@ -2940,7 +2967,7 @@ static void outliner_draw_tree_element(bContext *C,
uiBlock *block,
const uiFontStyle *fstyle,
const TreeViewContext *tvc,
- ARegion *ar,
+ ARegion *region,
SpaceOutliner *soops,
TreeElement *te,
bool draw_grayed_out,
@@ -2953,17 +2980,17 @@ static void outliner_draw_tree_element(bContext *C,
float ufac = UI_UNIT_X / 20.0f;
int offsx = 0;
eOLDrawState active = OL_DRAWSEL_NONE;
- unsigned char text_color[4];
+ uchar text_color[4];
UI_GetThemeColor4ubv(TH_TEXT, text_color);
float icon_bgcolor[4], icon_border[4];
outliner_icon_background_colors(icon_bgcolor, icon_border);
- if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
+ if (*starty + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && *starty <= region->v2d.cur.ymax) {
const float alpha_fac = ((te->flag & TE_DISABLED) || (te->flag & TE_CHILD_NOT_IN_COLLECTION) ||
draw_grayed_out) ?
0.5f :
1.0f;
- int xmax = ar->v2d.cur.xmax;
+ int xmax = region->v2d.cur.xmax;
if ((tselem->flag & TSE_TEXTBUT) && (*te_edit == NULL)) {
*te_edit = te;
@@ -3181,7 +3208,7 @@ static void outliner_draw_tree_element(bContext *C,
if (TSELEM_OPEN(tselem, soops)) {
*starty -= UI_UNIT_Y;
- for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
+ LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
/* check if element needs to be drawn grayed out, but also gray out
* childs of a grayed out parent (pass on draw_grayed_out to childs) */
bool draw_childs_grayed_out = draw_grayed_out || (ten->flag & TE_DRAGGING);
@@ -3189,7 +3216,7 @@ static void outliner_draw_tree_element(bContext *C,
block,
fstyle,
tvc,
- ar,
+ region,
soops,
ten,
draw_childs_grayed_out,
@@ -3200,7 +3227,7 @@ static void outliner_draw_tree_element(bContext *C,
}
}
else {
- for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
+ LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
outliner_set_coord_tree_element(ten, startx, *starty);
}
@@ -3208,11 +3235,11 @@ static void outliner_draw_tree_element(bContext *C,
}
}
-static void outliner_draw_hierarchy_lines_recursive(unsigned pos,
+static void outliner_draw_hierarchy_lines_recursive(uint pos,
SpaceOutliner *soops,
ListBase *lb,
int startx,
- const unsigned char col[4],
+ const uchar col[4],
bool draw_grayed_out,
int *starty)
{
@@ -3234,7 +3261,7 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos,
dash.step_len = UI_UNIT_X / dash.steps_num;
dash.gap_len = dash.step_len / 2;
- const unsigned char grayed_alpha = col[3] / 2;
+ const uchar grayed_alpha = col[3] / 2;
/* For vertical lines between objects. */
y1 = y2 = y1_dashed = y2_dashed = *starty;
@@ -3316,7 +3343,7 @@ static void outliner_draw_hierarchy_lines(SpaceOutliner *soops,
{
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- unsigned char col[4];
+ uchar col[4];
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col);
@@ -3329,12 +3356,12 @@ static void outliner_draw_hierarchy_lines(SpaceOutliner *soops,
immUnbindProgram();
}
-static void outliner_draw_struct_marks(ARegion *ar,
+static void outliner_draw_struct_marks(ARegion *region,
SpaceOutliner *soops,
ListBase *lb,
int *starty)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
/* selection status */
@@ -3344,14 +3371,14 @@ static void outliner_draw_struct_marks(ARegion *ar,
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immThemeColorShadeAlpha(TH_BACK, -15, -200);
- immRecti(pos, 0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
+ immRecti(pos, 0, *starty + 1, (int)region->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
immUnbindProgram();
}
}
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
+ outliner_draw_struct_marks(region, soops, &te->subtree, starty);
if (tselem->type == TSE_RNA_STRUCT) {
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -3360,7 +3387,7 @@ static void outliner_draw_struct_marks(ARegion *ar,
immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, 0, (float)*starty + UI_UNIT_Y);
- immVertex2f(pos, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
+ immVertex2f(pos, region->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
immEnd();
immUnbindProgram();
@@ -3369,8 +3396,8 @@ static void outliner_draw_struct_marks(ARegion *ar,
}
}
-static void outliner_draw_highlights_recursive(unsigned pos,
- const ARegion *ar,
+static void outliner_draw_highlights_recursive(uint pos,
+ const ARegion *region,
const SpaceOutliner *soops,
const ListBase *lb,
const float col_selection[4],
@@ -3383,23 +3410,23 @@ static void outliner_draw_highlights_recursive(unsigned pos,
const bool is_searching = (SEARCHING_OUTLINER(soops) ||
(soops->outlinevis == SO_DATA_API && soops->search_string[0] != 0));
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
const TreeStoreElem *tselem = TREESTORE(te);
const int start_y = *io_start_y;
/* selection status */
if ((tselem->flag & TSE_ACTIVE) && (tselem->flag & TSE_SELECTED)) {
immUniformColor4fv(col_active);
- immRecti(pos, 0, start_y, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y);
+ immRecti(pos, 0, start_y, (int)region->v2d.cur.xmax, start_y + UI_UNIT_Y);
}
else if (tselem->flag & TSE_SELECTED) {
immUniformColor4fv(col_selection);
- immRecti(pos, 0, start_y, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y);
+ immRecti(pos, 0, start_y, (int)region->v2d.cur.xmax, start_y + UI_UNIT_Y);
}
/* highlights */
if (tselem->flag & (TSE_DRAG_ANY | TSE_HIGHLIGHTED | TSE_SEARCHMATCH)) {
- const int end_x = (int)ar->v2d.cur.xmax;
+ const int end_x = (int)region->v2d.cur.xmax;
if (tselem->flag & TSE_DRAG_ANY) {
/* drag and drop highlight */
@@ -3442,7 +3469,7 @@ static void outliner_draw_highlights_recursive(unsigned pos,
*io_start_y -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops)) {
outliner_draw_highlights_recursive(pos,
- ar,
+ region,
soops,
&te->subtree,
col_selection,
@@ -3455,7 +3482,10 @@ static void outliner_draw_highlights_recursive(unsigned pos,
}
}
-static void outliner_draw_highlights(ARegion *ar, SpaceOutliner *soops, int startx, int *starty)
+static void outliner_draw_highlights(ARegion *region,
+ SpaceOutliner *soops,
+ int startx,
+ int *starty)
{
const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
float col_selection[4], col_active[4], col_searchmatch[4];
@@ -3472,7 +3502,7 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOutliner *soops, int star
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
outliner_draw_highlights_recursive(pos,
- ar,
+ region,
soops,
&soops->tree,
col_selection,
@@ -3488,7 +3518,7 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOutliner *soops, int star
static void outliner_draw_tree(bContext *C,
uiBlock *block,
const TreeViewContext *tvc,
- ARegion *ar,
+ ARegion *region,
SpaceOutliner *soops,
const float restrict_column_width,
TreeElement **te_edit)
@@ -3501,40 +3531,40 @@ static void outliner_draw_tree(bContext *C,
if (soops->outlinevis == SO_DATA_API) {
/* struct marks */
- starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
- outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
+ starty = (int)region->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
+ outliner_draw_struct_marks(region, soops, &soops->tree, &starty);
}
/* draw highlights before hierarchy */
- starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
+ starty = (int)region->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
- outliner_draw_highlights(ar, soops, startx, &starty);
+ outliner_draw_highlights(region, soops, startx, &starty);
/* set scissor so tree elements or lines can't overlap restriction icons */
float scissor[4] = {0};
if (restrict_column_width > 0.0f) {
- int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)restrict_column_width + 1;
+ int mask_x = BLI_rcti_size_x(&region->v2d.mask) - (int)restrict_column_width + 1;
CLAMP_MIN(mask_x, 0);
GPU_scissor_get_f(scissor);
- GPU_scissor(0, 0, mask_x, ar->winy);
+ GPU_scissor(0, 0, mask_x, region->winy);
}
// gray hierarchy lines
- starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
+ starty = (int)region->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
startx = UI_UNIT_X / 2 - (U.pixelsize + 1) / 2;
outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty);
// items themselves
- starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
+ starty = (int)region->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
- for (TreeElement *te = soops->tree.first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, &soops->tree) {
outliner_draw_tree_element(C,
block,
fstyle,
tvc,
- ar,
+ region,
soops,
te,
(te->flag & TE_DRAGGING) != 0,
@@ -3550,11 +3580,11 @@ static void outliner_draw_tree(bContext *C,
}
}
-static void outliner_back(ARegion *ar)
+static void outliner_back(ARegion *region)
{
int ystart;
- ystart = (int)ar->v2d.tot.ymax;
+ ystart = (int)region->v2d.tot.ymax;
ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
GPUVertFormat *format = immVertexFormat();
@@ -3566,9 +3596,9 @@ static void outliner_back(ARegion *ar)
UI_GetThemeColor4fv(TH_ROW_ALTERNATE, col_alternating);
immUniformThemeColorBlend(TH_BACK, TH_ROW_ALTERNATE, col_alternating[3]);
- const float x1 = 0.0f, x2 = ar->v2d.cur.xmax;
+ const float x1 = 0.0f, x2 = region->v2d.cur.xmax;
float y1 = ystart, y2;
- int tot = (int)floor(ystart - ar->v2d.cur.ymin + 2 * UI_UNIT_Y) / (2 * UI_UNIT_Y);
+ int tot = (int)floor(ystart - region->v2d.cur.ymin + 2 * UI_UNIT_Y) / (2 * UI_UNIT_Y);
if (tot > 0) {
immBegin(GPU_PRIM_TRIS, 6 * tot);
@@ -3603,7 +3633,7 @@ static int outliner_width(SpaceOutliner *soops, int max_tree_width, float restri
}
}
-static void outliner_update_viewable_area(ARegion *ar,
+static void outliner_update_viewable_area(ARegion *region,
SpaceOutliner *soops,
int tree_width,
int tree_height,
@@ -3615,7 +3645,7 @@ static void outliner_update_viewable_area(ARegion *ar,
/* extend size to allow for horizontal scrollbar and extra offset */
sizey += V2D_SCROLL_HEIGHT + OL_Y_OFFSET;
- UI_view2d_totRect_set(&ar->v2d, sizex, sizey);
+ UI_view2d_totRect_set(&region->v2d, sizex, sizey);
}
/* ****************************************************** */
@@ -3624,8 +3654,8 @@ static void outliner_update_viewable_area(ARegion *ar,
void draw_outliner(const bContext *C)
{
Main *mainvar = CTX_data_main(C);
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
SpaceOutliner *soops = CTX_wm_space_outliner(C);
uiBlock *block;
TreeElement *te_edit = NULL;
@@ -3633,7 +3663,7 @@ void draw_outliner(const bContext *C)
TreeViewContext tvc;
outliner_viewcontext_init(C, &tvc);
- outliner_build_tree(mainvar, tvc.scene, tvc.view_layer, soops, ar); // always
+ outliner_build_tree(mainvar, tvc.scene, tvc.view_layer, soops, region); // always
/* If global sync select is dirty, flag other outliners */
if (ED_outliner_select_sync_is_dirty(C)) {
@@ -3653,9 +3683,9 @@ void draw_outliner(const bContext *C)
/* draw outliner stuff (background, hierarchy lines and names) */
const float restrict_column_width = outliner_restrict_columns_width(soops);
- outliner_back(ar);
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- outliner_draw_tree((bContext *)C, block, &tvc, ar, soops, restrict_column_width, &te_edit);
+ outliner_back(region);
+ block = UI_block_begin(C, region, __func__, UI_EMBOSS);
+ outliner_draw_tree((bContext *)C, block, &tvc, region, soops, restrict_column_width, &te_edit);
/* Compute outliner dimensions after it has been drawn. */
int tree_width, tree_height;
@@ -3667,34 +3697,34 @@ void draw_outliner(const bContext *C)
if (soops->outlinevis == SO_DATA_API) {
int buttons_start_x = outliner_data_api_buttons_start_x(tree_width);
/* draw rna buttons */
- outliner_draw_rnacols(ar, buttons_start_x);
+ outliner_draw_rnacols(region, buttons_start_x);
UI_block_emboss_set(block, UI_EMBOSS);
- outliner_draw_rnabuts(block, ar, soops, buttons_start_x, &soops->tree);
+ outliner_draw_rnabuts(block, region, soops, buttons_start_x, &soops->tree);
UI_block_emboss_set(block, UI_EMBOSS_NONE);
}
else if (soops->outlinevis == SO_ID_ORPHANS) {
/* draw user toggle columns */
- outliner_draw_userbuts(block, ar, soops, &soops->tree);
+ outliner_draw_userbuts(block, region, soops, &soops->tree);
}
else if (restrict_column_width > 0.0f) {
/* draw restriction columns */
RestrictPropertiesActive props_active;
memset(&props_active, 1, sizeof(RestrictPropertiesActive));
outliner_draw_restrictbuts(
- block, tvc.scene, tvc.view_layer, ar, soops, &soops->tree, props_active);
+ block, tvc.scene, tvc.view_layer, region, soops, &soops->tree, props_active);
}
UI_block_emboss_set(block, UI_EMBOSS);
/* Draw edit buttons if necessary. */
if (te_edit) {
- outliner_buttons(C, block, ar, restrict_column_width, te_edit);
+ outliner_buttons(C, block, region, restrict_column_width, te_edit);
}
UI_block_end(C, block);
UI_block_draw(C, block);
/* Update total viewable region. */
- outliner_update_viewable_area(ar, soops, tree_width, tree_height, restrict_column_width);
+ outliner_update_viewable_area(region, soops, tree_width, tree_height, restrict_column_width);
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 7b59b056264..97ce9ad549f 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -25,17 +25,17 @@
#include "MEM_guardedalloc.h"
+#include "DNA_ID.h"
#include "DNA_anim_types.h"
#include "DNA_collection_types.h"
-#include "DNA_ID.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
-#include "BLI_utildefines.h"
#include "BLI_path_util.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -44,28 +44,29 @@
#include "BKE_blender_copybuffer.h"
#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_idcode.h"
+#include "BKE_idtype.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_outliner_treehash.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "../blenloader/BLO_readfile.h"
+#include "ED_armature.h"
+#include "ED_keyframing.h"
#include "ED_object.h"
#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
-#include "ED_keyframing.h"
-#include "ED_armature.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -82,9 +83,11 @@
#include "outliner_intern.h"
-/* ************************************************************** */
+/** \} */
-/* Highlight --------------------------------------------------- */
+/* -------------------------------------------------------------------- */
+/** \name Highlight on Cursor Motion Operator
+ * \{ */
static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
@@ -99,11 +102,12 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const
return OPERATOR_PASS_THROUGH;
}
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
float view_mval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
@@ -121,7 +125,7 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const
}
if (changed) {
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
return OPERATOR_PASS_THROUGH;
@@ -138,7 +142,11 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
}
-/* Toggle Open/Closed ------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Open/Closed Operator
+ * \{ */
/* Open or close a tree element, optionally toggling all children recursively */
void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all)
@@ -165,11 +173,12 @@ typedef struct OpenCloseData {
static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
float view_mval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
if (event->type == MOUSEMOVE) {
TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
@@ -182,7 +191,7 @@ static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEv
/* Only toggle openclose on the same level as the first clicked element */
if (te->xs == data->x_location) {
outliner_item_openclose(te, data->open, false);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
@@ -204,13 +213,14 @@ static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEv
static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
const bool toggle_all = RNA_boolean_get(op->ptr, "all");
float view_mval[2];
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
@@ -221,7 +231,7 @@ static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmE
(toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1)));
outliner_item_openclose(te, open, toggle_all);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
/* Only toggle once for single click toggling */
if (event->type == LEFTMOUSE) {
@@ -258,8 +268,10 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", false, "All", "Close or open all items");
}
+/** \} */
+
/* -------------------------------------------------------------------- */
-/** \name Object Mode Enter/Exit
+/** \name Object Mode Enter/Exit Utilities
* \{ */
static void item_object_mode_enter_exit(bContext *C, ReportList *reports, Object *ob, bool enter)
@@ -313,9 +325,11 @@ void item_object_mode_exit_cb(bContext *C,
/** \} */
-/* Rename --------------------------------------------------- */
+/* -------------------------------------------------------------------- */
+/** \name Rename Operator
+ * \{ */
-static void do_item_rename(ARegion *ar,
+static void do_item_rename(ARegion *region,
TreeElement *te,
TreeStoreElem *tselem,
ReportList *reports)
@@ -348,6 +362,12 @@ static void do_item_rename(ARegion *ar,
else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
}
+ else if (ID_IS_LINKED(tselem->id)) {
+ BKE_report(reports, RPT_WARNING, "Cannot edit external library data");
+ }
+ else if (ID_IS_OVERRIDE_LIBRARY(tselem->id)) {
+ BKE_report(reports, RPT_WARNING, "Cannot edit name of an override data-block");
+ }
else if (outliner_is_collection_tree_element(te)) {
Collection *collection = outliner_collection_from_tree_element(te);
@@ -358,9 +378,6 @@ static void do_item_rename(ARegion *ar,
add_textbut = true;
}
}
- else if (ID_IS_LINKED(tselem->id)) {
- BKE_report(reports, RPT_WARNING, "Cannot edit external library data");
- }
else if (te->idcode == ID_LI && ((Library *)tselem->id)->parent) {
BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
}
@@ -370,7 +387,7 @@ static void do_item_rename(ARegion *ar,
if (add_textbut) {
tselem->flag |= TSE_TEXTBUT;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
@@ -382,12 +399,12 @@ void item_rename_cb(bContext *C,
TreeStoreElem *tselem,
void *UNUSED(user_data))
{
- ARegion *ar = CTX_wm_region(C);
- do_item_rename(ar, te, tselem, reports);
+ ARegion *region = CTX_wm_region(C);
+ do_item_rename(region, te, tselem, reports);
}
static void do_outliner_item_rename(ReportList *reports,
- ARegion *ar,
+ ARegion *region,
TreeElement *te,
const float mval[2])
{
@@ -396,18 +413,18 @@ static void do_outliner_item_rename(ReportList *reports,
/* click on name */
if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
- do_item_rename(ar, te, tselem, reports);
+ do_item_rename(region, te, tselem, reports);
}
}
for (te = te->subtree.first; te; te = te->next) {
- do_outliner_item_rename(reports, ar, te, mval);
+ do_outliner_item_rename(reports, region, te, mval);
}
}
static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float fmval[2];
@@ -417,17 +434,17 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even
TreeElement *active_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
if (active_element) {
- do_item_rename(ar, active_element, TREESTORE(active_element), op->reports);
+ do_item_rename(region, active_element, TREESTORE(active_element), op->reports);
}
else {
BKE_report(op->reports, RPT_WARNING, "No active item to rename");
}
}
else {
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
- do_outliner_item_rename(op->reports, ar, te, fmval);
+ do_outliner_item_rename(op->reports, region, te, fmval);
}
}
@@ -445,7 +462,11 @@ void OUTLINER_OT_item_rename(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
}
-/* ID delete --------------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name ID Delete Operator
+ * \{ */
static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeStoreElem *tselem)
{
@@ -470,6 +491,14 @@ static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeSto
id->name);
return;
}
+ else if (te->idcode == ID_WS) {
+ BKE_workspace_id_tag_all_visible(bmain, LIB_TAG_DOIT);
+ if (id->tag & LIB_TAG_DOIT) {
+ BKE_reportf(
+ reports, RPT_WARNING, "Cannot delete currently visible workspace id '%s'", id->name);
+ return;
+ }
+ }
BKE_id_delete(bmain, id);
@@ -521,14 +550,14 @@ static int outliner_id_delete_invoke_do(bContext *C,
static int outliner_id_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float fmval[2];
- BLI_assert(ar && soops);
+ BLI_assert(region && soops);
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
int ret;
@@ -551,7 +580,11 @@ void OUTLINER_OT_id_delete(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
}
-/* ID remap --------------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name ID Remap Operator
+ * \{ */
static int outliner_id_remap_exec(bContext *C, wmOperator *op)
{
@@ -633,16 +666,16 @@ static bool outliner_id_remap_find_tree_element(bContext *C,
static int outliner_id_remap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float fmval[2];
if (!RNA_property_is_set(op->ptr, RNA_struct_find_property(op->ptr, "id_type"))) {
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
outliner_id_remap_find_tree_element(C, op, &soops->tree, fmval[1]);
}
- return WM_operator_props_dialog_popup(C, op, 200, 100);
+ return WM_operator_props_dialog_popup(C, op, 200);
}
static const EnumPropertyItem *outliner_id_itemf(bContext *C,
@@ -724,7 +757,11 @@ void id_remap_cb(bContext *C,
WM_operator_properties_free(&op_props);
}
-/* ID copy/Paste ------------------------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name ID Copy Operator
+ * \{ */
static int outliner_id_copy_tag(SpaceOutliner *soops, ListBase *tree)
{
@@ -767,7 +804,7 @@ static int outliner_id_copy_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
+ BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
BKE_copybuffer_save(bmain, str, op->reports);
BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-block(s)", num_ids);
@@ -789,12 +826,18 @@ void OUTLINER_OT_id_copy(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name ID Paste Operator
+ * \{ */
+
static int outliner_id_paste_exec(bContext *C, wmOperator *op)
{
char str[FILE_MAX];
const short flag = FILE_AUTOSELECT | FILE_ACTIVE_COLLECTION;
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
+ BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, 0);
if (num_pasted == 0) {
@@ -805,6 +848,7 @@ static int outliner_id_paste_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
BKE_reportf(op->reports, RPT_INFO, "%d data-block(s) pasted", num_pasted);
+
return OPERATOR_FINISHED;
}
@@ -822,7 +866,11 @@ void OUTLINER_OT_id_paste(wmOperatorType *ot)
ot->flag = 0;
}
-/* Library relocate/reload --------------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Library Relocate Operator
+ * \{ */
static int lib_relocate(
bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload)
@@ -898,14 +946,14 @@ static int outliner_lib_relocate_invoke_do(
static int outliner_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float fmval[2];
- BLI_assert(ar && soops);
+ BLI_assert(region && soops);
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
int ret;
@@ -946,14 +994,14 @@ void lib_relocate_cb(bContext *C,
static int outliner_lib_reload_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float fmval[2];
- BLI_assert(ar && soops);
+ BLI_assert(region && soops);
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
int ret;
@@ -966,6 +1014,12 @@ static int outliner_lib_reload_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_CANCELLED;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Library Reload Operator
+ * \{ */
+
void OUTLINER_OT_lib_reload(wmOperatorType *ot)
{
ot->name = "Reload Library";
@@ -989,13 +1043,11 @@ void lib_reload_cb(bContext *C,
lib_relocate(C, te, tselem, ot, true);
}
-/* ************************************************************** */
-/* Setting Toggling Operators */
-
-/* =============================================== */
-/* Toggling Utilities (Exported) */
+/** \} */
-/* Apply Settings ------------------------------- */
+/* -------------------------------------------------------------------- */
+/** \name Apply Settings Utilities
+ * \{ */
static int outliner_count_levels(ListBase *lb, const int curlevel)
{
@@ -1077,7 +1129,11 @@ bool outliner_flag_flip(ListBase *lb, short flag)
return changed;
}
-/* Restriction Columns ------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Restriction Column Utility
+ * \{ */
/* same check needed for both object operation and restrict column button func
* return 0 when in edit mode (cannot restrict view or select)
@@ -1103,15 +1159,16 @@ int common_restrict_check(bContext *C, Object *ob)
return 1;
}
-/* =============================================== */
-/* Outliner setting toggles */
+/** \} */
-/* Toggle Expanded (Outliner) ---------------------------------------- */
+/* -------------------------------------------------------------------- */
+/** \name Toggle Expanded (Outliner) Operator
+ * \{ */
static int outliner_toggle_expanded_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
if (outliner_flag_is_any_test(&soops->tree, TSE_CLOSED, 1)) {
outliner_flag_set(&soops->tree, TSE_CLOSED, 0);
@@ -1120,7 +1177,7 @@ static int outliner_toggle_expanded_exec(bContext *C, wmOperator *UNUSED(op))
outliner_flag_set(&soops->tree, TSE_CLOSED, 1);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -1139,12 +1196,16 @@ void OUTLINER_OT_expanded_toggle(wmOperatorType *ot)
/* no undo or registry, UI option */
}
-/* Toggle Selected (Outliner) ---------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Selected (Outliner) Operator
+ * \{ */
static int outliner_select_all_exec(bContext *C, wmOperator *op)
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
int action = RNA_enum_get(op->ptr, "action");
if (action == SEL_TOGGLE) {
@@ -1163,13 +1224,11 @@ static int outliner_select_all_exec(bContext *C, wmOperator *op)
break;
}
- if (soops->flag & SO_SYNC_SELECT) {
- ED_outliner_select_sync_from_outliner(C, soops);
- }
+ ED_outliner_select_sync_from_outliner(C, soops);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
return OPERATOR_FINISHED;
}
@@ -1191,10 +1250,11 @@ void OUTLINER_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-/* ************************************************************** */
-/* Hotkey Only Operators */
+/** \} */
-/* Show Active --------------------------------------------------- */
+/* -------------------------------------------------------------------- */
+/** \name View Show Active (Outliner) Operator
+ * \{ */
static void outliner_set_coordinates_element_recursive(SpaceOutliner *soops,
TreeElement *te,
@@ -1217,10 +1277,10 @@ static void outliner_set_coordinates_element_recursive(SpaceOutliner *soops,
}
/* to retrieve coordinates with redrawing the entire tree */
-void outliner_set_coordinates(ARegion *ar, SpaceOutliner *soops)
+void outliner_set_coordinates(ARegion *region, SpaceOutliner *soops)
{
TreeElement *te;
- int starty = (int)(ar->v2d.tot.ymax) - UI_UNIT_Y;
+ int starty = (int)(region->v2d.tot.ymax) - UI_UNIT_Y;
for (te = soops->tree.first; te; te = te->next) {
outliner_set_coordinates_element_recursive(soops, te, 0, &starty);
@@ -1279,18 +1339,18 @@ static TreeElement *outliner_show_active_get_element(bContext *C,
return te;
}
-static void outliner_show_active(SpaceOutliner *so, ARegion *ar, TreeElement *te, ID *id)
+static void outliner_show_active(SpaceOutliner *so, ARegion *region, TreeElement *te, ID *id)
{
/* open up tree to active object/bone */
if (TREESTORE(te)->id == id) {
if (outliner_open_back(te)) {
- outliner_set_coordinates(ar, so);
+ outliner_set_coordinates(region, so);
}
return;
}
- for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
- outliner_show_active(so, ar, ten, id);
+ LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
+ outliner_show_active(so, region, ten, id);
}
}
@@ -1298,8 +1358,8 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceOutliner *so = CTX_wm_space_outliner(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ View2D *v2d = &region->v2d;
TreeElement *active_element = outliner_show_active_get_element(C, so, view_layer);
@@ -1307,26 +1367,26 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
ID *id = TREESTORE(active_element)->id;
/* Expand all elements in the outliner with matching ID */
- for (TreeElement *te = so->tree.first; te; te = te->next) {
- outliner_show_active(so, ar, te, id);
+ LISTBASE_FOREACH (TreeElement *, te, &so->tree) {
+ outliner_show_active(so, region, te, id);
}
/* Also open back from the active_element (only done for the first found occurrence of ID
* though). */
- outliner_show_active(so, ar, active_element, id);
+ outliner_show_active(so, region, active_element, id);
/* Center view on first element found */
int size_y = BLI_rcti_size_y(&v2d->mask) + 1;
int ytop = (active_element->ys + (size_y / 2));
int delta_y = ytop - v2d->cur.ymax;
- outliner_scroll_view(ar, delta_y);
+ outliner_scroll_view(region, delta_y);
}
else {
return OPERATOR_CANCELLED;
}
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
return OPERATOR_FINISHED;
}
@@ -1344,12 +1404,16 @@ void OUTLINER_OT_show_active(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
}
-/* View Panning --------------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Panning (Outliner) Operator
+ * \{ */
static int outliner_scroll_page_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- int size_y = BLI_rcti_size_y(&ar->v2d.mask) + 1;
+ ARegion *region = CTX_wm_region(C);
+ int size_y = BLI_rcti_size_y(&region->v2d.mask) + 1;
bool up = RNA_boolean_get(op->ptr, "up");
@@ -1357,9 +1421,9 @@ static int outliner_scroll_page_exec(bContext *C, wmOperator *op)
size_y = -size_y;
}
- outliner_scroll_view(ar, size_y);
+ outliner_scroll_view(region, size_y);
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
return OPERATOR_FINISHED;
}
@@ -1382,10 +1446,14 @@ void OUTLINER_OT_scroll_page(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* Search ------------------------------------------------------- */
-// TODO: probably obsolete now with filtering?
+/** \} */
+
+#if 0 // TODO: probably obsolete now with filtering?
+
+/* -------------------------------------------------------------------- */
+/** \name Search
+ * \{ */
-#if 0
/* find next element that has this name */
static TreeElement *outliner_find_name(
@@ -1422,7 +1490,7 @@ static TreeElement *outliner_find_name(
}
static void outliner_find_panel(
- Scene *UNUSED(scene), ARegion *ar, SpaceOutliner *soops, int again, int flags)
+ Scene *UNUSED(scene), ARegion *region, SpaceOutliner *soops, int again, int flags)
{
ReportList *reports = NULL; // CTX_wm_reports(C);
TreeElement *te = NULL;
@@ -1463,7 +1531,7 @@ static void outliner_find_panel(
if (tselem) {
/* expand branches so that it will be visible, we need to get correct coordinates */
if (outliner_open_back(soops, te)) {
- outliner_set_coordinates(ar, soops);
+ outliner_set_coordinates(region, soops);
}
/* deselect all visible, and select found element */
@@ -1471,17 +1539,17 @@ static void outliner_find_panel(
tselem->flag |= TSE_SELECTED;
/* make te->ys center of view */
- ytop = (int)(te->ys + BLI_rctf_size_y(&ar->v2d.mask) / 2);
+ ytop = (int)(te->ys + BLI_rctf_size_y(&region->v2d.mask) / 2);
if (ytop > 0) {
ytop = 0;
}
- ar->v2d.cur.ymax = (float)ytop;
- ar->v2d.cur.ymin = (float)(ytop - BLI_rctf_size_y(&ar->v2d.mask));
+ region->v2d.cur.ymax = (float)ytop;
+ region->v2d.cur.ymin = (float)(ytop - BLI_rctf_size_y(&region->v2d.mask));
/* make te->xs ==> te->xend center of view */
- xdelta = (int)(te->xs - ar->v2d.cur.xmin);
- ar->v2d.cur.xmin += xdelta;
- ar->v2d.cur.xmax += xdelta;
+ xdelta = (int)(te->xs - region->v2d.cur.xmin);
+ region->v2d.cur.xmin += xdelta;
+ region->v2d.cur.xmax += xdelta;
/* store selection */
soops->search_tse = *tselem;
@@ -1490,7 +1558,7 @@ static void outliner_find_panel(
soops->search_flags = flags;
/* redraw */
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
}
else {
@@ -1498,9 +1566,14 @@ static void outliner_find_panel(
BKE_reportf(reports, RPT_WARNING, "Not found: %s", name);
}
}
-#endif
-/* Show One Level ----------------------------------------------- */
+/** \} */
+
+#endif /* if 0 */
+
+/* -------------------------------------------------------------------- */
+/** \name Show One Level Operator
+ * \{ */
/* helper function for Show/Hide one level operator */
static void outliner_openclose_level(ListBase *lb, int curlevel, int level, int open)
@@ -1529,7 +1602,7 @@ static void outliner_openclose_level(ListBase *lb, int curlevel, int level, int
static int outliner_one_level_exec(bContext *C, wmOperator *op)
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
const bool add = RNA_boolean_get(op->ptr, "open");
int level;
@@ -1548,7 +1621,7 @@ static int outliner_one_level_exec(bContext *C, wmOperator *op)
}
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -1573,7 +1646,11 @@ void OUTLINER_OT_show_one_level(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* Show Hierarchy ----------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Show Hierarchy Operator
+ * \{ */
/* Helper function for tree_element_shwo_hierarchy() -
* recursively checks whether subtrees have any objects. */
@@ -1640,13 +1717,13 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOutliner *soops, List
static int outliner_show_hierarchy_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
/* recursively open/close levels */
tree_element_show_hierarchy(scene, soops, &soops->tree);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
@@ -1665,15 +1742,19 @@ void OUTLINER_OT_show_hierarchy(wmOperatorType *ot)
/* no undo or registry, UI option */
}
-/* ************************************************************** */
-/* ANIMATO OPERATIONS */
-/* KeyingSet and Driver Creation - Helper functions */
+/** \} */
-/* specialized poll callback for these operators to work in Datablocks view only */
+/* -------------------------------------------------------------------- */
+/** \name Animation Internal Utilities
+ * \{ */
+
+/**
+ * Specialized poll callback for these operators to work in data-blocks view only.
+ */
static bool ed_operator_outliner_datablocks_active(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
+ ScrArea *area = CTX_wm_area(C);
+ if ((area) && (area->spacetype == SPACE_OUTLINER)) {
SpaceOutliner *so = CTX_wm_space_outliner(C);
return (so->outlinevis == SO_DATA_API);
}
@@ -1791,7 +1872,7 @@ static void tree_element_to_path(TreeElement *te,
/* ptr->data not ptr->owner_id seems to be the one we want,
* since ptr->data is sometimes the owner of this ID? */
if (RNA_struct_is_ID(ptr->type)) {
- *id = (ID *)ptr->data;
+ *id = ptr->data;
/* clear path */
if (*path) {
@@ -1831,19 +1912,23 @@ static void tree_element_to_path(TreeElement *te,
BLI_freelistN(&hierarchy);
}
-/* =============================================== */
-/* Driver Operations */
+/** \} */
-/* These operators are only available in databrowser mode for now, as
- * they depend on having RNA paths and/or hierarchies available.
+/* -------------------------------------------------------------------- */
+/** \name Driver Internal Utilities
+ * \{ */
+
+/**
+ * Driver Operations
+ *
+ * These operators are only available in data-browser mode for now,
+ * as they depend on having RNA paths and/or hierarchies available.
*/
enum {
DRIVERS_EDITMODE_ADD = 0,
DRIVERS_EDITMODE_REMOVE,
} /*eDrivers_EditModes*/;
-/* Utilities ---------------------------------- */
-
/* Recursively iterate over tree, finding and working on selected items */
static void do_outliner_drivers_editop(SpaceOutliner *soops,
ListBase *tree,
@@ -1919,7 +2004,11 @@ static void do_outliner_drivers_editop(SpaceOutliner *soops,
}
}
-/* Add Operator ---------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Driver Add Operator
+ * \{ */
static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op)
{
@@ -1954,7 +2043,11 @@ void OUTLINER_OT_drivers_add_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Remove Operator ---------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Driver Remove Operator
+ * \{ */
static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op)
{
@@ -1989,10 +2082,16 @@ void OUTLINER_OT_drivers_delete_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* =============================================== */
-/* Keying Set Operations */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Keying-Set Internal Utilities
+ * \{ */
-/* These operators are only available in databrowser mode for now, as
+/**
+ * Keying-Set Operations
+ *
+ * These operators are only available in data-browser mode for now, as
* they depend on having RNA paths and/or hierarchies available.
*/
enum {
@@ -2000,8 +2099,6 @@ enum {
KEYINGSET_EDITMODE_REMOVE,
} /*eKeyingSet_EditModes*/;
-/* Utilities ---------------------------------- */
-
/* find the 'active' KeyingSet, and add if not found (if adding is allowed) */
// TODO: should this be an API func?
static KeyingSet *verify_active_keyingset(Scene *scene, short add)
@@ -2093,7 +2190,11 @@ static void do_outliner_keyingset_editop(SpaceOutliner *soops,
}
}
-/* Add Operator ---------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Keying-Set Add Operator
+ * \{ */
static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op)
{
@@ -2134,7 +2235,11 @@ void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Remove Operator ---------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Keying-Set Remove Operator
+ * \{ */
static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -2171,33 +2276,30 @@ void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ************************************************************** */
-/* ORPHANED DATABLOCKS */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Purge Orphan Data-Blocks Operator
+ * \{ */
static bool ed_operator_outliner_id_orphans_active(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
- if (sa != NULL) {
- if (sa->spacetype == SPACE_TOPBAR) {
- return true;
- }
-
- if (sa->spacetype == SPACE_OUTLINER) {
- SpaceOutliner *so = CTX_wm_space_outliner(C);
- return (so->outlinevis == SO_ID_ORPHANS);
- }
+ ScrArea *area = CTX_wm_area(C);
+ if (area != NULL && area->spacetype == SPACE_OUTLINER) {
+ SpaceOutliner *so = CTX_wm_space_outliner(C);
+ return (so->outlinevis == SO_ID_ORPHANS);
}
- return 0;
+ return true;
}
-/* Purge Orphans Operator --------------------------------------- */
+/** \} */
static void outliner_orphans_purge_tag(ID *id, int *num_tagged)
{
if (id->us == 0) {
id->tag |= LIB_TAG_DOIT;
num_tagged[INDEX_ID_NULL]++;
- num_tagged[BKE_idcode_to_index(GS(id->name))]++;
+ num_tagged[BKE_idtype_idcode_to_index(GS(id->name))]++;
}
else {
id->tag &= ~LIB_TAG_DOIT;
@@ -2218,7 +2320,7 @@ static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEv
RNA_int_set(op->ptr, "num_deleted", num_tagged[INDEX_ID_NULL]);
if (num_tagged[INDEX_ID_NULL] == 0) {
- BKE_report(op->reports, RPT_INFO, "No orphanned data-blocks to purge");
+ BKE_report(op->reports, RPT_INFO, "No orphaned data-blocks to purge");
return OPERATOR_CANCELLED;
}
@@ -2236,7 +2338,7 @@ static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEv
BLI_dynstr_appendf(dyn_str,
"%d %s",
num_tagged[i],
- TIP_(BKE_idcode_to_name_plural(BKE_idcode_from_index(i))));
+ TIP_(BKE_idtype_idcode_to_name_plural(BKE_idtype_idcode_from_index(i))));
}
}
BLI_dynstr_append(dyn_str, TIP_("). Click here to proceed..."));
@@ -2252,7 +2354,7 @@ static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEv
static int outliner_orphans_purge_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
int num_tagged[INDEX_ID_MAX] = {0};
@@ -2265,7 +2367,7 @@ static int outliner_orphans_purge_exec(bContext *C, wmOperator *op)
FOREACH_MAIN_ID_END;
if (num_tagged[INDEX_ID_NULL] == 0) {
- BKE_report(op->reports, RPT_INFO, "No orphanned data-blocks to purge");
+ BKE_report(op->reports, RPT_INFO, "No orphaned data-blocks to purge");
return OPERATOR_CANCELLED;
}
}
@@ -2279,7 +2381,7 @@ static int outliner_orphans_purge_exec(bContext *C, wmOperator *op)
* outliner several mouse events can be handled in one cycle without
* handling notifiers/redraw which leads to deleting the same object twice.
* cleanup tree here to prevent such cases. */
- if ((sa != NULL) && (sa->spacetype == SPACE_OUTLINER)) {
+ if ((area != NULL) && (area->spacetype == SPACE_OUTLINER)) {
outliner_cleanup_tree(soops);
}
@@ -2308,3 +2410,5 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
PropertyRNA *prop = RNA_def_int(ot->srna, "num_deleted", 0, 0, INT_MAX, "", "", 0, INT_MAX);
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
+
+/** \} */
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 8075065e5c2..f2b64bc2a4b 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -49,14 +49,6 @@ typedef enum TreeElementInsertType {
TE_INSERT_INTO,
} TreeElementInsertType;
-/* Use generic walk select after D4771 is committed */
-typedef enum WalkSelectDirection {
- OUTLINER_SELECT_WALK_UP,
- OUTLINER_SELECT_WALK_DOWN,
- OUTLINER_SELECT_WALK_LEFT,
- OUTLINER_SELECT_WALK_RIGHT,
-} WalkSelectDirection;
-
typedef enum TreeTraversalAction {
/* Continue traversal regularly, don't skip children. */
TRAVERSE_CONTINUE = 0,
@@ -113,7 +105,11 @@ typedef struct TreeElementIcon {
ID_PA, \
ID_GD, \
ID_LS, \
- ID_LP) || /* Only in 'blendfile' mode ... :/ */ \
+ ID_LP, \
+ ID_HA, \
+ ID_PT, \
+ ID_VO, \
+ ID_SIM) || /* Only in 'blendfile' mode ... :/ */ \
ELEM(GS((_id)->name), \
ID_SCR, \
ID_WM, \
@@ -198,7 +194,8 @@ typedef enum {
/* is the current element open? if so we also show children */
#define TSELEM_OPEN(telm, sv) \
- ((telm->flag & TSE_CLOSED) == 0 || (SEARCHING_OUTLINER(sv) && (telm->flag & TSE_CHILDSEARCH)))
+ (((telm)->flag & TSE_CLOSED) == 0 || \
+ (SEARCHING_OUTLINER(sv) && ((telm)->flag & TSE_CHILDSEARCH)))
/**
* Container to avoid passing around these variables to many functions.
@@ -229,7 +226,7 @@ void outliner_build_tree(struct Main *mainvar,
struct Scene *scene,
struct ViewLayer *view_layer,
struct SpaceOutliner *soops,
- struct ARegion *ar);
+ struct ARegion *region);
typedef struct IDsSelectedData {
struct ListBase selected_array;
@@ -369,7 +366,7 @@ void item_object_mode_exit_cb(struct bContext *C,
struct TreeStoreElem *tselem,
void *user_data);
-void outliner_set_coordinates(struct ARegion *ar, struct SpaceOutliner *soops);
+void outliner_set_coordinates(struct ARegion *region, struct SpaceOutliner *soops);
void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all);
@@ -434,6 +431,7 @@ void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
void OUTLINER_OT_action_set(struct wmOperatorType *ot);
void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot);
void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_delete(struct wmOperatorType *ot);
/* ---------------------------------------------------------------- */
@@ -445,11 +443,16 @@ void outliner_keymap(struct wmKeyConfig *keyconf);
bool outliner_is_collection_tree_element(const TreeElement *te);
struct Collection *outliner_collection_from_tree_element(const TreeElement *te);
+void outliner_collection_delete(struct bContext *C,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ReportList *reports,
+ bool hierarchy);
void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
void OUTLINER_OT_collection_duplicate_linked(struct wmOperatorType *ot);
void OUTLINER_OT_collection_duplicate(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_delete(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_hierarchy_delete(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
@@ -492,7 +495,7 @@ TreeElement *outliner_find_parent_element(ListBase *lb,
TreeElement *outliner_find_id(struct SpaceOutliner *soops, ListBase *lb, const struct ID *id);
TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan);
TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone);
-struct ID *outliner_search_back(SpaceOutliner *soops, TreeElement *te, short idcode);
+struct ID *outliner_search_back(TreeElement *te, short idcode);
bool outliner_tree_traverse(const SpaceOutliner *soops,
ListBase *tree,
int filter_te_flag,
@@ -502,7 +505,7 @@ bool outliner_tree_traverse(const SpaceOutliner *soops,
float outliner_restrict_columns_width(const struct SpaceOutliner *soops);
TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag);
bool outliner_is_element_visible(const TreeElement *te);
-void outliner_scroll_view(struct ARegion *ar, int delta_y);
+void outliner_scroll_view(struct ARegion *region, int delta_y);
/* outliner_sync.c ---------------------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 9d7efc7fe46..af7d97b6950 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -66,6 +66,7 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_action_set);
WM_operatortype_append(OUTLINER_OT_constraint_operation);
WM_operatortype_append(OUTLINER_OT_modifier_operation);
+ WM_operatortype_append(OUTLINER_OT_delete);
WM_operatortype_append(OUTLINER_OT_show_one_level);
WM_operatortype_append(OUTLINER_OT_show_active);
@@ -93,7 +94,7 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_collection_new);
WM_operatortype_append(OUTLINER_OT_collection_duplicate_linked);
WM_operatortype_append(OUTLINER_OT_collection_duplicate);
- WM_operatortype_append(OUTLINER_OT_collection_delete);
+ WM_operatortype_append(OUTLINER_OT_collection_hierarchy_delete);
WM_operatortype_append(OUTLINER_OT_collection_objects_select);
WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
WM_operatortype_append(OUTLINER_OT_collection_link);
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 51e837db4c2..fa8422573ab 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -27,16 +27,16 @@
#include "DNA_armature_types.h"
#include "DNA_collection_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_light_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_world_types.h"
-#include "DNA_gpencil_types.h"
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BKE_armature.h"
#include "BKE_collection.h"
@@ -308,17 +308,21 @@ static eOLDrawState tree_element_set_active_object(bContext *C,
bool recursive)
{
TreeStoreElem *tselem = TREESTORE(te);
+ TreeStoreElem *parent_tselem = NULL;
Scene *sce;
Base *base;
Object *ob = NULL;
+ TreeElement *te_ob = NULL;
/* if id is not object, we search back */
if (te->idcode == ID_OB) {
ob = (Object *)tselem->id;
}
else {
- ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if (ob == OBACT(view_layer)) {
+ ob = (Object *)outliner_search_back(te, ID_OB);
+
+ /* Don't return when activating children of the previous active object. */
+ if (ob == OBACT(view_layer) && set == OL_SETSEL_NONE) {
return OL_DRAWSEL_NONE;
}
}
@@ -326,7 +330,7 @@ static eOLDrawState tree_element_set_active_object(bContext *C,
return OL_DRAWSEL_NONE;
}
- sce = (Scene *)outliner_search_back(soops, te, ID_SCE);
+ sce = (Scene *)outliner_search_back(te, ID_SCE);
if (sce && scene != sce) {
WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
scene = sce;
@@ -352,14 +356,25 @@ static eOLDrawState tree_element_set_active_object(bContext *C,
}
}
+ te_ob = outliner_find_id(soops, &soops->tree, (ID *)ob);
+ if (te_ob != NULL && te_ob != te) {
+ parent_tselem = TREESTORE(te_ob);
+ }
+
if (base) {
if (set == OL_SETSEL_EXTEND) {
/* swap select */
if (base->flag & BASE_SELECTED) {
ED_object_base_select(base, BA_DESELECT);
+ if (parent_tselem) {
+ parent_tselem->flag &= ~TSE_SELECTED;
+ }
}
else {
ED_object_base_select(base, BA_SELECT);
+ if (parent_tselem) {
+ parent_tselem->flag |= TSE_SELECTED;
+ }
}
}
else {
@@ -375,6 +390,9 @@ static eOLDrawState tree_element_set_active_object(bContext *C,
BKE_view_layer_base_deselect_all(view_layer);
}
ED_object_base_select(base, BA_SELECT);
+ if (parent_tselem) {
+ parent_tselem->flag |= TSE_SELECTED;
+ }
}
if (recursive) {
@@ -398,7 +416,6 @@ static eOLDrawState tree_element_set_active_object(bContext *C,
static eOLDrawState tree_element_active_material(bContext *C,
Scene *UNUSED(scene),
ViewLayer *view_layer,
- SpaceOutliner *soops,
TreeElement *te,
const eOLSetState set)
{
@@ -406,7 +423,7 @@ static eOLDrawState tree_element_active_material(bContext *C,
Object *ob;
/* we search for the object parent */
- ob = (Object *)outliner_search_back(soops, te, ID_OB);
+ ob = (Object *)outliner_search_back(te, ID_OB);
// note: ob->matbits can be NULL when a local object points to a library mesh.
if (ob == NULL || ob != OBACT(view_layer) || ob->matbits == NULL) {
return OL_DRAWSEL_NONE; /* just paranoia */
@@ -454,11 +471,10 @@ static eOLDrawState tree_element_active_material(bContext *C,
static eOLDrawState tree_element_active_camera(bContext *C,
Scene *scene,
ViewLayer *UNUSED(view_layer),
- SpaceOutliner *soops,
TreeElement *te,
const eOLSetState set)
{
- Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
+ Object *ob = (Object *)outliner_search_back(te, ID_OB);
if (set != OL_SETSEL_NONE) {
scene->camera = ob;
@@ -556,7 +572,7 @@ static eOLDrawState tree_element_active_gplayer(bContext *C,
*/
if (set != OL_SETSEL_NONE) {
if (gpl) {
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, gpd);
}
@@ -1026,13 +1042,13 @@ eOLDrawState tree_element_active(bContext *C,
}
break;
case ID_MA:
- return tree_element_active_material(C, tvc->scene, tvc->view_layer, soops, te, set);
+ return tree_element_active_material(C, tvc->scene, tvc->view_layer, te, set);
case ID_WO:
return tree_element_active_world(C, tvc->scene, tvc->view_layer, soops, te, set);
case ID_TXT:
return tree_element_active_text(C, tvc->scene, tvc->view_layer, soops, te, set);
case ID_CA:
- return tree_element_active_camera(C, tvc->scene, tvc->view_layer, soops, te, set);
+ return tree_element_active_camera(C, tvc->scene, tvc->view_layer, te, set);
}
return OL_DRAWSEL_NONE;
}
@@ -1201,7 +1217,7 @@ static void do_outliner_item_activate_tree_element(bContext *C,
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, tvc->scene);
}
else if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
- Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
+ Object *ob = (Object *)outliner_search_back(te, ID_OB);
if ((ob != NULL) && (ob->data == tselem->id)) {
Base *base = BKE_view_layer_base_find(tvc->view_layer, ob);
if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) {
@@ -1247,7 +1263,7 @@ static bool do_outliner_range_select_recursive(ListBase *lb,
TreeElement *cursor,
bool selecting)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
if (selecting) {
@@ -1311,10 +1327,10 @@ static void do_outliner_range_select(bContext *C,
}
static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops,
- const ARegion *ar,
+ const ARegion *region,
float view_co_x)
{
- return (view_co_x > ar->v2d.cur.xmax - outliner_restrict_columns_width(soops));
+ return (view_co_x > region->v2d.cur.xmax - outliner_restrict_columns_width(soops));
}
/**
@@ -1345,15 +1361,15 @@ static int outliner_item_do_activate_from_cursor(bContext *C,
const bool use_range,
const bool deselect_all)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float view_mval[2];
bool changed = false, rebuild_tree = false;
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
- if (outliner_is_co_within_restrict_columns(soops, ar, view_mval[0])) {
+ if (outliner_is_co_within_restrict_columns(soops, region, view_mval[0])) {
return OPERATOR_CANCELLED;
}
@@ -1401,15 +1417,13 @@ static int outliner_item_do_activate_from_cursor(bContext *C,
if (changed) {
if (rebuild_tree) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
else {
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
- if (soops->flag & SO_SYNC_SELECT) {
- ED_outliner_select_sync_from_outliner(C, soops);
- }
+ ED_outliner_select_sync_from_outliner(C, soops);
}
return OPERATOR_FINISHED;
@@ -1479,7 +1493,7 @@ static int outliner_box_select_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
rctf rectf;
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
@@ -1489,19 +1503,17 @@ static int outliner_box_select_exec(bContext *C, wmOperator *op)
}
WM_operator_properties_border_to_rctf(op, &rectf);
- UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf);
+ UI_view2d_region_to_view_rctf(&region->v2d, &rectf, &rectf);
- for (TreeElement *te = soops->tree.first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, &soops->tree) {
outliner_item_box_select(soops, scene, &rectf, te, select);
}
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
- if (soops->flag & SO_SYNC_SELECT) {
- ED_outliner_select_sync_from_outliner(C, soops);
- }
+ ED_outliner_select_sync_from_outliner(C, soops);
return OPERATOR_FINISHED;
}
@@ -1509,11 +1521,12 @@ static int outliner_box_select_exec(bContext *C, wmOperator *op)
static int outliner_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float view_mval[2];
const bool tweak = RNA_boolean_get(op->ptr, "tweak");
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
/* Find element clicked on */
TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
@@ -1636,16 +1649,16 @@ static TreeElement *do_outliner_select_walk(SpaceOutliner *soops,
tselem->flag &= ~TSE_ACTIVE_WALK;
switch (direction) {
- case OUTLINER_SELECT_WALK_UP:
+ case UI_SELECT_WALK_UP:
walk_element = outliner_find_previous_element(soops, walk_element);
break;
- case OUTLINER_SELECT_WALK_DOWN:
+ case UI_SELECT_WALK_DOWN:
walk_element = outliner_find_next_element(soops, walk_element);
break;
- case OUTLINER_SELECT_WALK_LEFT:
+ case UI_SELECT_WALK_LEFT:
outliner_item_openclose(walk_element, false, toggle_all);
break;
- case OUTLINER_SELECT_WALK_RIGHT:
+ case UI_SELECT_WALK_RIGHT:
outliner_item_openclose(walk_element, true, toggle_all);
break;
}
@@ -1700,25 +1713,25 @@ static TreeElement *find_walk_select_start_element(SpaceOutliner *soops, bool *c
}
/* Scroll the outliner when the walk element reaches the top or bottom boundary */
-static void outliner_walk_scroll(ARegion *ar, TreeElement *te)
+static void outliner_walk_scroll(ARegion *region, TreeElement *te)
{
/* Account for the header height */
- int y_max = ar->v2d.cur.ymax - UI_UNIT_Y;
- int y_min = ar->v2d.cur.ymin;
+ int y_max = region->v2d.cur.ymax - UI_UNIT_Y;
+ int y_min = region->v2d.cur.ymin;
/* Scroll if walked position is beyond the border */
if (te->ys > y_max) {
- outliner_scroll_view(ar, te->ys - y_max);
+ outliner_scroll_view(region, te->ys - y_max);
}
else if (te->ys < y_min) {
- outliner_scroll_view(ar, -(y_min - te->ys));
+ outliner_scroll_view(region, -(y_min - te->ys));
}
}
static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
const short direction = RNA_enum_get(op->ptr, "direction");
const bool extend = RNA_boolean_get(op->ptr, "extend");
@@ -1736,26 +1749,16 @@ static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEven
}
/* Scroll outliner to focus on walk element */
- outliner_walk_scroll(ar, walk_element);
+ outliner_walk_scroll(region, walk_element);
- if (soops->flag & SO_SYNC_SELECT) {
- ED_outliner_select_sync_from_outliner(C, soops);
- }
- ED_region_tag_redraw(ar);
+ ED_outliner_select_sync_from_outliner(C, soops);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
void OUTLINER_OT_select_walk(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {OUTLINER_SELECT_WALK_UP, "UP", 0, "Up", ""},
- {OUTLINER_SELECT_WALK_DOWN, "DOWN", 0, "Down", ""},
- {OUTLINER_SELECT_WALK_LEFT, "LEFT", 0, "Left", ""},
- {OUTLINER_SELECT_WALK_RIGHT, "RIGHT", 0, "Right", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
/* identifiers */
ot->name = "Walk Select";
ot->idname = "OUTLINER_OT_select_walk";
@@ -1769,13 +1772,7 @@ void OUTLINER_OT_select_walk(wmOperatorType *ot)
/* properties */
PropertyRNA *prop;
- prop = RNA_def_enum(ot->srna,
- "direction",
- direction_items,
- 0,
- "Walk Direction",
- "Select element in this direction");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ WM_operator_properties_select_walk_direction(ot);
prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection on walk");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(
diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c
index 745a527cc15..852773d3979 100644
--- a/source/blender/editors/space_outliner/outliner_sync.c
+++ b/source/blender/editors/space_outliner/outliner_sync.c
@@ -32,6 +32,7 @@
#include "BLI_compiler_compat.h"
#include "BLI_ghash.h"
+#include "BLI_listbase.h"
#include "BKE_armature.h"
#include "BKE_context.h"
@@ -95,8 +96,8 @@ void ED_outliner_select_sync_flag_outliners(const bContext *C)
wmWindowManager *wm = CTX_wm_manager(C);
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_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype == SPACE_OUTLINER) {
SpaceOutliner *soutliner = (SpaceOutliner *)sl;
@@ -318,7 +319,7 @@ static void outliner_sync_selection_from_outliner(Scene *scene,
SelectedItems *selected_items)
{
- for (TreeElement *te = tree->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, tree) {
TreeStoreElem *tselem = TREESTORE(te);
if (tselem->type == 0 && te->idcode == ID_OB) {
@@ -350,8 +351,9 @@ static void outliner_sync_selection_from_outliner(Scene *scene,
/* Set clean outliner and mark other outliners for syncing */
void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *soops)
{
- /* Don't sync in certain outliner display modes */
- if (ELEM(soops->outlinevis, SO_LIBRARIES, SO_DATA_API, SO_ID_ORPHANS)) {
+ /* Don't sync if not checked or in certain outliner display modes */
+ if (!(soops->flag & SO_SYNC_SELECT) ||
+ ELEM(soops->outlinevis, SO_LIBRARIES, SO_DATA_API, SO_ID_ORPHANS)) {
return;
}
@@ -499,7 +501,7 @@ static void outliner_sync_selection_to_outliner(ViewLayer *view_layer,
SyncSelectActiveData *active_data,
const SyncSelectTypes *sync_types)
{
- for (TreeElement *te = tree->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, tree) {
TreeStoreElem *tselem = TREESTORE(te);
if (tselem->type == 0 && te->idcode == ID_OB) {
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index c9eeb2cff20..0ccf982fd29 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -26,34 +26,39 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_collection_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_hair_types.h"
#include "DNA_light_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
+#include "DNA_volume_types.h"
#include "DNA_world_types.h"
-#include "DNA_object_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_modifier_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_collection.h"
-#include "BKE_context.h"
#include "BKE_constraint.h"
-#include "BKE_object.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
+#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -71,12 +76,12 @@
#include "ED_undo.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "UI_interface.h"
-#include "UI_view2d.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -84,9 +89,9 @@
#include "outliner_intern.h"
-/* ****************************************************** */
-
-/* ************ SELECTION OPERATIONS ********* */
+/* -------------------------------------------------------------------- */
+/** \name ID/Library/Data Set/Un-link Utilities
+ * \{ */
static void set_operation_types(SpaceOutliner *soops,
ListBase *lb,
@@ -153,6 +158,10 @@ static void set_operation_types(SpaceOutliner *soops,
case ID_CF:
case ID_WS:
case ID_LP:
+ case ID_HA:
+ case ID_PT:
+ case ID_VO:
+ case ID_SIM:
is_standard_id = true;
break;
case ID_WM:
@@ -230,6 +239,21 @@ static void unlink_material_cb(bContext *UNUSED(C),
totcol = mb->totcol;
matar = mb->mat;
}
+ else if (GS(tsep->id->name) == ID_HA) {
+ Hair *hair = (Hair *)tsep->id;
+ totcol = hair->totcol;
+ matar = hair->mat;
+ }
+ else if (GS(tsep->id->name) == ID_PT) {
+ PointCloud *pointcloud = (PointCloud *)tsep->id;
+ totcol = pointcloud->totcol;
+ matar = pointcloud->mat;
+ }
+ else if (GS(tsep->id->name) == ID_VO) {
+ Volume *volume = (Volume *)tsep->id;
+ totcol = volume->totcol;
+ matar = volume->mat;
+ }
else {
BLI_assert(0);
}
@@ -390,7 +414,12 @@ static void outliner_do_libdata_operation(bContext *C,
}
}
-/* ******************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Scene Menu Operator
+ * \{ */
+
typedef enum eOutliner_PropSceneOps {
OL_SCENE_OP_DELETE = 1,
} eOutliner_PropSceneOps;
@@ -478,7 +507,12 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_scene_op_types, 0, "Scene Operation", "");
}
-/* ******************************************** */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Search Utilities
+ * \{ */
/**
* Stores the parent and a child element of a merged icon-row icon for
@@ -496,7 +530,7 @@ static void merged_element_search_cb_recursive(
char name[64];
int iconid;
- for (TreeElement *te = tree->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, tree) {
TreeStoreElem *tselem = TREESTORE(te);
if (tree_element_id_type_to_index(te) == type && tselem_type == tselem->type) {
@@ -507,7 +541,7 @@ static void merged_element_search_cb_recursive(
/* Don't allow duplicate named items */
if (UI_search_items_find_index(items, name) == -1) {
- if (!UI_search_item_add(items, name, te, iconid)) {
+ if (!UI_search_item_add(items, name, te, iconid, 0)) {
break;
}
}
@@ -519,10 +553,10 @@ static void merged_element_search_cb_recursive(
}
/* Get a list of elements that match the search string */
-static void merged_element_search_cb(const bContext *UNUSED(C),
- void *data,
- const char *str,
- uiSearchItems *items)
+static void merged_element_search_update_fn(const bContext *UNUSED(C),
+ void *data,
+ const char *str,
+ uiSearchItems *items)
{
MergedSearchData *search_data = (MergedSearchData *)data;
TreeElement *parent = search_data->parent_element;
@@ -534,7 +568,7 @@ static void merged_element_search_cb(const bContext *UNUSED(C),
}
/* Activate an element from the merged element search menu */
-static void merged_element_search_call_cb(struct bContext *C, void *UNUSED(arg1), void *element)
+static void merged_element_search_exec_fn(struct bContext *C, void *UNUSED(arg1), void *element)
{
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te = (TreeElement *)element;
@@ -542,16 +576,14 @@ static void merged_element_search_call_cb(struct bContext *C, void *UNUSED(arg1)
outliner_item_select(soops, te, false, false);
outliner_item_do_activate_from_tree_element(C, te, te->store_elem, false, false);
- if (soops->flag & SO_SYNC_SELECT) {
- ED_outliner_select_sync_from_outliner(C, soops);
- }
+ ED_outliner_select_sync_from_outliner(C, soops);
}
/**
* Merged element search menu
* Created on activation of a merged or aggregated icon-row icon.
*/
-static uiBlock *merged_element_search_menu(bContext *C, ARegion *ar, void *data)
+static uiBlock *merged_element_search_menu(bContext *C, ARegion *region, void *data)
{
static char search[64] = "";
uiBlock *block;
@@ -560,7 +592,7 @@ static uiBlock *merged_element_search_menu(bContext *C, ARegion *ar, void *data)
/* Clear search on each menu creation */
*search = '\0';
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ block = UI_block_begin(C, region, __func__, UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
@@ -568,7 +600,7 @@ static uiBlock *merged_element_search_menu(bContext *C, ARegion *ar, void *data)
but = uiDefSearchBut(
block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, menu_width, UI_UNIT_Y, 0, 0, "");
UI_but_func_search_set(
- but, NULL, merged_element_search_cb, data, false, merged_element_search_call_cb, NULL);
+ but, NULL, merged_element_search_update_fn, data, NULL, merged_element_search_exec_fn, NULL);
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
/* Fake button to hold space for search items */
@@ -621,6 +653,12 @@ static void object_select_cb(bContext *C,
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks (Selection, Users & Library) Utilities
+ * \{ */
+
static void object_select_hierarchy_cb(bContext *C,
ReportList *UNUSED(reports),
Scene *UNUSED(scene),
@@ -651,13 +689,10 @@ static void object_deselect_cb(bContext *C,
}
}
-static void object_delete_cb(bContext *C,
- ReportList *reports,
- Scene *scene,
- TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
- void *UNUSED(user_data))
+static void outliner_object_delete(bContext *C,
+ ReportList *reports,
+ Scene *scene,
+ TreeStoreElem *tselem)
{
Object *ob = (Object *)tselem->id;
if (ob) {
@@ -678,8 +713,8 @@ static void object_delete_cb(bContext *C,
return;
}
- // check also library later
- if ((ob->mode && OB_MODE_EDIT) && BKE_object_is_in_editmode(ob)) {
+ /* Check also library later. */
+ if ((ob->mode & OB_MODE_EDIT) && BKE_object_is_in_editmode(ob)) {
ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
}
BKE_id_delete(bmain, ob);
@@ -698,8 +733,8 @@ static void id_local_cb(bContext *C,
Main *bmain = CTX_data_main(C);
/* if the ID type has no special local function,
* just clear the lib */
- if (id_make_local(bmain, tselem->id, false, false) == false) {
- id_clear_lib_data(bmain, tselem->id);
+ if (BKE_lib_id_make_local(bmain, tselem->id, false, 0) == false) {
+ BKE_lib_id_clear_library_data(bmain, tselem->id);
}
else {
BKE_main_id_clear_newpoins(bmain);
@@ -719,7 +754,7 @@ static void id_override_library_cb(bContext *C,
Main *bmain = CTX_data_main(C);
/* For now, remapp all local usages of linked ID to local override one here. */
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true);
- ID *override_id = BKE_override_library_create_from_id(bmain, tselem->id, true);
+ ID *override_id = BKE_lib_override_library_create_from_id(bmain, tselem->id, true);
if (override_id != NULL) {
BKE_main_id_clear_newpoins(bmain);
}
@@ -832,7 +867,7 @@ void outliner_do_object_operation_ex(bContext *C,
if (tselem->flag & TSE_SELECTED) {
if (tselem->type == 0 && te->idcode == ID_OB) {
// when objects selected in other scenes... dunno if that should be allowed
- Scene *scene_owner = (Scene *)outliner_search_back(soops, te, ID_SCE);
+ Scene *scene_owner = (Scene *)outliner_search_back(te, ID_SCE);
if (scene_owner && scene_act != scene_owner) {
WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), scene_owner);
}
@@ -863,7 +898,11 @@ void outliner_do_object_operation(bContext *C,
outliner_do_object_operation_ex(C, reports, scene_act, soops, lb, operation_cb, NULL, true);
}
-/* ******************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Tagging Utilities
+ * \{ */
static void clear_animdata_cb(int UNUSED(event),
TreeElement *UNUSED(te),
@@ -915,7 +954,11 @@ static void refreshdrivers_animdata_cb(int UNUSED(event),
}
}
-/* --------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Operation Utilities
+ * \{ */
typedef enum eOutliner_PropDataOps {
OL_DOP_SELECT = 1,
@@ -1048,9 +1091,8 @@ static void constraint_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel
{
bContext *C = C_v;
Main *bmain = CTX_data_main(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
bConstraint *constraint = (bConstraint *)te->directdata;
- Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
+ Object *ob = (Object *)outliner_search_back(te, ID_OB);
if (event == OL_CONSTRAINTOP_ENABLE) {
constraint->flag &= ~CONSTRAINT_OFF;
@@ -1089,9 +1131,8 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem
{
bContext *C = (bContext *)Carg;
Main *bmain = CTX_data_main(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
ModifierData *md = (ModifierData *)te->directdata;
- Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
+ Object *ob = (Object *)outliner_search_back(te, ID_OB);
if (event == OL_MODIFIER_OP_TOGVIS) {
md->mode ^= eModifierMode_Realtime;
@@ -1290,13 +1331,16 @@ static void object_batch_delete_hierarchy_cb(bContext *C,
}
}
-/* **************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Menu Operator
+ * \{ */
enum {
OL_OP_SELECT = 1,
OL_OP_DESELECT,
OL_OP_SELECT_HIERARCHY,
- OL_OP_DELETE,
OL_OP_DELETE_HIERARCHY,
OL_OP_REMAP,
OL_OP_LOCALIZED, /* disabled, see below */
@@ -1312,7 +1356,6 @@ static const EnumPropertyItem prop_object_op_types[] = {
{OL_OP_SELECT, "SELECT", ICON_RESTRICT_SELECT_OFF, "Select", ""},
{OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""},
{OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""},
- {OL_OP_DELETE, "DELETE", ICON_X, "Delete", ""},
{OL_OP_DELETE_HIERARCHY, "DELETE_HIERARCHY", 0, "Delete Hierarchy", ""},
{OL_OP_REMAP,
"REMAP",
@@ -1334,6 +1377,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
SpaceOutliner *soops = CTX_wm_space_outliner(C);
int event;
const char *str = NULL;
+ bool selection_changed = false;
/* check for invalid states */
if (soops == NULL) {
@@ -1350,8 +1394,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
}
str = "Select Objects";
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ selection_changed = true;
}
else if (event == OL_OP_SELECT_HIERARCHY) {
Scene *sce = scene; // to be able to delete, scenes are set...
@@ -1361,36 +1404,12 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
WM_window_set_active_scene(bmain, C, win, sce);
}
str = "Select Object Hierarchy";
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ selection_changed = true;
}
else if (event == OL_OP_DESELECT) {
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_deselect_cb);
str = "Deselect Objects";
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (event == OL_OP_DELETE) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const Base *basact_prev = BASACT(view_layer);
-
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_delete_cb);
-
- /* XXX: tree management normally happens from draw_outliner(), but when
- * you're clicking to fast on Delete object from context menu in
- * outliner several mouse events can be handled in one cycle without
- * handling notifiers/redraw which leads to deleting the same object twice.
- * cleanup tree here to prevent such cases. */
- outliner_cleanup_tree(soops);
-
- DEG_relations_tag_update(bmain);
- str = "Delete Objects";
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- if (basact_prev != BASACT(view_layer)) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
- }
+ selection_changed = true;
}
else if (event == OL_OP_DELETE_HIERARCHY) {
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1416,7 +1435,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
BKE_id_multi_tagged_delete(bmain);
}
- /* XXX: See OL_OP_DELETE comment above. */
+ /* XXX: See outliner_delete_exec comment below. */
outliner_cleanup_tree(soops);
DEG_relations_tag_update(bmain);
@@ -1427,6 +1446,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
}
+ selection_changed = true;
}
else if (event == OL_OP_REMAP) {
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
@@ -1455,6 +1475,12 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ if (selection_changed) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
+ }
+
ED_undo_push(C, str);
return OPERATOR_FINISHED;
@@ -1476,7 +1502,85 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_object_op_types, 0, "Object Operation", "");
}
-/* **************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Object/Collection Operator
+ * \{ */
+
+static void outliner_objects_delete(
+ bContext *C, Scene *scene, SpaceOutliner *soops, ReportList *reports, ListBase *lb)
+{
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (tselem->flag & TSE_SELECTED) {
+ if (tselem->type == 0 && te->idcode == ID_OB) {
+ outliner_object_delete(C, reports, scene, tselem);
+ }
+ }
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_objects_delete(C, scene, soops, reports, &te->subtree);
+ }
+ }
+}
+
+static int outliner_delete_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const Base *basact_prev = BASACT(view_layer);
+
+ outliner_collection_delete(C, bmain, scene, op->reports, false);
+ outliner_objects_delete(C, scene, soops, op->reports, &soops->tree);
+
+ /* Tree management normally happens from draw_outliner(), but when
+ * you're clicking too fast on Delete object from context menu in
+ * outliner several mouse events can be handled in one cycle without
+ * handling notifiers/redraw which leads to deleting the same object twice.
+ * cleanup tree here to prevent such cases. */
+ outliner_cleanup_tree(soops);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+
+ if (basact_prev != BASACT(view_layer)) {
+ 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(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete";
+ ot->idname = "OUTLINER_OT_delete";
+ ot->description = "Delete selected objects and collections";
+
+ /* callbacks */
+ ot->exec = outliner_delete_exec;
+ ot->poll = ED_operator_outliner_active;
+
+ /* flags */
+ ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name ID-Data Menu Operator
+ * \{ */
typedef enum eOutlinerIdOpTypes {
OUTLINER_IDOP_INVALID = 0,
@@ -1539,7 +1643,7 @@ static bool outliner_id_operation_item_poll(bContext *C,
switch (enum_value) {
case OUTLINER_IDOP_OVERRIDE_LIBRARY:
- return BKE_override_library_is_enabled();
+ return BKE_lib_override_library_is_enabled();
case OUTLINER_IDOP_SINGLE:
if (!soops || ELEM(soops->outlinevis, SO_SCENES, SO_VIEW_LAYER)) {
return true;
@@ -1652,7 +1756,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
break;
}
case OUTLINER_IDOP_OVERRIDE_LIBRARY: {
- if (BKE_override_library_is_enabled()) {
+ if (BKE_lib_override_library_is_enabled()) {
/* make local */
outliner_do_libdata_operation(
C, op->reports, scene, soops, &soops->tree, id_override_library_cb, NULL);
@@ -1707,6 +1811,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
}
case OUTLINER_IDOP_PASTE: {
WM_operator_name_call(C, "OUTLINER_OT_id_paste", WM_OP_INVOKE_DEFAULT, NULL);
+ ED_outliner_select_sync_from_all_tag(C);
ED_undo_push(C, "Paste");
break;
}
@@ -1740,6 +1845,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
case OUTLINER_IDOP_SELECT_LINKED:
outliner_do_libdata_operation(
C, op->reports, scene, soops, &soops->tree, id_select_linked_cb, NULL);
+ ED_outliner_select_sync_from_all_tag(C);
ED_undo_push(C, "Select");
break;
@@ -1774,7 +1880,11 @@ void OUTLINER_OT_id_operation(wmOperatorType *ot)
RNA_def_enum_funcs(ot->prop, outliner_id_operation_itemf);
}
-/* **************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Library Menu Operator
+ * \{ */
typedef enum eOutlinerLibOpTypes {
OL_LIB_INVALID = 0,
@@ -1875,7 +1985,11 @@ void OUTLINER_OT_lib_operation(wmOperatorType *ot)
ot->srna, "type", outliner_lib_op_type_items, 0, "Library Operation", "");
}
-/* **************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Outliner Set Active Action Operator
+ * \{ */
static void outliner_do_id_set_operation(
SpaceOutliner *soops,
@@ -1901,8 +2015,6 @@ static void outliner_do_id_set_operation(
}
}
-/* ------------------------------------------ */
-
static void actionset_id_cb(TreeElement *UNUSED(te),
TreeStoreElem *tselem,
TreeStoreElem *tsep,
@@ -1926,6 +2038,7 @@ static void actionset_id_cb(TreeElement *UNUSED(te),
static int outliner_action_set_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
@@ -1938,7 +2051,7 @@ static int outliner_action_set_exec(bContext *C, wmOperator *op)
set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
/* get action to use */
- act = BLI_findlink(&CTX_data_main(C)->actions, RNA_enum_get(op->ptr, "action"));
+ act = BLI_findlink(&bmain->actions, RNA_enum_get(op->ptr, "action"));
if (act == NULL) {
BKE_report(op->reports, RPT_ERROR, "No valid action to add");
@@ -1999,7 +2112,11 @@ void OUTLINER_OT_action_set(wmOperatorType *ot)
ot->prop = prop;
}
-/* **************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Animation Menu Operator
+ * \{ */
typedef enum eOutliner_AnimDataOps {
OUTLINER_ANIMOP_INVALID = 0,
@@ -2115,7 +2232,11 @@ void OUTLINER_OT_animdata_operation(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_animdata_op_types, 0, "Animation Operation", "");
}
-/* **************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Constraint Menu Operator
+ * \{ */
static const EnumPropertyItem prop_constraint_op_types[] = {
{OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_HIDE_OFF, "Enable", ""},
@@ -2161,7 +2282,11 @@ void OUTLINER_OT_constraint_operation(wmOperatorType *ot)
ot->srna, "type", prop_constraint_op_types, 0, "Constraint Operation", "");
}
-/* ******************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Modifier Menu Operator
+ * \{ */
static const EnumPropertyItem prop_modifier_op_types[] = {
{OL_MODIFIER_OP_TOGVIS, "TOGVIS", ICON_RESTRICT_VIEW_OFF, "Toggle viewport use", ""},
@@ -2206,7 +2331,11 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_modifier_op_types, 0, "Modifier Operation", "");
}
-/* ******************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Data Menu Operator
+ * \{ */
// XXX: select linked is for RNA structs only
static const EnumPropertyItem prop_data_op_types[] = {
@@ -2299,7 +2428,11 @@ void OUTLINER_OT_data_operation(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_data_op_types, 0, "Data Operation", "");
}
-/* ******************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Context Menu Operator
+ * \{ */
static int outliner_operator_menu(bContext *C, const char *opname)
{
@@ -2311,11 +2444,9 @@ static int outliner_operator_menu(bContext *C, const char *opname)
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
uiItemsEnumO(layout, ot->idname, RNA_property_identifier(ot->prop));
- MenuType *mt = WM_menutype_find("OUTLINER_MT_context", false);
- if (mt) {
- uiItemS(layout);
- UI_menutype_draw(C, mt, layout);
- }
+ uiItemS(layout);
+
+ uiItemMContents(layout, "OUTLINER_MT_context_menu");
UI_popup_menu_end(C, pup);
@@ -2323,7 +2454,7 @@ static int outliner_operator_menu(bContext *C, const char *opname)
}
static int do_outliner_operation_event(
- bContext *C, ARegion *ar, SpaceOutliner *soops, TreeElement *te, const float mval[2])
+ bContext *C, ARegion *region, SpaceOutliner *soops, TreeElement *te, const float mval[2])
{
ReportList *reports = CTX_wm_reports(C); // XXX...
@@ -2342,7 +2473,7 @@ static int do_outliner_operation_event(
/* Only redraw, don't rebuild here because TreeElement pointers will
* become invalid and operations will crash. */
- ED_region_tag_redraw_no_rebuild(ar);
+ ED_region_tag_redraw_no_rebuild(region);
}
set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
@@ -2420,7 +2551,7 @@ static int do_outliner_operation_event(
}
for (te = te->subtree.first; te; te = te->next) {
- int retval = do_outliner_operation_event(C, ar, soops, te, mval);
+ int retval = do_outliner_operation_event(C, region, soops, te, mval);
if (retval) {
return retval;
}
@@ -2431,7 +2562,7 @@ static int do_outliner_operation_event(
static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
uiBut *but = UI_context_active_but_get(C);
TreeElement *te;
@@ -2441,23 +2572,17 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
UI_but_tooltip_timer_remove(C, but);
}
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
- int retval = do_outliner_operation_event(C, ar, soops, te, fmval);
+ int retval = do_outliner_operation_event(C, region, soops, te, fmval);
if (retval) {
return retval;
}
}
- /* Menus for clicking in empty space. */
- if (soops->outlinevis == SO_VIEW_LAYER) {
- WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_FINISHED;
- }
-
- WM_menu_name_call(C, "OUTLINER_MT_context", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_FINISHED;
+ /* Let this fall through to 'OUTLINER_MT_context_menu'. */
+ return OPERATOR_PASS_THROUGH;
}
/* Menu only! Calls other operators */
@@ -2472,4 +2597,4 @@ void OUTLINER_OT_operation(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
}
-/* ****************************************************** */
+/** \} */
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 1bb1a1c5964..7bb62b0d1e2 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -28,37 +28,41 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_camera_types.h"
#include "DNA_cachefile_types.h"
+#include "DNA_camera_types.h"
#include "DNA_collection_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_hair_types.h"
#include "DNA_key_types.h"
#include "DNA_light_types.h"
+#include "DNA_lightprobe_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
-#include "DNA_lightprobe_types.h"
+#include "DNA_object_types.h"
#include "DNA_particle_types.h"
+#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
-#include "DNA_world_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_speaker_types.h"
-#include "DNA_object_types.h"
-#include "DNA_linestyle_types.h"
+#include "DNA_volume_types.h"
+#include "DNA_world_types.h"
#include "BLI_blenlib.h"
+#include "BLI_fnmatch.h"
#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
#include "BLI_mempool.h"
-#include "BLI_fnmatch.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
-#include "BKE_fcurve.h"
-#include "BKE_idcode.h"
+#include "BKE_fcurve_driver.h"
+#include "BKE_idtype.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_outliner_treehash.h"
@@ -750,6 +754,32 @@ static void outliner_add_id_contents(SpaceOutliner *soops,
Collection *collection = (Collection *)id;
outliner_add_collection_recursive(soops, collection, te);
}
+ break;
+ }
+ case ID_HA: {
+ Hair *hair = (Hair *)id;
+ if (outliner_animdata_test(hair->adt))
+ outliner_add_element(soops, &te->subtree, hair, te, TSE_ANIM_DATA, 0);
+ break;
+ }
+ case ID_PT: {
+ PointCloud *pointcloud = (PointCloud *)id;
+ if (outliner_animdata_test(pointcloud->adt))
+ outliner_add_element(soops, &te->subtree, pointcloud, te, TSE_ANIM_DATA, 0);
+ break;
+ }
+ case ID_VO: {
+ Volume *volume = (Volume *)id;
+ if (outliner_animdata_test(volume->adt))
+ outliner_add_element(soops, &te->subtree, volume, te, TSE_ANIM_DATA, 0);
+ break;
+ }
+ case ID_SIM: {
+ Simulation *simulation = (Simulation *)id;
+ if (outliner_animdata_test(simulation->adt)) {
+ outliner_add_element(soops, &te->subtree, simulation, te, TSE_ANIM_DATA, 0);
+ }
+ break;
}
default:
break;
@@ -1215,7 +1245,7 @@ static void outliner_add_seq_dup(SpaceOutliner *soops, Sequence *seq, TreeElemen
static const char *outliner_idcode_to_plural(short idcode)
{
- const char *propname = BKE_idcode_to_name_plural(idcode);
+ const char *propname = BKE_idtype_idcode_to_name_plural(idcode);
PropertyRNA *prop = RNA_struct_type_find_property(&RNA_BlendData, propname);
return (prop) ? RNA_property_ui_name(prop) : "UNKNOWN";
}
@@ -1232,7 +1262,7 @@ static bool outliner_library_id_show(Library *lib, ID *id, short filter_id_type)
Collection *collection = (Collection *)id;
bool has_non_scene_parent = false;
- for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ LISTBASE_FOREACH (CollectionParent *, cparent, &collection->parents) {
if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
has_non_scene_parent = true;
}
@@ -1365,7 +1395,7 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOutliner *soops
static void outliner_add_layer_collection_objects(
SpaceOutliner *soops, ListBase *tree, ViewLayer *layer, LayerCollection *lc, TreeElement *ten)
{
- for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
+ LISTBASE_FOREACH (CollectionObject *, cob, &lc->collection->gobject) {
Base *base = BKE_view_layer_base_find(layer, cob->ob);
TreeElement *te_object = outliner_add_element(soops, tree, base->object, ten, 0, 0);
te_object->directdata = base;
@@ -1383,7 +1413,7 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
TreeElement *parent_ten,
const bool show_objects)
{
- for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) {
+ LISTBASE_FOREACH (LayerCollection *, lc, layer_collections) {
const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
TreeElement *ten;
@@ -1446,7 +1476,7 @@ BLI_INLINE void outliner_add_collection_objects(SpaceOutliner *soops,
Collection *collection,
TreeElement *parent)
{
- for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
outliner_add_element(soops, tree, cob->ob, parent, 0, 0);
}
}
@@ -1457,7 +1487,7 @@ static TreeElement *outliner_add_collection_recursive(SpaceOutliner *soops,
{
outliner_add_collection_init(ten, collection);
- for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
outliner_add_element(soops, &ten->subtree, &child->collection->id, ten, 0, 0);
}
@@ -1520,7 +1550,7 @@ static void outliner_make_object_parent_hierarchy_collections(SpaceOutliner *soo
continue;
}
- for (LinkData *link = parent_ob_tree_elements->first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, parent_ob_tree_elements) {
TreeElement *parent_ob_tree_element = link->data;
TreeElement *parent_ob_collection_tree_element = NULL;
bool found = false;
@@ -1534,8 +1564,7 @@ static void outliner_make_object_parent_hierarchy_collections(SpaceOutliner *soo
parent_ob_collection_tree_element = parent_ob_collection_tree_element->parent;
}
- for (LinkData *link_iter = child_ob_tree_elements->first; link_iter;
- link_iter = link_iter->next) {
+ LISTBASE_FOREACH (LinkData *, link_iter, child_ob_tree_elements) {
TreeElement *child_ob_tree_element = link_iter->data;
if (child_ob_tree_element->parent == parent_ob_collection_tree_element) {
@@ -1567,7 +1596,7 @@ static void outliner_make_object_parent_hierarchy_collections(SpaceOutliner *soo
static void outliner_object_tree_elements_lookup_create_recursive(GHash *object_tree_elements_hash,
TreeElement *te_parent)
{
- for (TreeElement *te = te_parent->subtree.first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, &te_parent->subtree) {
TreeStoreElem *tselem = TREESTORE(te);
if (tselem->type == TSE_LAYER_COLLECTION) {
@@ -1842,13 +1871,13 @@ typedef struct OutlinerTreeElementFocus {
* Caller is expected to handle redrawing of ARegion.
*/
static void outliner_restore_scrolling_position(SpaceOutliner *soops,
- ARegion *ar,
+ ARegion *region,
OutlinerTreeElementFocus *focus)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
if (focus->tselem != NULL) {
- outliner_set_coordinates(ar, soops);
+ outliner_set_coordinates(region, soops);
TreeElement *te_new = outliner_find_tree_element(&soops->tree, focus->tselem);
@@ -1970,15 +1999,15 @@ static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner
* original position as before filtering.
*/
static void outliner_store_scrolling_position(SpaceOutliner *soops,
- ARegion *ar,
+ ARegion *region,
OutlinerTreeElementFocus *focus)
{
TreeElement *te;
- float limit = ar->v2d.cur.ymin;
+ float limit = region->v2d.cur.ymin;
- outliner_set_coordinates(ar, soops);
+ outliner_set_coordinates(region, soops);
- te = outliner_find_first_desired_element_at_y(soops, ar->v2d.cur.ymax, limit);
+ te = outliner_find_first_desired_element_at_y(soops, region->v2d.cur.ymax, limit);
if (te != NULL) {
focus->tselem = TREESTORE(te);
@@ -2090,12 +2119,12 @@ static bool outliner_element_visible_get(ViewLayer *view_layer,
}
if (exclude_filter & SO_FILTER_OB_STATE_VISIBLE) {
- if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
+ if ((base->flag & BASE_VISIBLE_VIEWLAYER) == 0) {
return false;
}
}
else if (exclude_filter & SO_FILTER_OB_STATE_HIDDEN) {
- if ((base->flag & BASE_VISIBLE_DEPSGRAPH) != 0) {
+ if ((base->flag & BASE_VISIBLE_VIEWLAYER) != 0) {
return false;
}
}
@@ -2264,7 +2293,7 @@ static void outliner_filter_tree(SpaceOutliner *soops, ViewLayer *view_layer)
/* Main entry point for building the tree data-structure that the outliner represents */
// TODO: split each mode into its own function?
void outliner_build_tree(
- Main *mainvar, Scene *scene, ViewLayer *view_layer, SpaceOutliner *soops, ARegion *ar)
+ Main *mainvar, Scene *scene, ViewLayer *view_layer, SpaceOutliner *soops, ARegion *region)
{
TreeElement *te = NULL, *ten;
TreeStoreElem *tselem;
@@ -2286,12 +2315,12 @@ void outliner_build_tree(
BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
}
- if (ar->do_draw & RGN_DRAW_NO_REBUILD) {
+ if (region->do_draw & RGN_DRAW_NO_REBUILD) {
return;
}
OutlinerTreeElementFocus focus;
- outliner_store_scrolling_position(soops, ar, &focus);
+ outliner_store_scrolling_position(soops, region, &focus);
outliner_free_tree(&soops->tree);
outliner_storage_cleanup(soops);
@@ -2405,7 +2434,7 @@ void outliner_build_tree(
else if (soops->outlinevis == SO_VIEW_LAYER) {
if (soops->filter & SO_FILTER_NO_COLLECTION) {
/* Show objects in the view layer. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
TreeElement *te_object = outliner_add_element(
soops, &soops->tree, base->object, NULL, 0, 0);
te_object->directdata = base;
@@ -2445,7 +2474,7 @@ void outliner_build_tree(
}
outliner_filter_tree(soops, view_layer);
- outliner_restore_scrolling_position(soops, ar, &focus);
+ outliner_restore_scrolling_position(soops, region, &focus);
BKE_main_id_clear_newpoins(mainvar);
}
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
index c3984ab16fa..a058c30cef2 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -23,6 +23,7 @@
#include <string.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_action_types.h"
@@ -30,9 +31,9 @@
#include "DNA_space_types.h"
#include "BKE_context.h"
-#include "BKE_outliner_treehash.h"
#include "BKE_layer.h"
#include "BKE_object.h"
+#include "BKE_outliner_treehash.h"
#include "ED_armature.h"
#include "ED_outliner.h"
@@ -77,7 +78,7 @@ TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops,
const ListBase *tree,
float view_co_y)
{
- for (TreeElement *te_iter = tree->first; te_iter; te_iter = te_iter->next) {
+ LISTBASE_FOREACH (TreeElement *, te_iter, tree) {
if (view_co_y < (te_iter->ys + UI_UNIT_Y)) {
if (view_co_y >= te_iter->ys) {
/* co_y is inside this element */
@@ -203,7 +204,7 @@ TreeElement *outliner_find_tse(SpaceOutliner *soops, const TreeStoreElem *tse)
/* Find treestore that refers to given ID */
TreeElement *outliner_find_id(SpaceOutliner *soops, ListBase *lb, const ID *id)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
if (tselem->type == 0) {
if (tselem->id == id) {
@@ -221,7 +222,7 @@ TreeElement *outliner_find_id(SpaceOutliner *soops, ListBase *lb, const ID *id)
TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
if (te->directdata == pchan) {
return te;
}
@@ -239,7 +240,7 @@ TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan)
TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
if (te->directdata == ebone) {
return te;
}
@@ -255,7 +256,7 @@ TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone)
return NULL;
}
-ID *outliner_search_back(SpaceOutliner *UNUSED(soops), TreeElement *te, short idcode)
+ID *outliner_search_back(TreeElement *te, short idcode)
{
TreeStoreElem *tselem;
te = te->parent;
@@ -360,7 +361,7 @@ float outliner_restrict_columns_width(const SpaceOutliner *soops)
/* Find first tree element in tree with matching treestore flag */
TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag)
{
- for (TreeElement *te = lb->first; te; te = te->next) {
+ LISTBASE_FOREACH (TreeElement *, te, lb) {
if ((TREESTORE(te)->flag & flag) == flag) {
return te;
}
@@ -409,38 +410,38 @@ bool outliner_item_is_co_within_close_toggle(const TreeElement *te, float view_c
}
/* Scroll view vertically while keeping within total bounds */
-void outliner_scroll_view(ARegion *ar, int delta_y)
+void outliner_scroll_view(ARegion *region, int delta_y)
{
- int y_min = MIN2(ar->v2d.cur.ymin, ar->v2d.tot.ymin);
+ int y_min = MIN2(region->v2d.cur.ymin, region->v2d.tot.ymin);
- ar->v2d.cur.ymax += delta_y;
- ar->v2d.cur.ymin += delta_y;
+ region->v2d.cur.ymax += delta_y;
+ region->v2d.cur.ymin += delta_y;
/* Adjust view if delta placed view outside total area */
int offset;
- if (ar->v2d.cur.ymax > -UI_UNIT_Y) {
- offset = ar->v2d.cur.ymax;
- ar->v2d.cur.ymax -= offset;
- ar->v2d.cur.ymin -= offset;
+ if (region->v2d.cur.ymax > -UI_UNIT_Y) {
+ offset = region->v2d.cur.ymax;
+ region->v2d.cur.ymax -= offset;
+ region->v2d.cur.ymin -= offset;
}
- else if (ar->v2d.cur.ymin < y_min) {
- offset = y_min - ar->v2d.cur.ymin;
- ar->v2d.cur.ymax += offset;
- ar->v2d.cur.ymin += offset;
+ else if (region->v2d.cur.ymin < y_min) {
+ offset = y_min - region->v2d.cur.ymin;
+ region->v2d.cur.ymax += offset;
+ region->v2d.cur.ymin += offset;
}
}
/* Get base of object under cursor. Used for eyedropper tool */
Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2])
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te;
Base *base = NULL;
float view_mval[2];
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
if (te) {
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 68eea4f278b..9450136b6a6 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -21,23 +21,23 @@
* \ingroup spoutliner
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_mempool.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_layer.h"
-#include "BKE_screen.h"
-#include "BKE_scene.h"
#include "BKE_outliner_treehash.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "WM_api.h"
#include "WM_message.h"
@@ -45,45 +45,45 @@
#include "RNA_access.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "outliner_intern.h"
#include "GPU_framebuffer.h"
+#include "outliner_intern.h"
-static void outliner_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void outliner_main_region_init(wmWindowManager *wm, ARegion *region)
{
ListBase *lb;
wmKeyMap *keymap;
/* make sure we keep the hide flags */
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
- ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP); /* prevent any noise of past */
- ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
+ region->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ region->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP); /* prevent any noise of past */
+ region->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ region->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
- ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
- ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
+ region->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ region->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ region->v2d.keeptot = V2D_KEEPTOT_STRICT;
+ region->v2d.minzoom = region->v2d.maxzoom = 1.0f;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Outliner", SPACE_OUTLINER, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
/* Add dropboxes */
lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW);
- WM_event_add_dropbox_handler(&ar->handlers, lb);
+ WM_event_add_dropbox_handler(&region->handlers, lb);
}
-static void outliner_main_region_draw(const bContext *C, ARegion *ar)
+static void outliner_main_region_draw(const bContext *C, ARegion *region)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
/* clear */
@@ -101,13 +101,13 @@ static void outliner_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
}
-static void outliner_main_region_free(ARegion *UNUSED(ar))
+static void outliner_main_region_free(ARegion *UNUSED(region))
{
}
static void outliner_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -128,11 +128,11 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win),
case ND_LAYER_CONTENT:
case ND_WORLD:
case ND_SCENEBROWSE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
if (wmn->action & NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_OBJECT:
@@ -145,46 +145,46 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win),
case ND_DRAW:
case ND_PARENT:
case ND_OB_SHADING:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_CONSTRAINT:
/* all constraint actions now, for reordering */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_MODIFIER:
/* all modifier actions now */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
default:
/* Trigger update for NC_OBJECT itself */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_GROUP:
/* all actions now, todo: check outliner view mode? */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_LAMP:
/* For updating light icons, when changing light type */
if (wmn->data == ND_LIGHTING_DRAW) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_OUTLINER) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_MATERIAL:
switch (wmn->data) {
case ND_SHADING_LINKS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -192,7 +192,7 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_VERTEX_GROUP:
case ND_DATA:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -200,38 +200,38 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_NLA_ACTCHANGE:
case ND_KEYFRAME:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_ANIMCHAN:
if (wmn->action == NA_SELECTED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
break;
case NC_GPENCIL:
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_MASK:
if (ELEM(wmn->action, NA_ADDED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_PAINTCURVE:
if (ELEM(wmn->action, NA_ADDED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_TEXT:
if (ELEM(wmn->action, NA_ADDED, NA_REMOVED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -241,14 +241,14 @@ static void outliner_main_region_message_subscribe(const struct bContext *UNUSED
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
- SpaceOutliner *soops = sa->spacedata.first;
+ SpaceOutliner *soops = area->spacedata.first;
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -260,23 +260,23 @@ static void outliner_main_region_message_subscribe(const struct bContext *UNUSED
/* ************************ header outliner area region *********************** */
/* add handlers, stuff you only do once or on area/region changes */
-static void outliner_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void outliner_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void outliner_header_region_draw(const bContext *C, ARegion *ar)
+static void outliner_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
-static void outliner_header_region_free(ARegion *UNUSED(ar))
+static void outliner_header_region_free(ARegion *UNUSED(region))
{
}
static void outliner_header_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -284,12 +284,12 @@ static void outliner_header_region_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_SCENE:
if (wmn->data == ND_KEYINGSET) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_OUTLINER) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -299,7 +299,7 @@ static void outliner_header_region_listener(wmWindow *UNUSED(win),
static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceOutliner *soutliner;
soutliner = MEM_callocN(sizeof(SpaceOutliner), "initoutliner");
@@ -311,17 +311,17 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
soutliner->flag |= SO_SYNC_SELECT;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for outliner");
+ region = MEM_callocN(sizeof(ARegion), "header for outliner");
- BLI_addtail(&soutliner->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&soutliner->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for outliner");
+ region = MEM_callocN(sizeof(ARegion), "main region for outliner");
- BLI_addtail(&soutliner->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&soutliner->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
return (SpaceLink *)soutliner;
}
@@ -341,7 +341,7 @@ static void outliner_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void outliner_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void outliner_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -360,7 +360,7 @@ static SpaceLink *outliner_duplicate(SpaceLink *sl)
return (SpaceLink *)soutlinern;
}
-static void outliner_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void outliner_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceOutliner *so = (SpaceOutliner *)slink;
@@ -393,12 +393,12 @@ static void outliner_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id,
}
}
-static void outliner_deactivate(struct ScrArea *sa)
+static void outliner_deactivate(struct ScrArea *area)
{
/* Remove hover highlights */
- SpaceOutliner *soops = sa->spacedata.first;
+ SpaceOutliner *soops = area->spacedata.first;
outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED, false);
- ED_region_tag_redraw(BKE_area_find_region_type(sa, RGN_TYPE_WINDOW));
+ ED_region_tag_redraw(BKE_area_find_region_type(area, RGN_TYPE_WINDOW));
}
/* only called once, from space_api/spacetypes.c */
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c
index 2be05785d2b..e9ed1cec228 100644
--- a/source/blender/editors/space_script/script_edit.c
+++ b/source/blender/editors/space_script/script_edit.c
@@ -21,11 +21,11 @@
* \ingroup spscript
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -51,8 +51,8 @@ static int run_pyfile_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", path);
#ifdef WITH_PYTHON
if (BPY_execute_filepath(C, path, op->reports)) {
- ARegion *ar = CTX_wm_region(C);
- ED_region_tag_redraw(ar);
+ ARegion *region = CTX_wm_region(C);
+ ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
#else
@@ -67,12 +67,12 @@ void SCRIPT_OT_python_file_run(wmOperatorType *ot)
ot->name = "Run Python File";
ot->description = "Run Python file";
ot->idname = "SCRIPT_OT_python_file_run";
- ot->flag = OPTYPE_UNDO;
/* api callbacks */
ot->exec = run_pyfile_exec;
ot->poll = ED_operator_areaactive;
+ /* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "Path", "");
@@ -92,7 +92,7 @@ static bool script_test_modal_operators(bContext *C)
wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base;
if (handler->op != NULL) {
wmOperatorType *ot = handler->op->type;
- if (ot->ext.srna) {
+ if (ot->rna_ext.srna) {
return true;
}
}
diff --git a/source/blender/editors/space_script/script_ops.c b/source/blender/editors/space_script/script_ops.c
index 3101bf6a7a7..4b557daf36a 100644
--- a/source/blender/editors/space_script/script_ops.c
+++ b/source/blender/editors/space_script/script_ops.c
@@ -21,8 +21,8 @@
* \ingroup spscript
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include "WM_api.h"
diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c
index b99c2eaf54e..343f35421a4 100644
--- a/source/blender/editors/space_script/space_script.c
+++ b/source/blender/editors/space_script/space_script.c
@@ -21,8 +21,8 @@
* \ingroup spscript
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -32,8 +32,8 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -44,8 +44,8 @@
#ifdef WITH_PYTHON
#endif
-#include "script_intern.h" // own include
#include "GPU_framebuffer.h"
+#include "script_intern.h" // own include
// static script_run_python(char *funcname, )
@@ -53,24 +53,24 @@
static SpaceLink *script_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceScript *sscript;
sscript = MEM_callocN(sizeof(SpaceScript), "initscript");
sscript->spacetype = SPACE_SCRIPT;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for script");
+ region = MEM_callocN(sizeof(ARegion), "header for script");
- BLI_addtail(&sscript->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&sscript->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for script");
+ region = MEM_callocN(sizeof(ARegion), "main region for script");
- BLI_addtail(&sscript->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&sscript->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
/* channel list region XXX */
@@ -94,7 +94,7 @@ static void script_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void script_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void script_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -108,22 +108,22 @@ static SpaceLink *script_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void script_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void script_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_STANDARD, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Script", SPACE_SCRIPT, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void script_main_region_draw(const bContext *C, ARegion *ar)
+static void script_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceScript *sscript = (SpaceScript *)CTX_wm_space_data(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
@@ -149,19 +149,19 @@ static void script_main_region_draw(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void script_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void script_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void script_header_region_draw(const bContext *C, ARegion *ar)
+static void script_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
static void script_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *UNUSED(ar),
+ ScrArea *UNUSED(area),
+ ARegion *UNUSED(region),
wmNotifier *UNUSED(wmn),
const Scene *UNUSED(scene))
{
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index da7d9e2a8f3..8105891e157 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -17,6 +17,7 @@
set(INC
../include
+ ../../blenfont
../../blenkernel
../../blenlib
../../blentranslation
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 9e8fa6475a0..80172c5462f 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -21,10 +21,10 @@
* \ingroup spseq
*/
-#include <stdlib.h>
+#include <ctype.h>
#include <math.h>
+#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
#include "MEM_guardedalloc.h"
@@ -34,11 +34,11 @@
#include "BLT_translation.h"
-#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
+#include "DNA_scene_types.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_movieclip.h"
@@ -51,8 +51,7 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-/* for menu/popup icons etc etc*/
-
+/* For menu, popup, icons, etc. */
#include "ED_screen.h"
#include "ED_sequencer.h"
@@ -67,16 +66,16 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-/* own include */
+/* Own include. */
#include "sequencer_intern.h"
typedef struct SequencerAddData {
ImageFormatData im_format;
} SequencerAddData;
-/* Generic functions, reused by add strip operators */
+/* Generic functions, reused by add strip operators. */
-/* avoid passing multiple args and be more verbose */
+/* Avoid passing multiple args and be more verbose. */
#define SEQPROP_STARTFRAME (1 << 0)
#define SEQPROP_ENDFRAME (1 << 1)
#define SEQPROP_NOPATHS (1 << 2)
@@ -101,7 +100,7 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
}
if (flag & SEQPROP_ENDFRAME) {
- /* not usual since most strips have a fixed length */
+ /* Not usual since most strips have a fixed length. */
RNA_def_int(ot->srna,
"frame_end",
0,
@@ -119,7 +118,7 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
RNA_def_boolean(
ot->srna, "replace_sel", 1, "Replace Selection", "Replace the current selection");
- /* only for python scripts which import strips and place them after */
+ /* Only for python scripts which import strips and place them after. */
prop = RNA_def_boolean(
ot->srna, "overlap", 0, "Allow Overlap", "Don't correct overlap on new sequence strips");
RNA_def_property_flag(prop, PROP_HIDDEN);
@@ -175,7 +174,7 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i
int cfra = (int)CFRA;
- /* effect strips don't need a channel initialized from the mouse */
+ /* Effect strips don't need a channel initialized from the mouse. */
if (!(flag & SEQPROP_NOCHAN) && RNA_struct_property_is_set(op->ptr, "channel") == 0) {
RNA_int_set(op->ptr, "channel", sequencer_generic_invoke_xy_guess_channel(C, type));
}
@@ -203,18 +202,17 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
memset(seq_load, 0, sizeof(SeqLoadInfo));
seq_load->start_frame = RNA_int_get(op->ptr, "frame_start");
- seq_load->end_frame = seq_load->start_frame; /* un-set */
-
+ seq_load->end_frame = seq_load->start_frame;
seq_load->channel = RNA_int_get(op->ptr, "channel");
- seq_load->len = 1; // images only, if endframe isn't set!
+ seq_load->len = 1;
if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
- /* full path, file is set by the caller */
+ /* Full path, file is set by the caller. */
RNA_property_string_get(op->ptr, prop, seq_load->path);
is_file = 1;
}
else if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
- /* full path, file is set by the caller */
+ /* Full path, file is set by the caller. */
RNA_property_string_get(op->ptr, prop, seq_load->path);
is_file = 0;
}
@@ -252,15 +250,13 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
seq_load->flag |= SEQ_LOAD_SYNC_FPS;
}
- /* always use this for ops */
+ /* Create consecutive array of strips. */
seq_load->flag |= SEQ_LOAD_FRAME_ADVANCE;
if (is_file == 1) {
BLI_strncpy(seq_load->name, BLI_path_basename(seq_load->path), sizeof(seq_load->name));
}
else if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
- /* used for image strip */
- /* best guess, first images name */
RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
char *name = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
BLI_strncpy(seq_load->name, name, sizeof(seq_load->name));
@@ -278,9 +274,6 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
seq_load->views_format = imf->views_format;
seq_load->flag |= SEQ_USE_VIEWS;
-
- /* operator custom data is always released after the SeqLoadInfo,
- * no need to handle the memory here */
seq_load->stereo3d_format = &imf->stereo3d_format;
}
}
@@ -332,23 +325,18 @@ static bool seq_effect_add_properties_poll(const bContext *UNUSED(C),
return true;
}
-/* add scene operator */
static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, true);
-
Scene *sce_seq;
+ Sequence *seq;
- Sequence *seq; /* generic strip vars */
-
- int start_frame, channel; /* operator props */
-
+ int start_frame, channel;
start_frame = RNA_int_get(op->ptr, "frame_start");
channel = RNA_int_get(op->ptr, "channel");
-
- sce_seq = BLI_findlink(&CTX_data_main(C)->scenes, RNA_enum_get(op->ptr, "scene"));
+ sce_seq = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
if (sce_seq == NULL) {
BKE_report(op->reports, RPT_ERROR, "Scene not found");
@@ -356,11 +344,8 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
}
seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_SCENE);
- seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
-
+ seq->blend_mode = SEQ_TYPE_CROSS;
seq->scene = sce_seq;
-
- /* basic defaults */
seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2);
@@ -388,26 +373,23 @@ static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, const w
sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_SCENE);
return sequencer_add_scene_strip_exec(C, op);
- // needs a menu
- // return WM_menu_invoke(C, op, event);
}
void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
{
PropertyRNA *prop;
- /* identifiers */
+ /* Identifiers. */
ot->name = "Add Scene Strip";
ot->idname = "SEQUENCER_OT_scene_strip_add";
ot->description = "Add a strip to the sequencer using a blender scene as a source";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_add_scene_strip_invoke;
ot->exec = sequencer_add_scene_strip_exec;
-
ot->poll = ED_operator_sequencer_active_editable;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
@@ -417,22 +399,18 @@ void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
ot->prop = prop;
}
-/* add movieclip operator */
static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, true);
-
MovieClip *clip;
+ Sequence *seq;
- Sequence *seq; /* generic strip vars */
-
- int start_frame, channel; /* operator props */
-
+ int start_frame, channel;
start_frame = RNA_int_get(op->ptr, "frame_start");
channel = RNA_int_get(op->ptr, "channel");
-
- clip = BLI_findlink(&CTX_data_main(C)->movieclips, RNA_enum_get(op->ptr, "clip"));
+ clip = BLI_findlink(&bmain->movieclips, RNA_enum_get(op->ptr, "clip"));
if (clip == NULL) {
BKE_report(op->reports, RPT_ERROR, "Movie clip not found");
@@ -442,12 +420,10 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MOVIECLIP);
seq->blend_mode = SEQ_TYPE_CROSS;
seq->clip = clip;
+ seq->len = BKE_movieclip_get_duration(clip);
id_us_ensure_real(&seq->clip->id);
- /* basic defaults */
- seq->len = BKE_movieclip_get_duration(clip);
-
BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2);
BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
@@ -472,26 +448,23 @@ static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, con
sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_MOVIECLIP);
return sequencer_add_movieclip_strip_exec(C, op);
- // needs a menu
- // return WM_menu_invoke(C, op, event);
}
void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot)
{
PropertyRNA *prop;
- /* identifiers */
+ /* Identifiers. */
ot->name = "Add MovieClip Strip";
ot->idname = "SEQUENCER_OT_movieclip_strip_add";
ot->description = "Add a movieclip strip to the sequencer";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_add_movieclip_strip_invoke;
ot->exec = sequencer_add_movieclip_strip_exec;
-
ot->poll = ED_operator_sequencer_active_editable;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
@@ -504,19 +477,16 @@ void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot)
static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, true);
-
Mask *mask;
+ Sequence *seq;
- Sequence *seq; /* generic strip vars */
-
- int start_frame, channel; /* operator props */
-
+ int start_frame, channel;
start_frame = RNA_int_get(op->ptr, "frame_start");
channel = RNA_int_get(op->ptr, "channel");
-
- mask = BLI_findlink(&CTX_data_main(C)->masks, RNA_enum_get(op->ptr, "mask"));
+ mask = BLI_findlink(&bmain->masks, RNA_enum_get(op->ptr, "mask"));
if (mask == NULL) {
BKE_report(op->reports, RPT_ERROR, "Mask not found");
@@ -526,12 +496,10 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MASK);
seq->blend_mode = SEQ_TYPE_CROSS;
seq->mask = mask;
+ seq->len = BKE_mask_get_duration(mask);
id_us_ensure_real(&seq->mask->id);
- /* basic defaults */
- seq->len = BKE_mask_get_duration(mask);
-
BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2);
BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
@@ -556,26 +524,23 @@ static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, const wm
sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_MASK);
return sequencer_add_mask_strip_exec(C, op);
- // needs a menu
- // return WM_menu_invoke(C, op, event);
}
void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot)
{
PropertyRNA *prop;
- /* identifiers */
+ /* Identifiers. */
ot->name = "Add Mask Strip";
ot->idname = "SEQUENCER_OT_mask_strip_add";
ot->description = "Add a mask strip to the sequencer";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_add_mask_strip_invoke;
ot->exec = sequencer_add_mask_strip_exec;
-
ot->poll = ED_operator_sequencer_active_editable;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
@@ -585,9 +550,9 @@ void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot)
ot->prop = prop;
}
-static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFunc seq_load_func)
+static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFn seq_load_fn)
{
- Scene *scene = CTX_data_scene(C); /* only for sound */
+ Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, true);
SeqLoadInfo seq_load;
int tot_files;
@@ -598,32 +563,23 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
ED_sequencer_deselect_all(scene);
}
- if (RNA_struct_property_is_set(op->ptr, "files") &&
- RNA_struct_property_is_set(op->ptr, "directory")) {
- tot_files = RNA_property_collection_length(op->ptr,
- RNA_struct_find_property(op->ptr, "files"));
- }
- else {
- tot_files = 0;
- }
+ tot_files = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
- if (tot_files) {
- /* multiple files */
+ if (tot_files > 1) {
char dir_only[FILE_MAX];
char file_only[FILE_MAX];
- RNA_string_get(op->ptr, "directory", dir_only);
-
RNA_BEGIN (op->ptr, itemptr, "files") {
Sequence *seq;
+ RNA_string_get(op->ptr, "directory", dir_only);
RNA_string_get(&itemptr, "name", file_only);
BLI_join_dirfile(seq_load.path, sizeof(seq_load.path), dir_only, file_only);
- /* Set seq_load.name, else all video/audio files get the same name! ugly! */
+ /* Set seq_load.name, otherwise all video/audio files get the same name. */
BLI_strncpy(seq_load.name, file_only, sizeof(seq_load.name));
- seq = seq_load_func(C, ed->seqbasep, &seq_load);
+ seq = seq_load_fn(C, ed->seqbasep, &seq_load);
if (seq) {
sequencer_add_apply_overlap(C, op, seq);
if (seq_load.seq_sound) {
@@ -633,11 +589,10 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
}
RNA_END;
}
- else {
+ else { /* Single file./ */
Sequence *seq;
+ seq = seq_load_fn(C, ed->seqbasep, &seq_load);
- /* single file */
- seq = seq_load_func(C, ed->seqbasep, &seq_load);
if (seq) {
sequencer_add_apply_overlap(C, op, seq);
if (seq_load.seq_sound) {
@@ -664,7 +619,6 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
return OPERATOR_FINISHED;
}
-/* add sequencer operators */
static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op)
{
op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__);
@@ -678,9 +632,9 @@ static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op)
op->customdata = NULL;
}
-static bool sequencer_add_draw_check_prop(PointerRNA *UNUSED(ptr),
- PropertyRNA *prop,
- void *UNUSED(user_data))
+static bool sequencer_add_draw_check_fn(PointerRNA *UNUSED(ptr),
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
{
const char *prop_id = RNA_property_identifier(prop);
@@ -688,7 +642,6 @@ static bool sequencer_add_draw_check_prop(PointerRNA *UNUSED(ptr),
STREQ(prop_id, "filename"));
}
-/* add movie operator */
static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
{
return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_movie_strip);
@@ -702,20 +655,12 @@ static int sequencer_add_movie_strip_invoke(bContext *C,
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
- /* only enable "use_framerate" if there aren't any existing strips
- * - When there are no strips yet, there is no harm in enabling this,
- * and it makes the single-strip case really nice for casual users
- * - When there are strips, it's best we don't touch the framerate,
- * as all hell may break loose (e.g. audio strips start overlapping
- * and can't be restored)
- * - These initial guesses can still be manually overridden by users
- * from the modal options panel
- */
+ /* Only enable "use_framerate" if there aren't any existing strips, unless overriden by user. */
if (ed && ed->seqbasep && ed->seqbasep->first) {
RNA_boolean_set(op->ptr, "use_framerate", false);
}
- /* This is for drag and drop */
+ /* This is for drag and drop. */
if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
RNA_struct_property_is_set(op->ptr, "filepath")) {
sequencer_generic_invoke_xy__internal(C, op, SEQPROP_NOPATHS, SEQ_TYPE_MOVIE);
@@ -723,17 +668,14 @@ static int sequencer_add_movie_strip_invoke(bContext *C,
}
sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_MOVIE);
-
sequencer_add_init(C, op);
- /* show multiview save options only if scene has multiviews */
+ /* Show multiview save options only if scene use multiview. */
prop = RNA_struct_find_property(op->ptr, "show_multiview");
RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
-
- // return sequencer_add_movie_strip_exec(C, op);
}
static void sequencer_add_draw(bContext *UNUSED(C), wmOperator *op)
@@ -743,15 +685,15 @@ static void sequencer_add_draw(bContext *UNUSED(C), wmOperator *op)
ImageFormatData *imf = &sad->im_format;
PointerRNA imf_ptr, ptr;
- /* main draw call */
+ /* Main draw call. */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
uiDefAutoButsRNA(
- layout, &ptr, sequencer_add_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
+ layout, &ptr, sequencer_add_draw_check_fn, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
- /* image template */
+ /* Image template. */
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
- /* multiview template */
+ /* Multiview template. */
if (RNA_boolean_get(op->ptr, "show_multiview")) {
uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
}
@@ -760,20 +702,19 @@ static void sequencer_add_draw(bContext *UNUSED(C), wmOperator *op)
void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Add Movie Strip";
ot->idname = "SEQUENCER_OT_movie_strip_add";
ot->description = "Add a movie strip to the sequencer";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_add_movie_strip_invoke;
ot->exec = sequencer_add_movie_strip_exec;
ot->cancel = sequencer_add_cancel;
ot->ui = sequencer_add_draw;
-
ot->poll = ED_operator_sequencer_active_editable;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_filesel(ot,
@@ -781,7 +722,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
FILE_SPECIAL,
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES |
- WM_FILESEL_SHOW_PROPS,
+ WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
@@ -793,8 +734,6 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
"Use framerate from the movie to keep sound and video in sync");
}
-/* add sound operator */
-
static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
{
return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_sound_strip);
@@ -804,7 +743,7 @@ static int sequencer_add_sound_strip_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
{
- /* This is for drag and drop */
+ /* This is for drag and drop. */
if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
RNA_struct_property_is_set(op->ptr, "filepath")) {
sequencer_generic_invoke_xy__internal(C, op, SEQPROP_NOPATHS, SEQ_TYPE_SOUND_RAM);
@@ -815,25 +754,22 @@ static int sequencer_add_sound_strip_invoke(bContext *C,
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
-
- // return sequencer_add_sound_strip_exec(C, op);
}
void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Add Sound Strip";
ot->idname = "SEQUENCER_OT_sound_strip_add";
ot->description = "Add a sound strip to the sequencer";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_add_sound_strip_invoke;
ot->exec = sequencer_add_sound_strip_exec;
-
ot->poll = ED_operator_sequencer_active_editable;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_filesel(ot,
@@ -841,7 +777,7 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
FILE_SPECIAL,
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES |
- WM_FILESEL_SHOW_PROPS,
+ WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
@@ -860,7 +796,6 @@ int sequencer_image_seq_get_minmax_frame(wmOperator *op,
RNA_BEGIN (op->ptr, itemptr, "files") {
char *filename;
int frame;
- /* just get the first filename */
filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
if (filename) {
@@ -891,7 +826,6 @@ void sequencer_image_seq_reserve_frames(
int i;
char *filename = NULL;
RNA_BEGIN (op->ptr, itemptr, "files") {
- /* just get the first filename */
filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
break;
}
@@ -900,7 +834,7 @@ void sequencer_image_seq_reserve_frames(
if (filename) {
char ext[PATH_MAX];
char filename_stripped[PATH_MAX];
- /* strip the frame from filename and substitute with # */
+ /* Strip the frame from filename and substitute with `#`. */
BLI_path_frame_strip(filename, ext);
for (i = 0; i < len; i++, se++) {
@@ -913,23 +847,20 @@ void sequencer_image_seq_reserve_frames(
}
}
-/* add image operator */
static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
{
int minframe, numdigits;
- /* cant use the generic function for this */
- Scene *scene = CTX_data_scene(C); /* only for sound */
+ Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, true);
SeqLoadInfo seq_load;
Sequence *seq;
-
Strip *strip;
StripElem *se;
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
seq_load_operator_info(&seq_load, C, op);
- /* images are unique in how they handle this - 1 per strip elem */
+ /* Images are unique in how they handle this - 1 per strip elem. */
if (use_placeholders) {
seq_load.len = sequencer_image_seq_get_minmax_frame(
op, seq_load.start_frame, &minframe, &numdigits);
@@ -947,11 +878,10 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
ED_sequencer_deselect_all(scene);
}
- /* main adding function */
+ /* Main adding function. */
seq = BKE_sequencer_add_image_strip(C, ed->seqbasep, &seq_load);
strip = seq->strip;
se = strip->stripdata;
-
seq->blend_mode = SEQ_TYPE_ALPHAOVER;
if (use_placeholders) {
@@ -974,21 +904,18 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
}
BKE_sequence_init_colorspace(seq);
-
BKE_sequence_calc_disp(scene, seq);
-
BKE_sequencer_sort(scene);
- /* last active name */
+ /* Last active name. */
BLI_strncpy(ed->act_imagedir, strip->dir, sizeof(ed->act_imagedir));
-
sequencer_add_apply_overlap(C, op, seq);
if (op->customdata) {
MEM_freeN(op->customdata);
}
- BKE_sequence_invalidate_cache_composite(scene, seq);
+ BKE_sequence_invalidate_cache_composite(scene, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1002,7 +929,7 @@ static int sequencer_add_image_strip_invoke(bContext *C,
PropertyRNA *prop;
Scene *scene = CTX_data_scene(C);
- /* drag drop has set the names */
+ /* Name set already by drag and drop. */
if (RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) {
sequencer_generic_invoke_xy__internal(
C, op, SEQPROP_ENDFRAME | SEQPROP_NOPATHS, SEQ_TYPE_IMAGE);
@@ -1010,10 +937,9 @@ static int sequencer_add_image_strip_invoke(bContext *C,
}
sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME, SEQ_TYPE_IMAGE);
-
sequencer_add_init(C, op);
- /* show multiview save options only if scene has multiviews */
+ /* Show multiview save options only if scene use multiview. */
prop = RNA_struct_find_property(op->ptr, "show_multiview");
RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
@@ -1024,20 +950,19 @@ static int sequencer_add_image_strip_invoke(bContext *C,
void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Add Image Strip";
ot->idname = "SEQUENCER_OT_image_strip_add";
ot->description = "Add an image or image sequence to the sequencer";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_add_image_strip_invoke;
ot->exec = sequencer_add_image_strip_exec;
ot->cancel = sequencer_add_cancel;
ot->ui = sequencer_add_draw;
-
ot->poll = ED_operator_sequencer_active_editable;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_filesel(ot,
@@ -1045,7 +970,7 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
FILE_SPECIAL,
FILE_OPENFILE,
WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES |
- WM_FILESEL_SHOW_PROPS,
+ WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
@@ -1057,65 +982,54 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
"Use placeholders for missing frames of the strip");
}
-/* add_effect_strip operator */
static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, true);
-
- Sequence *seq; /* generic strip vars */
+ Sequence *seq;
struct SeqEffectHandle sh;
-
- int start_frame, end_frame, channel, type; /* operator props */
-
Sequence *seq1, *seq2, *seq3;
const char *error_msg;
+ int start_frame, end_frame, channel, type;
start_frame = RNA_int_get(op->ptr, "frame_start");
end_frame = RNA_int_get(op->ptr, "frame_end");
channel = RNA_int_get(op->ptr, "channel");
-
type = RNA_enum_get(op->ptr, "type");
- // XXX move to invoke
if (!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) {
BKE_report(op->reports, RPT_ERROR, error_msg);
return OPERATOR_CANCELLED;
}
- /* If seq1 is NULL and no error was raised it means the seq is standalone
- * (like color strips) and we need to check its start and end frames are valid */
+ /* Check its start and end frames are valid. */
if (seq1 == NULL && end_frame <= start_frame) {
end_frame = start_frame + 1;
RNA_int_set(op->ptr, "frame_end", end_frame);
}
seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, type);
-
BLI_strncpy(seq->name + 2, BKE_sequence_give_name(seq), sizeof(seq->name) - 2);
BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
sh = BKE_sequence_get_effect(seq);
-
+ sh.init(seq);
seq->seq1 = seq1;
seq->seq2 = seq2;
seq->seq3 = seq3;
- sh.init(seq);
-
- if (!seq1) { /* effect has no deps */
- seq->len = 1;
+ if (!seq1) {
+ seq->len = 1; /* Effect is generator, set non zero length. */
BKE_sequence_tx_set_final_right(seq, end_frame);
}
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
-
BKE_sequence_calc(scene, seq);
if (seq->type == SEQ_TYPE_COLOR) {
SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
RNA_float_get_array(op->ptr, "color", colvars->col);
- seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
+ seq->blend_mode = SEQ_TYPE_CROSS;
}
else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
seq->blend_mode = SEQ_TYPE_CROSS;
@@ -1124,8 +1038,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
seq->blend_mode = SEQ_TYPE_ALPHAOVER;
}
- /* an unset channel is a special case where we automatically go above
- * the other strips. */
+ /* Set channel. If unset, use lowest free one above strips. */
if (!RNA_struct_property_is_set(op->ptr, "channel")) {
if (seq->seq1) {
int chan = max_iii(seq->seq1 ? seq->seq1->machine : 0,
@@ -1140,20 +1053,16 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
sequencer_add_apply_replace_sel(C, op, seq);
sequencer_add_apply_overlap(C, op, seq);
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* runs BKE_sequence_calc */
-
- /* not sure if this is needed with update_changed_seq_and_deps.
- * it was NOT called in blender 2.4x, but wont hurt */
+ BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs BKE_sequence_calc. */
BKE_sequencer_sort(scene);
- BKE_sequence_invalidate_cache_composite(scene, seq);
+ BKE_sequence_invalidate_cache_composite(scene, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
}
-/* add color */
static int sequencer_add_effect_strip_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
@@ -1165,10 +1074,8 @@ static int sequencer_add_effect_strip_invoke(bContext *C,
if (is_type_set) {
type = RNA_enum_get(op->ptr, "type");
- /* when invoking an effect strip which uses inputs,
- * skip initializing the channel from the mouse.
- * Instead leave the property unset so exec() initializes it to be
- * above the strips its applied to. */
+ /* When invoking an effect strip which uses inputs, skip initializing the channel from the
+ * mouse. */
if (BKE_sequence_effect_get_num_inputs(type) != 0) {
prop_flag |= SEQPROP_NOCHAN;
}
@@ -1183,19 +1090,18 @@ void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
{
PropertyRNA *prop;
- /* identifiers */
+ /* Identifiers. */
ot->name = "Add Effect Strip";
ot->idname = "SEQUENCER_OT_effect_strip_add";
ot->description = "Add an effect to the sequencer, most are applied on top of existing strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_add_effect_strip_invoke;
ot->exec = sequencer_add_effect_strip_exec;
-
ot->poll = ED_operator_sequencer_active_editable;
ot->poll_property = seq_effect_add_properties_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_enum(ot->srna,
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
index 7bec913900d..dce8aa16985 100644
--- a/source/blender/editors/space_sequencer/sequencer_buttons.c
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -21,13 +21,13 @@
* \ingroup spseq
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -35,15 +35,15 @@
#include "BKE_global.h"
#include "BKE_screen.h"
-#include "ED_screen.h"
#include "ED_gpencil.h"
+#include "ED_screen.h"
#include "ED_sequencer.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "sequencer_intern.h"
@@ -54,7 +54,7 @@ static bool sequencer_grease_pencil_panel_poll(const bContext *C, PanelType *UNU
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
- /* don't show the gpencil if we are not showing the image */
+ /* Don't show the gpencil if we are not showing the image. */
return ED_space_sequencer_check_show_imbuf(sseq);
}
#endif
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index bef4a7cdd22..5d8851d5e3d 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -21,49 +21,50 @@
* \ingroup spseq
*/
-#include <string.h>
#include <math.h>
+#include <string.h>
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_threads.h"
+#include "BLI_utildefines.h"
#include "IMB_imbuf_types.h"
-#include "DNA_scene_types.h"
+#include "DNA_anim_types.h"
#include "DNA_mask_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
-#include "DNA_sound_types.h"
-#include "DNA_anim_types.h"
#include "BKE_context.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
-#include "BKE_scene.h"
-#include "BKE_fcurve.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
+#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
-#include "GPU_framebuffer.h"
+#include "GPU_vertex_buffer.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
#include "ED_markers.h"
#include "ED_mask.h"
-#include "ED_sequencer.h"
#include "ED_screen.h"
-#include "ED_time_scrub_ui.h"
+#include "ED_sequencer.h"
#include "ED_space_api.h"
+#include "ED_time_scrub_ui.h"
#include "BIF_glutil.h"
@@ -74,31 +75,30 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "BLF_api.h"
+
#include "MEM_guardedalloc.h"
-/* own include */
+/* Own include. */
#include "sequencer_intern.h"
#define SEQ_LEFTHANDLE 1
#define SEQ_RIGHTHANDLE 2
-
-#define SEQ_HANDLE_SIZE_MIN 7.0f
-#define SEQ_HANDLE_SIZE_MAX 40.0f
-
+#define SEQ_HANDLE_SIZE 8.0f
#define SEQ_SCROLLER_TEXT_OFFSET 8
+#define MUTE_ALPHA 120
/* Note, Don't use SEQ_BEGIN/SEQ_END while drawing!
- * it messes up transform, - Campbell */
+ * it messes up transform. */
#undef SEQ_BEGIN
#undef SEQP_BEGIN
#undef SEQ_END
static Sequence *special_seq_update = NULL;
-void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
+void color3ubv_from_seq(Scene *curscene, Sequence *seq, uchar col[3])
{
- unsigned char blendcol[3];
- SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
+ uchar blendcol[3];
switch (seq->type) {
case SEQ_TYPE_IMAGE:
@@ -118,7 +118,7 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
break;
case SEQ_TYPE_MASK:
- UI_GetThemeColor3ubv(TH_SEQ_MASK, col); /* TODO */
+ UI_GetThemeColor3ubv(TH_SEQ_MASK, col);
break;
case SEQ_TYPE_SCENE:
@@ -129,25 +129,16 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
}
break;
- /* transitions */
+ /* Transitions use input colors, fallback for when the input is a transition itself. */
case SEQ_TYPE_CROSS:
case SEQ_TYPE_GAMCROSS:
case SEQ_TYPE_WIPE:
- UI_GetThemeColor3ubv(TH_SEQ_TRANSITION, col);
-
- /* slightly offset hue to distinguish different effects */
- if (seq->type == SEQ_TYPE_CROSS) {
- rgb_byte_set_hue_float_offset(col, 0.04);
- }
- if (seq->type == SEQ_TYPE_GAMCROSS) {
- rgb_byte_set_hue_float_offset(col, 0.08);
- }
- if (seq->type == SEQ_TYPE_WIPE) {
- rgb_byte_set_hue_float_offset(col, 0.12);
- }
+ col[0] = 130;
+ col[1] = 130;
+ col[2] = 130;
break;
- /* effects */
+ /* Effects. */
case SEQ_TYPE_TRANSFORM:
case SEQ_TYPE_SPEED:
case SEQ_TYPE_ADD:
@@ -163,47 +154,50 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
case SEQ_TYPE_COLORMIX:
UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
- /* slightly offset hue to distinguish different effects */
+ /* Slightly offset hue to distinguish different effects. */
if (seq->type == SEQ_TYPE_ADD) {
- rgb_byte_set_hue_float_offset(col, 0.04);
+ rgb_byte_set_hue_float_offset(col, 0.03);
}
else if (seq->type == SEQ_TYPE_SUB) {
- rgb_byte_set_hue_float_offset(col, 0.08);
+ rgb_byte_set_hue_float_offset(col, 0.06);
}
else if (seq->type == SEQ_TYPE_MUL) {
- rgb_byte_set_hue_float_offset(col, 0.12);
+ rgb_byte_set_hue_float_offset(col, 0.13);
}
else if (seq->type == SEQ_TYPE_ALPHAOVER) {
rgb_byte_set_hue_float_offset(col, 0.16);
}
else if (seq->type == SEQ_TYPE_ALPHAUNDER) {
- rgb_byte_set_hue_float_offset(col, 0.20);
+ rgb_byte_set_hue_float_offset(col, 0.23);
}
else if (seq->type == SEQ_TYPE_OVERDROP) {
- rgb_byte_set_hue_float_offset(col, 0.24);
+ rgb_byte_set_hue_float_offset(col, 0.26);
}
- else if (seq->type == SEQ_TYPE_GLOW) {
- rgb_byte_set_hue_float_offset(col, 0.28);
+ else if (seq->type == SEQ_TYPE_COLORMIX) {
+ rgb_byte_set_hue_float_offset(col, 0.33);
}
- else if (seq->type == SEQ_TYPE_TRANSFORM) {
- rgb_byte_set_hue_float_offset(col, 0.36);
+ else if (seq->type == SEQ_TYPE_GAUSSIAN_BLUR) {
+ rgb_byte_set_hue_float_offset(col, 0.43);
}
- else if (seq->type == SEQ_TYPE_MULTICAM) {
- rgb_byte_set_hue_float_offset(col, 0.32);
+ else if (seq->type == SEQ_TYPE_GLOW) {
+ rgb_byte_set_hue_float_offset(col, 0.46);
}
else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
- rgb_byte_set_hue_float_offset(col, 0.40);
+ rgb_byte_set_hue_float_offset(col, 0.55);
}
- else if (seq->type == SEQ_TYPE_GAUSSIAN_BLUR) {
- rgb_byte_set_hue_float_offset(col, 0.42);
+ else if (seq->type == SEQ_TYPE_SPEED) {
+ rgb_byte_set_hue_float_offset(col, 0.65);
}
- else if (seq->type == SEQ_TYPE_COLORMIX) {
- rgb_byte_set_hue_float_offset(col, 0.46);
+ else if (seq->type == SEQ_TYPE_TRANSFORM) {
+ rgb_byte_set_hue_float_offset(col, 0.75);
+ }
+ else if (seq->type == SEQ_TYPE_MULTICAM) {
+ rgb_byte_set_hue_float_offset(col, 0.85);
}
break;
case SEQ_TYPE_COLOR:
- rgb_float_to_uchar(col, colvars->col);
+ UI_GetThemeColor3ubv(TH_SEQ_COLOR, col);
break;
case SEQ_TYPE_SOUND_RAM:
@@ -226,24 +220,22 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
}
}
-static void drawseqwave(View2D *v2d,
- const bContext *C,
- SpaceSeq *sseq,
- Scene *scene,
- Sequence *seq,
- float x1,
- float y1,
- float x2,
- float y2,
- float stepsize)
+/**
+ * \param x1, x2, y1, y2: The starting and end X value to draw the wave, same for y1 and y2.
+ * \param stepsize: The width of a pixel.
+ */
+static void draw_seq_waveform(View2D *v2d,
+ const bContext *C,
+ SpaceSeq *sseq,
+ Scene *scene,
+ Sequence *seq,
+ float x1,
+ float y1,
+ float x2,
+ float y2,
+ float stepsize)
{
- /*
- * x1 is the starting x value to draw the wave,
- * x2 the end x value, same for y1 and y2
- * stepsize is width of a pixel.
- */
-
- /* offset x1 and x2 values, to match view min/max, if strip is out of bounds */
+ /* Offset x1 and x2 values, to match view min/max, if strip is out of bounds. */
int x1_offset = max_ff(v2d->cur.xmin, x1);
int x2_offset = min_ff(v2d->cur.xmax + 1.0f, x2);
@@ -257,8 +249,6 @@ static void drawseqwave(View2D *v2d,
float volume = seq->volume;
float value1, value2;
bSound *sound = seq->sound;
- FCurve *fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, NULL);
-
SoundWaveform *waveform;
if (length < 2) {
@@ -268,7 +258,7 @@ static void drawseqwave(View2D *v2d,
BLI_spin_lock(sound->spinlock);
if (!sound->waveform) {
if (!(sound->tags & SOUND_TAGS_WAVEFORM_LOADING)) {
- /* prevent sounds from reloading */
+ /* Prevent sounds from reloading. */
sound->tags |= SOUND_TAGS_WAVEFORM_LOADING;
BLI_spin_unlock(sound->spinlock);
sequencer_preview_add_sound(C, seq);
@@ -276,15 +266,14 @@ static void drawseqwave(View2D *v2d,
else {
BLI_spin_unlock(sound->spinlock);
}
- return; /* nothing to draw */
+ return; /* Nothing to draw. */
}
BLI_spin_unlock(sound->spinlock);
waveform = sound->waveform;
+ /* Waveform could not be built. */
if (waveform->length == 0) {
- /* BKE_sound_read_waveform() set an empty SoundWaveform data in case it cannot generate a
- * valid one. See T45726. */
return;
}
@@ -302,6 +291,9 @@ static void drawseqwave(View2D *v2d,
return;
}
+ /* Fcurve lookup is quite expensive, so do this after precondition. */
+ FCurve *fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, NULL);
+
GPU_blend(true);
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -328,7 +320,7 @@ static void drawseqwave(View2D *v2d,
}
}
else if (p + 1 < waveform->length) {
- /* use simple linear interpolation */
+ /* Use simple linear interpolation. */
float f = sampleoffset - p;
value1 = (1.0f - f) * value1 + f * waveform->data[p * 3 + 3];
value2 = (1.0f - f) * value2 + f * waveform->data[p * 3 + 4];
@@ -337,6 +329,7 @@ static void drawseqwave(View2D *v2d,
if (fcu && !BKE_fcurve_is_empty(fcu)) {
float evaltime = x1_offset + (i * stepsize);
volume = evaluate_fcurve(fcu, evaltime);
+ CLAMP_MIN(volume, 0.0f);
}
value1 *= volume;
value2 *= volume;
@@ -360,14 +353,13 @@ static void drawseqwave(View2D *v2d,
GPU_blend(false);
}
}
+
static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2)
{
- /* note: this used to use SEQ_BEGIN/SEQ_END, but it messes up the
- * seq->depth value, (needed by transform when doing overlap checks)
- * so for now, just use the meta's immediate children, could be fixed but
- * its only drawing - campbell */
+ /* Don't use SEQ_BEGIN/SEQ_END here,
+ * because it changes seq->depth, which is needed for transform. */
Sequence *seq;
- unsigned char col[4];
+ uchar col[4];
int chan_min = MAXSEQ;
int chan_max = 0;
@@ -401,12 +393,12 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
chan_range = (chan_max - chan_min) + 1;
draw_height = draw_range / chan_range;
- col[3] = 196; /* alpha, used for all meta children */
+ col[3] = 196; /* Alpha, used for all meta children. */
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ /* Draw only immediate children (1 level depth). */
for (seq = seqbase->first; seq; seq = seq->next) {
const int startdisp = seq->startdisp + offset;
const int enddisp = seq->enddisp + offset;
@@ -417,7 +409,13 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
float x2_chan = enddisp;
float y1_chan, y2_chan;
- color3ubv_from_seq(scene, seq, col);
+ if (seq->type == SEQ_TYPE_COLOR) {
+ SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
+ rgb_float_to_uchar(col, colvars->col);
+ }
+ else {
+ color3ubv_from_seq(scene, seq, col);
+ }
if ((seqm->flag & SEQ_MUTE) || (seq->flag & SEQ_MUTE)) {
col[3] = 64;
@@ -428,7 +426,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
immUniformColor4ubv(col);
- /* clamp within parent sequence strip bounds */
+ /* Clamp within parent sequence strip bounds. */
if (x1_chan < x1) {
x1_chan = x1;
}
@@ -448,27 +446,29 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
GPU_blend(false);
}
-/* clamp handles to defined size in pixel space */
-static float draw_seq_handle_size_get_clamped(Sequence *seq, const float pixelx)
+/* Get handle width in pixels. */
+float sequence_handle_size_get_clamped(Sequence *seq, const float pixelx)
{
- const float minhandle = pixelx * SEQ_HANDLE_SIZE_MIN;
- const float maxhandle = pixelx * SEQ_HANDLE_SIZE_MAX;
- float size = CLAMPIS(seq->handsize, minhandle, maxhandle);
+ const float maxhandle = (pixelx * SEQ_HANDLE_SIZE) * U.pixelsize;
- /* ensure we're not greater than half width */
- return min_ff(size, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx);
+ /* Ensure that handle is not wider, than half of strip. */
+ return min_ff(maxhandle, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx);
}
-/* draw a handle, for each end of a sequence strip */
+/* Draw a handle, on left or right side of strip. */
static void draw_seq_handle(View2D *v2d,
Sequence *seq,
const float handsize_clamped,
const short direction,
- unsigned int pos)
+ uint pos,
+ bool seq_active,
+ float pixelx,
+ bool y_threshold)
{
- float v1[2], v2[2], v3[2], rx1 = 0, rx2 = 0; // for triangles and rect
+ float rx1 = 0, rx2 = 0;
float x1, x2, y1, y2;
- unsigned int whichsel = 0;
+ uint whichsel = 0;
+ uchar col[4];
x1 = seq->startdisp;
x2 = seq->enddisp;
@@ -476,35 +476,18 @@ static void draw_seq_handle(View2D *v2d,
y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
- /* set up co-ordinates/dimensions for either left or right handle */
+ /* Set up co-ordinates and dimensions for either left or right handle. */
if (direction == SEQ_LEFTHANDLE) {
rx1 = x1;
- rx2 = x1 + handsize_clamped * 0.75f;
-
- v1[0] = x1 + handsize_clamped / 4;
- v1[1] = y1 + (((y1 + y2) / 2.0f - y1) / 2);
- v2[0] = x1 + handsize_clamped / 4;
- v2[1] = y2 - (((y1 + y2) / 2.0f - y1) / 2);
- v3[0] = v2[0] + handsize_clamped / 4;
- v3[1] = (y1 + y2) / 2.0f;
-
+ rx2 = x1 + handsize_clamped;
whichsel = SEQ_LEFTSEL;
}
else if (direction == SEQ_RIGHTHANDLE) {
- rx1 = x2 - handsize_clamped * 0.75f;
+ rx1 = x2 - handsize_clamped;
rx2 = x2;
-
- v1[0] = x2 - handsize_clamped / 4;
- v1[1] = y1 + (((y1 + y2) / 2.0f - y1) / 2);
- v2[0] = x2 - handsize_clamped / 4;
- v2[1] = y2 - (((y1 + y2) / 2.0f - y1) / 2);
- v3[0] = v2[0] - handsize_clamped / 4;
- v3[1] = (y1 + y2) / 2.0f;
-
whichsel = SEQ_RIGHTSEL;
}
- /* draw! */
if (!(seq->type & SEQ_TYPE_EFFECT) || BKE_sequence_effect_get_num_inputs(seq->type) == 0) {
GPU_blend(true);
@@ -512,69 +495,135 @@ static void draw_seq_handle(View2D *v2d,
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
if (seq->flag & whichsel) {
- immUniformColor4ub(0, 0, 0, 80);
- }
- else if (seq->flag & SELECT) {
- immUniformColor4ub(255, 255, 255, 30);
+ if (seq_active) {
+ UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col);
+ }
+ else {
+ UI_GetThemeColor3ubv(TH_SEQ_SELECTED, col);
+ /* Make handles slightly brighter than the outlines. */
+ UI_GetColorPtrShade3ubv(col, col, 50);
+ }
+ col[3] = 255;
+ immUniformColor4ubv(col);
}
else {
- immUniformColor4ub(0, 0, 0, 22);
+ immUniformColor4ub(0, 0, 0, 50);
}
immRectf(pos, rx1, y1, rx2, y2);
+ GPU_blend(false);
+ }
- if (seq->flag & whichsel) {
- immUniformColor4ub(255, 255, 255, 200);
- }
- else {
- immUniformColor4ub(0, 0, 0, 50);
- }
+ /* Draw numbers for start and end of the strip next to its handles. */
+ if (y_threshold &&
+ (((seq->flag & SELECT) && (G.moving & G_TRANSFORM_SEQ)) || (seq->flag & whichsel))) {
- immBegin(GPU_PRIM_TRIS, 3);
- immVertex2fv(pos, v1);
- immVertex2fv(pos, v2);
- immVertex2fv(pos, v3);
- immEnd();
+ char numstr[64];
+ size_t numstr_len;
+ const int fontid = BLF_default();
+ BLF_set_default();
- GPU_blend(false);
+ /* Calculate if strip is wide enough for showing the labels. */
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d%d", seq->startdisp, seq->enddisp);
+ float tot_width = BLF_width(fontid, numstr, numstr_len);
+
+ if ((x2 - x1) / pixelx > 20 + tot_width) {
+ col[0] = col[1] = col[2] = col[3] = 255;
+ float text_margin = 1.2f * handsize_clamped;
+
+ if (direction == SEQ_LEFTHANDLE) {
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->startdisp);
+ x1 += text_margin;
+ y1 += 0.09f;
+ }
+ else {
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
+ x1 = x2 - (text_margin + pixelx * BLF_width(fontid, numstr, numstr_len));
+ y1 += 0.09f;
+ }
+ UI_view2d_text_cache_add(v2d, x1, y1, numstr, numstr_len, col);
+ }
}
+}
- if ((G.moving & G_TRANSFORM_SEQ) || (seq->flag & whichsel)) {
- const char col[4] = {255, 255, 255, 255};
- char numstr[32];
- size_t numstr_len;
+static void draw_seq_outline(Sequence *seq,
+ uint pos,
+ float x1,
+ float x2,
+ float y1,
+ float y2,
+ float pixelx,
+ float pixely,
+ bool seq_active)
+{
+ uchar col[3];
+
+ /* Get the color for the outline. */
+ if (seq_active && (seq->flag & SELECT)) {
+ UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col);
+ }
+ else if (seq->flag & SELECT) {
+ UI_GetThemeColor3ubv(TH_SEQ_SELECTED, col);
+ }
+ else {
+ /* Color for unselected strips is a bit darker than the background. */
+ UI_GetThemeColor3ubv(TH_BACK, col);
+ UI_GetColorPtrShade3ubv(col, col, -40);
+ }
- if (direction == SEQ_LEFTHANDLE) {
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->startdisp);
- x1 = rx1;
- y1 -= 0.45f;
+ /* Outline while translating strips:
+ * - Slightly lighter.
+ * - Red when overlapping with other strips.
+ */
+ if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) {
+ if (seq->flag & SEQ_OVERLAP) {
+ col[0] = 255;
+ col[1] = col[2] = 33;
}
else {
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
- x1 = x2 - handsize_clamped * 0.75f;
- y1 = y2 + 0.05f;
+ UI_GetColorPtrShade3ubv(col, col, 70);
}
- UI_view2d_text_cache_add(v2d, x1, y1, numstr, numstr_len, col);
+ }
+ immUniformColor3ubv(col);
+
+ /* 2px wide outline for selected strips. */
+ /* XXX: some platforms don't support glLines wider than 1px (see T57570),
+ * draw outline as four boxes instead.
+ */
+ if (seq->flag & SELECT) {
+ /* Left */
+ immRectf(pos, x1 - pixelx, y1, x1 + pixelx, y2);
+ /* Bottom */
+ immRectf(pos, x1 - pixelx, y1, x2 + pixelx, y1 + 2 * pixely);
+ /* Right */
+ immRectf(pos, x2 - pixelx, y1, x2 + pixelx, y2);
+ /* Top */
+ immRectf(pos, x1 - pixelx, y2 - 2 * pixely, x2 + pixelx, y2);
+ }
+ else {
+ /* 1px wide outline for unselected strips. */
+ imm_draw_box_wire_2d(pos, x1, y1, x2, y2);
}
}
-/* draw info text on a sequence strip */
+/* Draw info text on a sequence strip. */
static void draw_seq_text(View2D *v2d,
- SpaceSeq *sseq,
Sequence *seq,
+ SpaceSeq *sseq,
float x1,
float x2,
float y1,
float y2,
- const unsigned char background_col[3])
+ bool seq_active,
+ bool y_threshold)
{
rctf rect;
char str[32 + FILE_MAX];
size_t str_len;
const char *name = seq->name + 2;
- char col[4];
+ uchar col[4];
- /* note, all strings should include 'name' */
+ /* All strings should include name. */
if (name[0] == '\0') {
name = BKE_sequence_give_name(seq);
}
@@ -640,9 +689,10 @@ static void draw_seq_text(View2D *v2d,
str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
}
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
- /* If a waveform is drawn, we don't want to overlay it with text,
- * as it would make both hard to read. */
- if ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)) {
+ /* If a waveform is drawn, avoid to draw text when there is not enough vertical space. */
+ if (!y_threshold && (sseq->flag & SEQ_NO_WAVEFORMS) == 0 &&
+ ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) {
+
str[0] = 0;
str_len = 0;
}
@@ -663,23 +713,26 @@ static void draw_seq_text(View2D *v2d,
seq->len);
}
else {
- /* should never get here!, but might with files from future */
+ /* Should never get here!, but might with files from future. */
BLI_assert(0);
str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len);
}
- if (seq->flag & SELECT) {
- col[0] = col[1] = col[2] = 255;
- }
- else if ((((int)background_col[0] + (int)background_col[1] + (int)background_col[2]) / 3) < 50) {
- col[0] = col[1] = col[2] = 80; /* use lighter text color for dark background */
- }
- else {
- col[0] = col[1] = col[2] = 0;
- }
+ /* White text for the active strip. */
+ col[0] = col[1] = col[2] = seq_active ? 255 : 10;
col[3] = 255;
+ /* Make the text duller when the strip is muted. */
+ if (seq->flag & SEQ_MUTE) {
+ if (seq_active) {
+ UI_GetColorPtrShade3ubv(col, col, -70);
+ }
+ else {
+ UI_GetColorPtrShade3ubv(col, col, 15);
+ }
+ }
+
rect.xmin = x1;
rect.ymin = y1;
rect.xmax = x2;
@@ -688,11 +741,10 @@ static void draw_seq_text(View2D *v2d,
UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col);
}
-static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, unsigned int pos)
+static void draw_sequence_extensions(Scene *scene, Sequence *seq, uint pos, float pixely)
{
- float x1, x2, y1, y2, pixely;
- unsigned char col[4], blendcol[3];
- View2D *v2d = &ar->v2d;
+ float x1, x2, y1, y2;
+ uchar col[4], blend_col[3];
x1 = seq->startdisp;
x2 = seq->enddisp;
@@ -700,291 +752,461 @@ static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, u
y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
- pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- if (pixely <= 0) {
- return; /* can happen when the view is split/resized */
+ color3ubv_from_seq(scene, seq, col);
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrShade3ubv(col, col, 50);
}
+ col[3] = seq->flag & SEQ_MUTE ? MUTE_ALPHA : 200;
+ UI_GetColorPtrShade3ubv(col, blend_col, 10);
- blendcol[0] = blendcol[1] = blendcol[2] = 120;
+ if (seq->startofs) {
+ immUniformColor4ubv(col);
+ immRectf(pos, (float)(seq->start), y1 - pixely, x1, y1 - SEQ_STRIP_OFSBOTTOM);
- if (seq->startofs || seq->endofs) {
- GPU_blend(true);
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ /* Outline. */
+ immUniformColor3ubv(blend_col);
+ imm_draw_box_wire_2d(pos, x1, y1 - pixely, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM);
+ }
+ if (seq->endofs) {
+ immUniformColor4ubv(col);
+ immRectf(pos, x2, y2 + pixely, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
- color3ubv_from_seq(scene, seq, col);
+ /* Outline. */
+ immUniformColor3ubv(blend_col);
+ imm_draw_box_wire_2d(
+ pos, x2, y2 + pixely, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
+ }
+ GPU_blend(false);
+}
- if (seq->flag & SELECT) {
- UI_GetColorPtrShade3ubv(col, col, -50);
- }
+static void draw_color_strip_band(Sequence *seq, uint pos, float text_margin_y, float y1)
+{
+ uchar col[4];
+ SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
- if (seq->flag & SEQ_MUTE) {
- col[3] = 64;
- }
- else {
- if (seq->flag & SELECT) {
- col[3] = 170;
- }
- else {
- col[3] = 80;
- }
- }
+ rgb_float_to_uchar(col, colvars->col);
+ if (seq->flag & SEQ_MUTE) {
+ GPU_blend(true);
+ col[3] = MUTE_ALPHA;
+ }
+ else {
+ col[3] = 255;
}
- if (seq->startofs) {
- immUniformColor4ubv(col);
- immRectf(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
+ immUniformColor4ubv(col);
- immUniformColor3ubvAlpha(col, col[3] + 50);
+ immRectf(pos, seq->startdisp, y1, seq->enddisp, text_margin_y);
- /* outline */
- imm_draw_box_wire_2d(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
- }
- if (seq->endofs) {
- immUniformColor4ubv(col);
- immRectf(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
+ /* 1px line to better separate the color band. */
+ UI_GetColorPtrShade3ubv(col, col, -20);
+ immUniformColor4ubv(col);
- immUniformColor3ubvAlpha(col, col[3] + 50);
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, seq->startdisp, text_margin_y);
+ immVertex2f(pos, seq->enddisp, text_margin_y);
+ immEnd();
- /* outline */
- imm_draw_box_wire_2d(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
+ if (seq->flag & SEQ_MUTE) {
+ GPU_blend(false);
}
+}
- if (seq->startofs || seq->endofs) {
- GPU_blend(false);
+static void draw_seq_background(Scene *scene,
+ Sequence *seq,
+ uint pos,
+ float x1,
+ float x2,
+ float y1,
+ float y2,
+ bool is_single_image)
+{
+ uchar col[4];
+
+ /* Get the correct color per strip type, transitions use their inputs ones. */
+ if (ELEM(seq->type, SEQ_TYPE_CROSS, SEQ_TYPE_GAMCROSS, SEQ_TYPE_WIPE)) {
+ Sequence *seq1 = seq->seq1;
+ if (seq1->type == SEQ_TYPE_COLOR) {
+ SolidColorVars *colvars = (SolidColorVars *)seq1->effectdata;
+ rgb_float_to_uchar(col, colvars->col);
+ }
+ else {
+ color3ubv_from_seq(scene, seq1, col);
+ }
+ }
+ else {
+ color3ubv_from_seq(scene, seq, col);
}
- if (seq->startstill || seq->endstill) {
+ if (seq->flag & SEQ_MUTE) {
GPU_blend(true);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- color3ubv_from_seq(scene, seq, col);
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5f, 60);
+ col[3] = MUTE_ALPHA;
+ }
+ else {
+ col[3] = 255;
+ }
+ immUniformColor4ubv(col);
+
+ /* Draw the main strip body. */
+ if (is_single_image) {
+ immRectf(pos,
+ BKE_sequence_tx_get_final_left(seq, false),
+ y1,
+ BKE_sequence_tx_get_final_right(seq, false),
+ y2);
+ }
+ else {
+ immRectf(pos, x1, y1, x2, y2);
+ }
- if (seq->flag & SEQ_MUTE) {
- col[3] = 96;
+ /* Draw background for hold still regions. */
+ if (!is_single_image && (seq->startstill || seq->endstill)) {
+ UI_GetColorPtrShade3ubv(col, col, -35);
+ immUniformColor4ubv(col);
+
+ if (seq->startstill) {
+ immRectf(pos, seq->startdisp, y1, (float)(seq->start), y2);
+ }
+ if (seq->endstill) {
+ immRectf(pos, (float)(seq->start + seq->len), y1, seq->enddisp, y2);
+ }
+ }
+
+ /* Draw right half of transition strips. */
+ if (ELEM(seq->type, SEQ_TYPE_CROSS, SEQ_TYPE_GAMCROSS, SEQ_TYPE_WIPE)) {
+ float vert_pos[3][2];
+ Sequence *seq1 = seq->seq1;
+ Sequence *seq2 = seq->seq2;
+
+ if (seq2->type == SEQ_TYPE_COLOR) {
+ SolidColorVars *colvars = (SolidColorVars *)seq2->effectdata;
+ rgb_float_to_uchar(col, colvars->col);
}
else {
- if (seq->flag & SELECT) {
- col[3] = 255;
- }
- else {
- col[3] = 170;
+ color3ubv_from_seq(scene, seq2, col);
+ /* If the transition inputs are of the same type, draw the right side slightly darker. */
+ if (seq1->type == seq2->type) {
+ UI_GetColorPtrShade3ubv(col, col, -15);
}
}
-
immUniformColor4ubv(col);
- }
- if (seq->startstill) {
- immRectf(pos, x1, y1, (float)(seq->start), y2);
- }
- if (seq->endstill) {
- immRectf(pos, (float)(seq->start + seq->len), y1, x2, y2);
+ copy_v2_fl2(vert_pos[0], x1, y2);
+ copy_v2_fl2(vert_pos[1], x2, y2);
+ copy_v2_fl2(vert_pos[2], x2, y1);
+
+ immBegin(GPU_PRIM_TRIS, 3);
+ immVertex2fv(pos, vert_pos[0]);
+ immVertex2fv(pos, vert_pos[1]);
+ immVertex2fv(pos, vert_pos[2]);
+ immEnd();
}
- if (seq->startstill || seq->endstill) {
+ if (seq->flag & SEQ_MUTE) {
GPU_blend(false);
}
}
-/*
- * Draw a sequence strip, bounds check already made
- * ARegion is currently only used to get the windows width in pixels
- * so wave file sample drawing precision is zoom adjusted
- */
-static void draw_seq_strip(const bContext *C,
- SpaceSeq *sseq,
- Scene *scene,
- ARegion *ar,
- Sequence *seq,
- int outline_tint,
- float pixelx)
+static void draw_seq_locked(float x1, float y1, float x2, float y2)
{
- View2D *v2d = &ar->v2d;
- float x1, x2, y1, y2;
- unsigned char col[4], background_col[4], is_single_image;
- const float handsize_clamped = draw_seq_handle_size_get_clamped(seq, pixelx);
+ GPU_blend(true);
- /* we need to know if this is a single image/color or not for drawing */
- is_single_image = (char)BKE_sequence_single_check(seq);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
- /* body */
- x1 = (seq->startstill) ? seq->start : seq->startdisp;
- y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
- x2 = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
- y2 = seq->machine + SEQ_STRIP_OFSTOP;
+ immUniform4f("color1", 1.0f, 1.0f, 1.0f, 0.0f);
+ immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.25f);
+ immUniform1i("size1", 8);
+ immUniform1i("size2", 4);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immRectf(pos, x1, y1, x2, y2);
+
+ immUnbindProgram();
+ GPU_blend(false);
+}
+
+static void draw_seq_invalid(float x1, float x2, float y2, float text_margin_y)
+{
+ GPU_blend(true);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(1.0f, 0.0f, 0.0f, 0.9f);
+ immRectf(pos, x1, y2, x2, text_margin_y);
- /* get the correct color per strip type*/
- // color3ubv_from_seq(scene, seq, col);
- color3ubv_from_seq(scene, seq, background_col);
+ immUnbindProgram();
+ GPU_blend(false);
+}
- if (seq->flag & SEQ_MUTE) {
- background_col[3] = 128;
+static void calculate_seq_text_offsets(
+ View2D *v2d, Sequence *seq, float *x1, float *x2, float pixelx)
+{
+ const float handsize_clamped = sequence_handle_size_get_clamped(seq, pixelx);
+ float text_margin = 2.0f * handsize_clamped;
- GPU_blend(true);
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ *x1 += text_margin;
+ *x2 -= text_margin;
+
+ float scroller_vert_xoffs = (V2D_SCROLL_HANDLE_WIDTH + SEQ_SCROLLER_TEXT_OFFSET) * pixelx;
+
+ /* Info text on the strip. */
+ if (*x1 < v2d->cur.xmin + scroller_vert_xoffs) {
+ *x1 = v2d->cur.xmin + scroller_vert_xoffs;
}
- else {
- background_col[3] = 255;
+ else if (*x1 > v2d->cur.xmax) {
+ *x1 = v2d->cur.xmax;
}
-
- if (seq->flag & SELECT) {
- UI_GetColorPtrShade3ubv(background_col, background_col, -50);
+ if (*x2 < v2d->cur.xmin) {
+ *x2 = v2d->cur.xmin;
}
+ else if (*x2 > v2d->cur.xmax) {
+ *x2 = v2d->cur.xmax;
+ }
+}
- immUniformColor4ubv(background_col);
+static void fcurve_batch_add_verts(GPUVertBuf *vbo,
+ float y1,
+ float y2,
+ float y_height,
+ int cfra,
+ float curve_val,
+ unsigned int *vert_count)
+{
+ float vert_pos[2][2];
- /* draw the main strip body */
- if (is_single_image) { /* single image */
- immRectf(pos,
- BKE_sequence_tx_get_final_left(seq, false),
- y1,
- BKE_sequence_tx_get_final_right(seq, false),
- y2);
+ copy_v2_fl2(vert_pos[0], cfra, (curve_val * y_height) + y1);
+ copy_v2_fl2(vert_pos[1], cfra, y2);
+
+ GPU_vertbuf_vert_set(vbo, *vert_count, vert_pos[0]);
+ GPU_vertbuf_vert_set(vbo, *vert_count + 1, vert_pos[1]);
+ *vert_count += 2;
+}
+
+/**
+ * Draw f-curves as darkened regions of the strip:
+ * - Volume for sound strips.
+ * - Opacity for the other types.
+ */
+static void draw_seq_fcurve(
+ Scene *scene, View2D *v2d, Sequence *seq, float x1, float y1, float x2, float y2, float pixelx)
+{
+ FCurve *fcu;
+
+ if (seq->type == SEQ_TYPE_SOUND_RAM) {
+ fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, NULL);
}
- else { /* normal operation */
- immRectf(pos, x1, y1, x2, y2);
+ else {
+ fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "blend_alpha", 0, NULL);
}
- if (seq->flag & SEQ_MUTE) {
- GPU_blend(false);
- }
+ if (fcu && !BKE_fcurve_is_empty(fcu)) {
- if (!is_single_image) {
- if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
- draw_sequence_extensions(scene, ar, seq, pos);
+ /* Clamp curve evaluation to the editor's borders. */
+ int eval_start = max_ff(x1, v2d->cur.xmin);
+ int eval_end = min_ff(x2, v2d->cur.xmax + 1);
+
+ int eval_step = max_ii(1, floor(pixelx));
+
+ if (eval_start >= eval_end) {
+ return;
}
- }
- draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos);
- draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos);
+ GPUVertFormat format = {0};
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- x1 = seq->startdisp;
- x2 = seq->enddisp;
+ uint max_verts = 2 * ((eval_end - eval_start) / eval_step + 1);
+ GPU_vertbuf_data_alloc(vbo, max_verts);
+ uint vert_count = 0;
- immUnbindProgram();
+ const float y_height = y2 - y1;
+ float curve_val;
+ float prev_val = INT_MIN;
+ bool skip = false;
- /* draw sound wave */
- if (seq->type == SEQ_TYPE_SOUND_RAM) {
- if (!(sseq->flag & SEQ_NO_WAVEFORMS)) {
- drawseqwave(
- v2d, C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
- }
- }
+ for (int cfra = eval_start; cfra <= eval_end; cfra += eval_step) {
+ curve_val = evaluate_fcurve(fcu, cfra);
+ CLAMP(curve_val, 0.0f, 1.0f);
- /* draw lock */
- if (seq->flag & SEQ_LOCK) {
- GPU_blend(true);
+ /* Avoid adding adjacent verts that have the same value. */
+ if (curve_val == prev_val && cfra < eval_end - eval_step) {
+ skip = true;
+ continue;
+ }
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
+ /* If some frames were skipped above, we need to close the shape. */
+ if (skip) {
+ fcurve_batch_add_verts(vbo, y1, y2, y_height, cfra - eval_step, prev_val, &vert_count);
+ skip = false;
+ }
- immUniform4f("color1", 1.0f, 1.0f, 1.0f, 0.125f);
- immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.125f);
- immUniform1i("size1", 8);
- immUniform1i("size2", 8);
+ fcurve_batch_add_verts(vbo, y1, y2, y_height, cfra, curve_val, &vert_count);
+ prev_val = curve_val;
+ }
- immRectf(pos, x1, y1, x2, y2);
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_vertbuf_data_len_set(vbo, vert_count);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_batch_uniform_4f(batch, "color", 0.0f, 0.0f, 0.0f, 0.15f);
+ GPU_blend(true);
- immUnbindProgram();
+ if (vert_count > 0) {
+ GPU_batch_draw(batch);
+ }
GPU_blend(false);
+ GPU_batch_discard(batch);
}
+}
- if (!BKE_sequence_is_valid_check(seq)) {
- GPU_blend(true);
+/* Draw visible strips. Bounds check are already made. */
+static void draw_seq_strip(const bContext *C,
+ SpaceSeq *sseq,
+ Scene *scene,
+ ARegion *region,
+ Sequence *seq,
+ float pixelx,
+ bool seq_active)
+{
+ View2D *v2d = &region->v2d;
+ float x1, x2, y1, y2;
+ const float handsize_clamped = sequence_handle_size_get_clamped(seq, pixelx);
+ float pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
+ /* Check if we are doing "solo preview". */
+ bool is_single_image = (char)BKE_sequence_single_check(seq);
- immUniform4f("color1", 1.0f, 0.0f, 0.0f, 1.0f);
- immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.0f);
- immUniform1i("size1", 8);
- immUniform1i("size2", 8);
+ /* Draw strip body. */
+ x1 = (seq->startstill) ? seq->start : seq->startdisp;
+ y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
+ x2 = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
+ y2 = seq->machine + SEQ_STRIP_OFSTOP;
- immRectf(pos, x1, y1, x2, y2);
+ /* Calculate height needed for drawing text on strip. */
+ float text_margin_y = y2 - min_ff(0.40f, 20 * U.dpi_fac * pixely);
- immUnbindProgram();
+ /* Is there enough space for drawing something else than text? */
+ bool y_threshold = ((y2 - y1) / pixely) > 20 * U.dpi_fac;
- GPU_blend(false);
- }
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- color3ubv_from_seq(scene, seq, col);
+ draw_seq_background(scene, seq, pos, x1, x2, y1, y2, is_single_image);
- /* draw the strip outline */
- color3ubv_from_seq(scene, seq, col);
- if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) {
- if (seq->flag & SEQ_OVERLAP) {
- col[0] = 255;
- col[1] = col[2] = 40;
- }
- else {
- UI_GetColorPtrShade3ubv(col, col, 120 + outline_tint);
- }
+ /* Draw a color band inside color strip. */
+ if (seq->type == SEQ_TYPE_COLOR && y_threshold) {
+ draw_color_strip_band(seq, pos, text_margin_y, y1);
}
- else {
- UI_GetColorPtrShade3ubv(col, col, outline_tint);
+
+ /* Draw strip offsets when flag is enabled or during "solo preview". */
+ if (!is_single_image && (seq->startofs || seq->endofs) && pixely > 0) {
+ if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
+ draw_sequence_extensions(scene, seq, pos, pixely);
+ }
}
+ immUnbindProgram();
+
+ x1 = seq->startdisp;
+ x2 = seq->enddisp;
+
if ((seq->type == SEQ_TYPE_META) ||
((seq->type == SEQ_TYPE_SCENE) && (seq->flag & SEQ_SCENE_STRIPS))) {
drawmeta_contents(scene, seq, x1, y1, x2, y2);
}
- pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- /* TODO: add back stippled line for muted strips? */
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ if (sseq->flag & SEQ_SHOW_FCURVES) {
+ draw_seq_fcurve(scene, v2d, seq, x1, y1, x2, y2, pixelx);
+ }
- if (seq->flag & SEQ_MUTE) {
- col[3] = 96;
+ /* Draw sound strip waveform. */
+ if ((seq->type == SEQ_TYPE_SOUND_RAM) && (sseq->flag & SEQ_NO_WAVEFORMS) == 0) {
+ draw_seq_waveform(v2d,
+ C,
+ sseq,
+ scene,
+ seq,
+ x1,
+ y_threshold ? y1 + 0.05f : y1,
+ x2,
+ y_threshold ? text_margin_y : y2,
+ BLI_rctf_size_x(&region->v2d.cur) / region->winx);
+ }
- GPU_blend(true);
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ /* Draw locked state. */
+ if (seq->flag & SEQ_LOCK) {
+ draw_seq_locked(x1, y1, x2, y2);
+ }
- immUniformColor4ubv(col);
+ /* Draw Red line on the top of invalid strip (Missing media). */
+ if (!BKE_sequence_is_valid_check(seq)) {
+ draw_seq_invalid(x1, x2, y2, text_margin_y);
}
- else {
- immUniformColor3ubv(col);
+
+ pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ if ((seq->flag & SEQ_LOCK) == 0) {
+ draw_seq_handle(
+ v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos, seq_active, pixelx, y_threshold);
+ draw_seq_handle(
+ v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos, seq_active, pixelx, y_threshold);
}
- imm_draw_box_wire_2d(pos, x1, y1, x2, y2); /* outline */
+ draw_seq_outline(seq, pos, x1, x2, y1, y2, pixelx, pixely, seq_active);
immUnbindProgram();
- /* calculate if seq is long enough to print a name */
- x1 = seq->startdisp + handsize_clamped;
- x2 = seq->enddisp - handsize_clamped;
+ calculate_seq_text_offsets(v2d, seq, &x1, &x2, pixelx);
- float scroller_vert_xoffs = (V2D_SCROLL_HANDLE_WIDTH + SEQ_SCROLLER_TEXT_OFFSET) * pixelx;
-
- /* info text on the strip */
- if (x1 < v2d->cur.xmin + scroller_vert_xoffs) {
- x1 = v2d->cur.xmin + scroller_vert_xoffs;
- }
- else if (x1 > v2d->cur.xmax) {
- x1 = v2d->cur.xmax;
- }
- if (x2 < v2d->cur.xmin) {
- x2 = v2d->cur.xmin;
- }
- else if (x2 > v2d->cur.xmax) {
- x2 = v2d->cur.xmax;
+ /* Don't draw strip if there is not enough vertical or horizontal space. */
+ if (((x2 - x1) > 32 * pixelx * U.dpi_fac) && ((y2 - y1) > 8 * pixely * U.dpi_fac)) {
+ /* Depending on the vertical space, draw text on top or in the center of strip. */
+ draw_seq_text(
+ v2d, seq, sseq, x1, x2, y_threshold ? text_margin_y : y1, y2, seq_active, y_threshold);
}
+}
- /* nice text here would require changing the view matrix for texture text */
- if ((x2 - x1) / pixelx > 32) {
- draw_seq_text(v2d, sseq, seq, x1, x2, y1, y2, background_col);
+static void draw_effect_inputs_highlight(Sequence *seq)
+{
+ Sequence *seq1 = seq->seq1;
+ Sequence *seq2 = seq->seq2;
+ Sequence *seq3 = seq->seq3;
+ GPU_blend(true);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ub(255, 255, 255, 48);
+ immRectf(pos,
+ seq1->startdisp,
+ seq1->machine + SEQ_STRIP_OFSBOTTOM,
+ seq1->enddisp,
+ seq1->machine + SEQ_STRIP_OFSTOP);
+
+ if (seq2 && seq2 != seq1) {
+ immRectf(pos,
+ seq2->startdisp,
+ seq2->machine + SEQ_STRIP_OFSBOTTOM,
+ seq2->enddisp,
+ seq2->machine + SEQ_STRIP_OFSTOP);
}
+ if (seq3 && !ELEM(seq3, seq1, seq2)) {
+ immRectf(pos,
+ seq3->startdisp,
+ seq3->machine + SEQ_STRIP_OFSBOTTOM,
+ seq3->enddisp,
+ seq3->machine + SEQ_STRIP_OFSTOP);
+ }
+ immUnbindProgram();
+ GPU_blend(false);
}
void sequencer_special_update_set(Sequence *seq)
@@ -1000,10 +1222,10 @@ Sequence *ED_sequencer_special_preview_get(void)
void ED_sequencer_special_preview_set(bContext *C, const int mval[2])
{
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
int hand;
Sequence *seq;
- seq = find_nearest_seq(scene, &ar->v2d, &hand, mval);
+ seq = find_nearest_seq(scene, &region->v2d, &hand, mval);
sequencer_special_update_set(seq);
}
@@ -1055,18 +1277,15 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain,
if (special_seq_update) {
ibuf = BKE_sequencer_give_ibuf_direct(&context, cfra + frame_ofs, special_seq_update);
}
- else if (!U.prefetchframes) { // XXX || (G.f & G_PLAYANIM) == 0) {
- ibuf = BKE_sequencer_give_ibuf(&context, cfra + frame_ofs, sseq->chanshown);
- }
else {
- ibuf = BKE_sequencer_give_ibuf_threaded(&context, cfra + frame_ofs, sseq->chanshown);
+ ibuf = BKE_sequencer_give_ibuf(&context, cfra + frame_ofs, sseq->chanshown);
}
if (fb) {
GPU_framebuffer_bind(fb);
}
- /* restore state so real rendering would be canceled (if needed) */
+ /* Restore state so real rendering would be canceled if needed. */
G.is_break = is_break;
return ibuf;
@@ -1102,7 +1321,7 @@ static void sequencer_check_scopes(SequencerScopes *scopes, ImBuf *ibuf)
}
}
-static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scope_cb)(ImBuf *ibuf))
+static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scope_fn)(ImBuf *ibuf))
{
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
ImBuf *scope;
@@ -1110,7 +1329,7 @@ static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scop
IMB_colormanagement_imbuf_make_display_space(
display_ibuf, &scene->view_settings, &scene->display_settings);
- scope = make_scope_cb(display_ibuf);
+ scope = make_scope_fn(display_ibuf);
IMB_freeImBuf(display_ibuf);
@@ -1127,17 +1346,17 @@ static void sequencer_display_size(Scene *scene, float r_viewrect[2])
static void sequencer_draw_gpencil(const bContext *C)
{
- /* draw grease-pencil (image aligned) */
+ /* Draw grease-pencil (image aligned). */
ED_annotation_draw_2dimage(C);
- /* ortho at pixel level */
+ /* Ortho at pixel level. */
UI_view2d_view_restore(C);
- /* draw grease-pencil (screen aligned) */
+ /* Draw grease-pencil (screen aligned). */
ED_annotation_draw_view2d(C, 0);
}
-/* draws content borders plus safety borders if needed */
+/* Draw content and safety borders borders. */
static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, const Scene *scene)
{
float x1 = v2d->tot.xmin;
@@ -1147,7 +1366,7 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons
GPU_line_width(1.0f);
- /* border */
+ /* Draw border. */
const uint shdr_pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -1164,7 +1383,7 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons
imm_draw_box_wire_2d(shdr_pos, x1 - 0.5f, y1 - 0.5f, x2 + 0.5f, y2 + 0.5f);
- /* safety border */
+ /* Draw safety border. */
if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) {
immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
@@ -1186,10 +1405,10 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons
}
#if 0
-void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq)
+void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *region, SpaceSeq *sseq)
{
- /* NOTE: sequencer mask editing isnt finished, the draw code is working but editing not,
- * for now just disable drawing since the strip frame will likely be offset */
+ /* NOTE: sequencer mask editing isnt finished, the draw code is working but editing not.
+ * For now just disable drawing since the strip frame will likely be offset. */
// if (sc->mode == SC_MODE_MASKEDIT)
if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
@@ -1205,7 +1424,7 @@ void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *ar, Space
height = (scene->r.size * scene->r.ysch) / 100;
ED_mask_draw_region(mask,
- ar,
+ region,
0,
0,
0, /* TODO */
@@ -1231,68 +1450,67 @@ static void seq_prefetch_wm_notify(const bContext *C, Scene *scene)
}
static void *sequencer_OCIO_transform_ibuf(
- const bContext *C, ImBuf *ibuf, bool *glsl_used, int *format, int *type)
+ const bContext *C, ImBuf *ibuf, bool *r_glsl_used, int *r_format, int *r_type)
{
void *display_buffer;
void *cache_handle = NULL;
bool force_fallback = false;
- *glsl_used = false;
+ *r_glsl_used = false;
force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL);
force_fallback |= (ibuf->dither != 0.0f);
+ /* Fallback to CPU based color space conversion. */
if (force_fallback) {
- /* Fallback to CPU based color space conversion */
- *glsl_used = false;
- *format = GL_RGBA;
- *type = GL_UNSIGNED_BYTE;
+ *r_glsl_used = false;
+ *r_format = GL_RGBA;
+ *r_type = GL_UNSIGNED_BYTE;
display_buffer = NULL;
}
else if (ibuf->rect_float) {
display_buffer = ibuf->rect_float;
if (ibuf->channels == 4) {
- *format = GL_RGBA;
+ *r_format = GL_RGBA;
}
else if (ibuf->channels == 3) {
- *format = GL_RGB;
+ *r_format = GL_RGB;
}
else {
BLI_assert(!"Incompatible number of channels for float buffer in sequencer");
- *format = GL_RGBA;
+ *r_format = GL_RGBA;
display_buffer = NULL;
}
- *type = GL_FLOAT;
+ *r_type = GL_FLOAT;
if (ibuf->float_colorspace) {
- *glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(
+ *r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(
C, ibuf->float_colorspace, ibuf->dither, true);
}
else {
- *glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true);
+ *r_glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true);
}
}
else if (ibuf->rect) {
display_buffer = ibuf->rect;
- *format = GL_RGBA;
- *type = GL_UNSIGNED_BYTE;
+ *r_format = GL_RGBA;
+ *r_type = GL_UNSIGNED_BYTE;
- *glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(
+ *r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(
C, ibuf->rect_colorspace, ibuf->dither, false);
}
else {
- *format = GL_RGBA;
- *type = GL_UNSIGNED_BYTE;
+ *r_format = GL_RGBA;
+ *r_type = GL_UNSIGNED_BYTE;
display_buffer = NULL;
}
- /* there's a data to be displayed, but GLSL is not initialized
- * properly, in this case we fallback to CPU-based display transform
- */
- if ((ibuf->rect || ibuf->rect_float) && !*glsl_used) {
+ /* There is data to be displayed, but GLSL is not initialized
+ * properly, in this case we fallback to CPU-based display transform. */
+ if ((ibuf->rect || ibuf->rect_float) && !*r_glsl_used) {
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
- *format = GL_RGBA;
- *type = GL_UNSIGNED_BYTE;
+ *r_format = GL_RGBA;
+ *r_type = GL_UNSIGNED_BYTE;
}
if (cache_handle) {
IMB_display_buffer_release(cache_handle);
@@ -1304,14 +1522,12 @@ static void *sequencer_OCIO_transform_ibuf(
static void sequencer_stop_running_jobs(const bContext *C, Scene *scene)
{
if (G.is_rendering == false && (scene->r.seq_prev_type) == OB_RENDER) {
- /* stop all running jobs, except screen one. currently previews frustrate Render
- * needed to make so sequencer's rendering doesn't conflict with compositor
- */
+ /* Stop all running jobs, except screen one. Currently previews frustrate Render.
+ * Need to make so sequencer's rendering doesn't conflict with compositor. */
WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_COMPOSITE);
- /* in case of final rendering used for preview, kill all previews,
- * otherwise threading conflict will happen in rendering module
- */
+ /* In case of final rendering used for preview, kill all previews,
+ * otherwise threading conflict will happen in rendering module. */
WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW);
}
}
@@ -1327,12 +1543,12 @@ static void sequencer_preview_clear(void)
static void sequencer_preview_get_rect(rctf *preview,
Scene *scene,
- ARegion *ar,
+ ARegion *region,
SpaceSeq *sseq,
bool draw_overlay,
bool draw_backdrop)
{
- struct View2D *v2d = &ar->v2d;
+ struct View2D *v2d = &region->v2d;
float viewrect[2];
sequencer_display_size(scene, viewrect);
@@ -1349,7 +1565,7 @@ static void sequencer_preview_get_rect(rctf *preview,
(fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymin);
}
else if (draw_backdrop) {
- float aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct);
+ float aspect = BLI_rcti_size_x(&region->winrct) / (float)BLI_rcti_size_y(&region->winrct);
float image_aspect = viewrect[0] / viewrect[1];
if (aspect >= image_aspect) {
@@ -1368,7 +1584,7 @@ static void sequencer_preview_get_rect(rctf *preview,
static void sequencer_draw_display_buffer(const bContext *C,
Scene *scene,
- ARegion *ar,
+ ARegion *region,
SpaceSeq *sseq,
ImBuf *ibuf,
ImBuf *scope,
@@ -1384,8 +1600,7 @@ static void sequencer_draw_display_buffer(const bContext *C,
}
/* Format needs to be created prior to any immBindProgram call.
- * Do it here because OCIO binds it's own shader.
- */
+ * Do it here because OCIO binds it's own shader. */
int format, type;
bool glsl_used = false;
GLuint texid;
@@ -1401,7 +1616,7 @@ static void sequencer_draw_display_buffer(const bContext *C,
IMB_rect_from_float(ibuf);
}
- display_buffer = (unsigned char *)ibuf->rect;
+ display_buffer = (uchar *)ibuf->rect;
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
}
@@ -1439,7 +1654,7 @@ static void sequencer_draw_display_buffer(const bContext *C,
rctf preview;
rctf canvas;
- sequencer_preview_get_rect(&preview, scene, ar, sseq, draw_overlay, draw_backdrop);
+ sequencer_preview_get_rect(&preview, scene, region, sseq, draw_overlay, draw_backdrop);
if (draw_overlay && sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
canvas = scene->ed->over_border;
@@ -1534,7 +1749,7 @@ static ImBuf *sequencer_get_scope(Scene *scene, SpaceSeq *sseq, ImBuf *ibuf, boo
break;
}
- /* future files may have new scopes we don't catch above */
+ /* Future files may have new scopes we don't catch above. */
if (scope) {
scopes->reference_ibuf = ibuf;
}
@@ -1544,7 +1759,7 @@ static ImBuf *sequencer_get_scope(Scene *scene, SpaceSeq *sseq, ImBuf *ibuf, boo
void sequencer_draw_preview(const bContext *C,
Scene *scene,
- ARegion *ar,
+ ARegion *region,
SpaceSeq *sseq,
int cfra,
int frame_ofs,
@@ -1553,7 +1768,7 @@ void sequencer_draw_preview(const bContext *C,
{
struct Main *bmain = CTX_data_main(C);
struct Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
- struct View2D *v2d = &ar->v2d;
+ struct View2D *v2d = &region->v2d;
struct ImBuf *ibuf = NULL;
struct ImBuf *scope = NULL;
float viewrect[2];
@@ -1571,13 +1786,13 @@ void sequencer_draw_preview(const bContext *C,
return;
}
- /* Setup view */
+ /* Setup view. */
sequencer_display_size(scene, viewrect);
UI_view2d_totRect_set(v2d, viewrect[0] + 0.5f, viewrect[1] + 0.5f);
UI_view2d_curRect_validate(v2d);
UI_view2d_view_ortho(v2d);
- /* Draw background */
+ /* Draw background. */
if (!draw_backdrop && (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE)) {
sequencer_preview_clear();
@@ -1585,17 +1800,18 @@ void sequencer_draw_preview(const bContext *C,
imm_draw_box_checker_2d(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
}
}
- /* Get image */
+ /* Get image. */
ibuf = sequencer_ibuf_get(
bmain, depsgraph, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]);
if (ibuf) {
scope = sequencer_get_scope(scene, sseq, ibuf, draw_backdrop);
- /* Draw image */
- sequencer_draw_display_buffer(C, scene, ar, sseq, ibuf, scope, draw_overlay, draw_backdrop);
+ /* Draw image. */
+ sequencer_draw_display_buffer(
+ C, scene, region, sseq, ibuf, scope, draw_overlay, draw_backdrop);
- /* Draw over image */
+ /* Draw over image. */
if (sseq->flag & SEQ_SHOW_METADATA) {
ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0);
}
@@ -1608,12 +1824,11 @@ void sequencer_draw_preview(const bContext *C,
if (draw_gpencil && show_imbuf) {
sequencer_draw_gpencil(C);
}
+#if 0
+ sequencer_draw_maskedit(C, scene, region, sseq);
+#endif
- /* TODO */
- /* sequencer_draw_maskedit(C, scene, ar, sseq); */
-
- /* Scope is freed in sequencer_check_scopes when ibuf changes and
- * scope image is to be replaced. */
+ /* Scope is freed in sequencer_check_scopes when ibuf changes and redraw is needed. */
if (ibuf) {
IMB_freeImBuf(ibuf);
}
@@ -1622,28 +1837,7 @@ void sequencer_draw_preview(const bContext *C,
seq_prefetch_wm_notify(C, scene);
}
-#if 0
-void drawprefetchseqspace(Scene *scene, ARegion *UNUSED(ar), SpaceSeq *sseq)
-{
- int rectx, recty;
- int render_size = BKE_sequencer_rendersize_to_scale_factor(sseq->render_size);
- if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) {
- return;
- }
-
- if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_SCENE) {
- render_size = scene->r.size / 100.0;
- }
- rectx = render_size * scene->r.xsch + 0.5;
- recty = render_size * scene->r.ysch + 0.5;
-
- if (sseq->mainb != SEQ_DRAW_SEQUENCE) {
- give_ibuf_prefetch_request(rectx, recty, (scene->r.cfra), sseq->chanshown, sseq->render_size);
- }
-}
-#endif
-
-/* draw backdrop of the sequencer strips view */
+/* Draw backdrop in sequencer timeline. */
static void draw_seq_backdrop(View2D *v2d)
{
int i;
@@ -1651,11 +1845,11 @@ static void draw_seq_backdrop(View2D *v2d)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* darker gray overlay over the view backdrop */
+ /* Darker gray overlay over the view backdrop. */
immUniformThemeColorShade(TH_BACK, -20);
immRectf(pos, v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0);
- /* Alternating horizontal stripes */
+ /* Alternating horizontal stripes. */
i = max_ii(1, ((int)v2d->cur.ymin) - 1);
while (i < v2d->cur.ymax) {
@@ -1671,7 +1865,7 @@ static void draw_seq_backdrop(View2D *v2d)
i++;
}
- /* Darker lines separating the horizontal bands */
+ /* Darker lines separating the horizontal bands. */
i = max_ii(1, ((int)v2d->cur.ymin) - 1);
int line_len = (int)v2d->cur.ymax - i + 1;
immUniformThemeColor(TH_GRID);
@@ -1685,29 +1879,25 @@ static void draw_seq_backdrop(View2D *v2d)
immUnbindProgram();
}
-/* draw the contents of the sequencer strips view */
-static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
+static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region)
{
Scene *scene = CTX_data_scene(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
SpaceSeq *sseq = CTX_wm_space_seq(C);
Sequence *last_seq = BKE_sequencer_active_get(scene);
int sel = 0, j;
float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
- /* loop through twice, first unselected, then selected */
+ /* Loop through twice, first unselected, then selected. */
for (j = 0; j < 2; j++) {
Sequence *seq;
- /* highlighting around strip edges indicating selection */
- int outline_tint = (j) ? -60 : -150;
-
- /* loop through strips, checking for those that are visible */
+ /* Loop through strips, checking for those that are visible. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- /* boundbox and selection tests for NOT drawing the strip... */
+ /* Boundbox and selection tests for NOT drawing the strip. */
if ((seq->flag & SELECT) != sel) {
continue;
}
- else if (seq == last_seq) {
+ else if (seq == last_seq && (last_seq->flag & SELECT)) {
continue;
}
else if (min_ii(seq->startdisp, seq->start) > v2d->cur.xmax) {
@@ -1723,21 +1913,42 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
continue;
}
- /* strip passed all tests unscathed... so draw it now */
- draw_seq_strip(C, sseq, scene, ar, seq, outline_tint, pixelx);
+ /* Strip passed all tests, draw it now. */
+ draw_seq_strip(C, sseq, scene, region, seq, pixelx, seq == last_seq ? true : false);
}
- /* draw selected next time round */
+ /* Draw selected next time round. */
sel = SELECT;
}
- /* draw the last selected last (i.e. 'active' in other parts of Blender),
- * removes some overlapping error */
- if (last_seq) {
- draw_seq_strip(C, sseq, scene, ar, last_seq, 120, pixelx);
+ /* When selected draw the last selected (active) strip last,
+ * removes some overlapping error. */
+ if (last_seq && (last_seq->flag & SELECT)) {
+ draw_seq_strip(C, sseq, scene, region, last_seq, pixelx, true);
+
+ /* When active strip is an effect, highlight its inputs. */
+ if (BKE_sequence_effect_get_num_inputs(last_seq->type) > 0) {
+ draw_effect_inputs_highlight(last_seq);
+ }
+ /* When active is a Multicam strip, highlight its source channel. */
+ else if (last_seq->type == SEQ_TYPE_MULTICAM) {
+ int channel = last_seq->multicam_source;
+ if (channel != 0) {
+ GPU_blend(true);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ub(255, 255, 255, 48);
+ immRectf(pos, v2d->cur.xmin, channel, v2d->cur.xmax, channel + 1);
+
+ immUnbindProgram();
+ GPU_blend(false);
+ }
+ }
}
- /* draw highlight when previewing a single strip */
+ /* Draw highlight if "solo preview" is used. */
if (special_seq_update) {
const Sequence *seq = special_seq_update;
GPU_blend(true);
@@ -1769,8 +1980,7 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* draw darkened area outside of active timeline
- * frame range used is preview range or scene range */
+ /* Draw overlay outside of frame range. */
immUniformThemeColorShadeAlpha(TH_BACK, -25, -100);
if (frame_sta < frame_end) {
@@ -1783,7 +1993,7 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
immUniformThemeColorShade(TH_BACK, -60);
- /* thin lines where the actual frames are */
+ /* Draw frame range boundary. */
immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, frame_sta, v2d->cur.ymin);
@@ -1794,12 +2004,23 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
immEnd();
+ /* While in meta strip, draw a checkerboard overlay outside of frame range. */
if (ed && !BLI_listbase_is_empty(&ed->metastack)) {
MetaStack *ms = ed->metastack.last;
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
- immUniformColor4ub(255, 255, 255, 8);
- immRectf(pos, ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+ immUniform4f("color1", 0.0f, 0.0f, 0.0f, 0.22f);
+ immUniform4f("color2", 1.0f, 1.0f, 1.0f, 0.0f);
+ immUniform1i("size", 8);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, ms->disp_range[0], v2d->cur.ymax);
+ immRectf(pos, ms->disp_range[1], v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_BACK, -40);
immBegin(GPU_PRIM_LINES, 4);
@@ -1819,109 +2040,121 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
}
typedef struct CacheDrawData {
- const bContext *C;
- uint pos;
+ struct View2D *v2d;
float stripe_offs;
float stripe_ht;
+ int cache_flag;
+ GPUVertBuf *raw_vbo;
+ GPUVertBuf *preprocessed_vbo;
+ GPUVertBuf *composite_vbo;
+ GPUVertBuf *final_out_vbo;
+ size_t raw_vert_count;
+ size_t preprocessed_vert_count;
+ size_t composite_vert_count;
+ size_t final_out_vert_count;
} CacheDrawData;
-/* Called as a callback */
-static bool draw_cache_view_cb(
- void *userdata, struct Sequence *seq, int nfra, int cache_type, float UNUSED(cost))
+/* Called as a callback. */
+static bool draw_cache_view_init_fn(void *userdata, size_t item_count)
{
- CacheDrawData *drawdata = userdata;
- const bContext *C = drawdata->C;
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- struct View2D *v2d = &ar->v2d;
- Editing *ed = scene->ed;
- uint pos = drawdata->pos;
-
- if ((ed->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT) == 0) {
+ if (item_count == 0) {
return true;
}
- float stripe_bot, stripe_top, stripe_offs, stripe_ht;
- float color[4];
- color[3] = 0.4f;
-
- switch (cache_type) {
- case SEQ_CACHE_STORE_FINAL_OUT:
- if (scene->ed->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT) {
- color[0] = 1.0f;
- color[1] = 0.4f;
- color[2] = 0.2f;
- stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) -
- v2d->cur.ymin;
- stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HANDLE_HEIGHT);
- stripe_top = stripe_bot + stripe_ht;
- break;
- }
- else {
- return false;
- }
-
- case SEQ_CACHE_STORE_RAW:
- if (scene->ed->cache_flag & SEQ_CACHE_VIEW_RAW) {
- color[0] = 1.0f;
- color[1] = 0.1f;
- color[2] = 0.02f;
- stripe_offs = drawdata->stripe_offs;
- stripe_ht = drawdata->stripe_ht;
- stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + stripe_offs;
- stripe_top = stripe_bot + stripe_ht;
- break;
- }
- else {
- return false;
- }
+ CacheDrawData *drawdata = userdata;
+ /* We can not get item count per cache type, so using total item count is safe. */
+ size_t max_vert_count = item_count * 6;
+ GPU_vertbuf_data_alloc(drawdata->raw_vbo, max_vert_count);
+ GPU_vertbuf_data_alloc(drawdata->preprocessed_vbo, max_vert_count);
+ GPU_vertbuf_data_alloc(drawdata->composite_vbo, max_vert_count);
+ GPU_vertbuf_data_alloc(drawdata->final_out_vbo, max_vert_count);
- case SEQ_CACHE_STORE_PREPROCESSED:
- if (scene->ed->cache_flag & SEQ_CACHE_VIEW_PREPROCESSED) {
- color[0] = 0.1f;
- color[1] = 0.1f;
- color[2] = 0.75f;
- stripe_offs = drawdata->stripe_offs;
- stripe_ht = drawdata->stripe_ht;
- stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + (stripe_offs + stripe_ht) + stripe_offs;
- stripe_top = stripe_bot + stripe_ht;
- break;
- }
- else {
- return false;
- }
+ return false;
+}
- case SEQ_CACHE_STORE_COMPOSITE:
- if (scene->ed->cache_flag & SEQ_CACHE_VIEW_COMPOSITE) {
- color[0] = 1.0f;
- color[1] = 0.6f;
- color[2] = 0.0f;
- stripe_offs = drawdata->stripe_offs;
- stripe_ht = drawdata->stripe_ht;
- stripe_top = seq->machine + SEQ_STRIP_OFSTOP - stripe_offs;
- stripe_bot = stripe_top - stripe_ht;
- break;
- }
- else {
- return false;
- }
+/* Called as a callback */
+static bool draw_cache_view_iter_fn(
+ void *userdata, struct Sequence *seq, int nfra, int cache_type, float UNUSED(cost))
+{
+ CacheDrawData *drawdata = userdata;
+ struct View2D *v2d = drawdata->v2d;
+ float stripe_bot, stripe_top, stripe_offs, stripe_ht;
+ GPUVertBuf *vbo;
+ size_t *vert_count;
- default:
- return false;
+ if ((cache_type & SEQ_CACHE_STORE_FINAL_OUT) &&
+ (drawdata->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT)) {
+ stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) - v2d->cur.ymin;
+ stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HANDLE_HEIGHT);
+ stripe_top = stripe_bot + stripe_ht;
+ vbo = drawdata->final_out_vbo;
+ vert_count = &drawdata->final_out_vert_count;
+ }
+ else if ((cache_type & SEQ_CACHE_STORE_RAW) && (drawdata->cache_flag & SEQ_CACHE_VIEW_RAW)) {
+ stripe_offs = drawdata->stripe_offs;
+ stripe_ht = drawdata->stripe_ht;
+ stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + stripe_offs;
+ stripe_top = stripe_bot + stripe_ht;
+ vbo = drawdata->raw_vbo;
+ vert_count = &drawdata->raw_vert_count;
+ }
+ else if ((cache_type & SEQ_CACHE_STORE_PREPROCESSED) &&
+ (drawdata->cache_flag & SEQ_CACHE_VIEW_PREPROCESSED)) {
+ stripe_offs = drawdata->stripe_offs;
+ stripe_ht = drawdata->stripe_ht;
+ stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + (stripe_offs + stripe_ht) + stripe_offs;
+ stripe_top = stripe_bot + stripe_ht;
+ vbo = drawdata->preprocessed_vbo;
+ vert_count = &drawdata->preprocessed_vert_count;
+ }
+ else if ((cache_type & SEQ_CACHE_STORE_COMPOSITE) &&
+ (drawdata->cache_flag & SEQ_CACHE_VIEW_COMPOSITE)) {
+ stripe_offs = drawdata->stripe_offs;
+ stripe_ht = drawdata->stripe_ht;
+ stripe_top = seq->machine + SEQ_STRIP_OFSTOP - stripe_offs;
+ stripe_bot = stripe_top - stripe_ht;
+ vbo = drawdata->composite_vbo;
+ vert_count = &drawdata->composite_vert_count;
+ }
+ else {
+ return false;
}
int cfra = seq->start + nfra;
- immUniformColor4f(color[0], color[1], color[2], color[3]);
- immRectf(pos, cfra, stripe_bot, cfra + 1, stripe_top);
+ float vert_pos[6][2];
+ copy_v2_fl2(vert_pos[0], cfra, stripe_bot);
+ copy_v2_fl2(vert_pos[1], cfra, stripe_top);
+ copy_v2_fl2(vert_pos[2], cfra + 1, stripe_top);
+ copy_v2_v2(vert_pos[3], vert_pos[2]);
+ copy_v2_v2(vert_pos[4], vert_pos[0]);
+ copy_v2_fl2(vert_pos[5], cfra + 1, stripe_bot);
+ for (int i = 0; i < 6; i++) {
+ GPU_vertbuf_vert_set(vbo, *vert_count + i, vert_pos[i]);
+ }
+
+ *vert_count += 6;
return false;
}
+static void draw_cache_view_batch(
+ GPUVertBuf *vbo, size_t vert_count, float col_r, float col_g, float col_b, float col_a)
+{
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ if (vert_count > 0) {
+ GPU_vertbuf_data_len_set(vbo, vert_count);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_batch_uniform_4f(batch, "color", col_r, col_g, col_b, col_a);
+ GPU_batch_draw(batch);
+ }
+ GPU_batch_discard(batch);
+}
+
static void draw_cache_view(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- struct View2D *v2d = &ar->v2d;
+ ARegion *region = CTX_wm_region(C);
+ struct View2D *v2d = &region->v2d;
if ((scene->ed->cache_flag & SEQ_CACHE_VIEW_ENABLE) == 0) {
return;
@@ -1985,32 +2218,51 @@ static void draw_cache_view(const bContext *C)
}
}
+ immUnbindProgram();
+
+ GPUVertFormat format = {0};
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
CacheDrawData userdata;
- userdata.C = C;
- userdata.pos = pos;
+ userdata.v2d = v2d;
userdata.stripe_offs = stripe_offs;
userdata.stripe_ht = stripe_ht;
+ userdata.cache_flag = scene->ed->cache_flag;
+ userdata.raw_vert_count = 0;
+ userdata.preprocessed_vert_count = 0;
+ userdata.composite_vert_count = 0;
+ userdata.final_out_vert_count = 0;
+ userdata.raw_vbo = GPU_vertbuf_create_with_format(&format);
+ userdata.preprocessed_vbo = GPU_vertbuf_create_with_format(&format);
+ userdata.composite_vbo = GPU_vertbuf_create_with_format(&format);
+ userdata.final_out_vbo = GPU_vertbuf_create_with_format(&format);
+
+ BKE_sequencer_cache_iterate(scene, &userdata, draw_cache_view_init_fn, draw_cache_view_iter_fn);
+
+ draw_cache_view_batch(userdata.raw_vbo, userdata.raw_vert_count, 1.0f, 0.1f, 0.02f, 0.4f);
+ draw_cache_view_batch(
+ userdata.preprocessed_vbo, userdata.preprocessed_vert_count, 0.1f, 0.1f, 0.75f, 0.4f);
+ draw_cache_view_batch(
+ userdata.composite_vbo, userdata.composite_vert_count, 1.0f, 0.6f, 0.0f, 0.4f);
+ draw_cache_view_batch(
+ userdata.final_out_vbo, userdata.final_out_vert_count, 1.0f, 0.4f, 0.2f, 0.4f);
- BKE_sequencer_cache_iterate(scene, &userdata, draw_cache_view_cb);
-
- immUnbindProgram();
GPU_blend(false);
}
-/* Draw Timeline/Strip Editor Mode for Sequencer */
-void draw_timeline_seq(const bContext *C, ARegion *ar)
+/* Draw sequencer timeline. */
+void draw_timeline_seq(const bContext *C, ARegion *region)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
SpaceSeq *sseq = CTX_wm_space_seq(C);
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
View2DScrollers *scrollers;
short cfra_flag = 0;
float col[3];
seq_prefetch_wm_notify(C, scene);
- /* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
if (ed && ed->metastack.first) {
GPU_clear_color(col[0], col[1], col[2] - 0.1f, 0.0f);
@@ -2021,59 +2273,36 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
GPU_clear(GPU_COLOR_BIT);
UI_view2d_view_ortho(v2d);
-
- /* calculate extents of sequencer strips/data
- * NOTE: needed for the scrollers later
- */
+ /* Get timeline boundbox, needed for the scrollers. */
boundbox_seq(scene, &v2d->tot);
-
- /* draw backdrop */
draw_seq_backdrop(v2d);
-
- /* regular grid-pattern over the rest of the view (i.e. 1-second grid lines) */
UI_view2d_constant_grid_draw(v2d, FPS);
- /* Only draw backdrop in pure sequence view. */
+ /* Only draw backdrop in timeline view. */
if (sseq->view == SEQ_VIEW_SEQUENCE && sseq->draw_flag & SEQ_DRAW_BACKDROP) {
- sequencer_draw_preview(C, scene, ar, sseq, scene->r.cfra, 0, false, true);
+ sequencer_draw_preview(C, scene, region, sseq, scene->r.cfra, 0, false, true);
UI_view2d_view_ortho(v2d);
}
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
-
+ /* Draw attached callbacks. */
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
seq_draw_sfra_efra(scene, v2d);
- /* sequence strips (if there is data available to be drawn) */
if (ed) {
- /* draw the data */
- draw_seq_strips(C, ed, ar);
- /* text draw cached (for sequence names), in pixelspace now */
- UI_view2d_text_cache_draw(ar);
+ draw_seq_strips(C, ed, region);
+ /* Draw text added in previous function. */
+ UI_view2d_text_cache_draw(region);
}
- /* current frame */
UI_view2d_view_ortho(v2d);
if ((sseq->flag & SEQ_DRAWFRAMES) == 0) {
cfra_flag |= DRAWCFRA_UNIT_SECONDS;
}
- ANIM_draw_cfra(C, v2d, cfra_flag);
- /* markers */
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- int marker_draw_flag = DRAW_MARKERS_MARGIN;
- if (sseq->flag & SEQ_SHOW_MARKERS) {
- ED_markers_draw(C, marker_draw_flag);
- }
-
- 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);
+ /* Draw playhead. */
+ ANIM_draw_cfra(C, v2d, cfra_flag);
- /* overlap playhead */
+ /* Draw overlap playhead. */
if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) {
int cfra_over = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ?
scene->ed->over_cfra :
@@ -2084,6 +2313,8 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ /* Shader may have color set from past usage - reset it. */
+ immUniform1i("colors_len", 0);
immUniform1f("dash_width", 20.0f * U.pixelsize);
immUniform1f("dash_factor", 0.5f);
immUniformThemeColor(TH_CFRAME);
@@ -2096,24 +2327,33 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
immUnbindProgram();
}
- /* callback */
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ UI_view2d_view_orthoSpecial(region, v2d, 1);
+ int marker_draw_flag = DRAW_MARKERS_MARGIN;
+ if (sseq->flag & SEQ_SHOW_MARKERS) {
+ ED_markers_draw(C, marker_draw_flag);
+ }
- /* reset view matrix */
- UI_view2d_view_restore(C);
+ UI_view2d_view_ortho(v2d);
- /* scrubbing region */
- ED_time_scrub_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true);
+ if (ed) {
+ draw_cache_view(C);
+ }
- /* scrollers */
+ ANIM_draw_previewrange(C, v2d, 1);
+
+ /* Draw registered callbacks. */
+ ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
+ UI_view2d_view_restore(C);
+ ED_time_scrub_draw(region, scene, !(sseq->flag & SEQ_DRAWFRAMES), true);
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
- /* channel numbers */
+ /* Draw channel numbers. */
{
rcti rect;
- BLI_rcti_init(&rect, 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, ar->winy - UI_TIME_SCRUB_MARGIN_Y);
- UI_view2d_draw_scale_y__block(ar, v2d, &rect, TH_SCROLL_TEXT);
+ BLI_rcti_init(
+ &rect, 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, region->winy - UI_TIME_SCRUB_MARGIN_Y);
+ UI_view2d_draw_scale_y__block(region, v2d, &rect, TH_SCROLL_TEXT);
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index a1177454acd..c910f1d2382 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -21,8 +21,8 @@
* \ingroup spseq
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
@@ -40,11 +40,11 @@
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
-#include "BKE_library.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -52,26 +52,27 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-/* for menu/popup icons etc etc*/
+/* For menu, popup, icons, etc. */
#include "ED_anim_api.h"
#include "ED_numinput.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
-#include "ED_transform.h"
#include "ED_sequencer.h"
#include "ED_space_api.h"
+#include "ED_transform.h"
-#include "UI_view2d.h"
#include "UI_interface.h"
+#include "UI_view2d.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-/* own include */
+/* Own include. */
#include "sequencer_intern.h"
/* XXX */
-/* RNA Enums, used in multiple files */
+/* RNA Enums, used in multiple files. */
EnumPropertyItem sequencer_prop_effect_types[] = {
{SEQ_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
{SEQ_TYPE_ADD, "ADD", 0, "Add", "Add effect strip type"},
@@ -94,8 +95,6 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
{0, NULL, 0, NULL, NULL},
};
-/* mute operator */
-
#define SEQ_SIDE_MOUSE -1
EnumPropertyItem prop_side_types[] = {
@@ -144,7 +143,7 @@ static void proxy_freejob(void *pjv)
MEM_freeN(pj);
}
-/* only this runs inside thread */
+/* Only this runs inside thread. */
static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
{
ProxyJob *pj = pjv;
@@ -185,7 +184,7 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Sequence *seq;
GSet *file_list;
@@ -233,7 +232,7 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
/* ********************************************************************** */
@@ -256,7 +255,7 @@ void boundbox_seq(Scene *scene, rctf *rect)
return;
}
- min[0] = 0.0;
+ min[0] = SFRA;
max[0] = EFRA + 1;
min[1] = 0.0;
max[1] = 8.0;
@@ -291,7 +290,7 @@ static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
mval[0] = mouse_x;
mval[1] = 0;
- /* choose the side based on which side of the playhead the mouse is on */
+ /* Choose the side based on which side of the playhead the mouse is on. */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
@@ -299,7 +298,7 @@ static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
{
- /* sel - 0==unselected, 1==selected, -1==done care*/
+ /* sel: 0==unselected, 1==selected, -1==don't care. */
Sequence *seq;
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -334,7 +333,7 @@ Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int se
static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
{
- /* sel - 0==unselected, 1==selected, -1==done care*/
+ /* sel: 0==unselected, 1==selected, -1==don't care. */
Sequence *seq, *best_seq = NULL;
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -375,7 +374,7 @@ static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, i
}
seq = seq->next;
}
- return best_seq; /* can be null */
+ return best_seq; /* Can be null. */
}
Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2])
@@ -400,22 +399,21 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[
while (seq) {
if (seq->machine == (int)y) {
- /* check for both normal strips, and strips that have been flipped horizontally */
+ /* Check for both normal strips, and strips that have been flipped horizontally. */
if (((seq->startdisp < seq->enddisp) && (seq->startdisp <= x && seq->enddisp >= x)) ||
((seq->startdisp > seq->enddisp) && (seq->startdisp >= x && seq->enddisp <= x))) {
if (BKE_sequence_tx_test(seq)) {
- /* clamp handles to defined size in pixel space */
-
- handsize = seq->handsize;
+ /* Clamp handles to defined size in pixel space. */
+ handsize = 2.0f * sequence_handle_size_get_clamped(seq, pixelx);
displen = (float)abs(seq->startdisp - seq->enddisp);
- /* don't even try to grab the handles of small strips */
+ /* Don't even try to grab the handles of small strips. */
if (displen / pixelx > 16) {
+
/* Set the max value to handle to 1/3 of the total len when its
* less than 28. This is important because otherwise selecting
* handles happens even when you click in the middle. */
-
if ((displen / 3) < 30 * pixelx) {
handsize = displen / 3;
}
@@ -510,7 +508,6 @@ void recurs_sel_seq(Sequence *seqm)
bool ED_space_sequencer_maskedit_mask_poll(bContext *C)
{
- /* in this case both funcs are the same, for clip editor not */
return ED_space_sequencer_maskedit_poll(C);
}
@@ -535,7 +532,7 @@ bool ED_space_sequencer_maskedit_poll(bContext *C)
return false;
}
-/* are we displaying the seq output (not channels or histogram)*/
+/* Are we displaying the seq output (not channels or histogram). */
bool ED_space_sequencer_check_show_imbuf(SpaceSeq *sseq)
{
return (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW) &&
@@ -551,15 +548,15 @@ bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
int seq_effect_find_selected(Scene *scene,
Sequence *activeseq,
int type,
- Sequence **selseq1,
- Sequence **selseq2,
- Sequence **selseq3,
- const char **error_str)
+ Sequence **r_selseq1,
+ Sequence **r_selseq2,
+ Sequence **r_selseq3,
+ const char **r_error_str)
{
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq;
- *error_str = NULL;
+ *r_error_str = NULL;
if (!activeseq) {
seq2 = BKE_sequencer_active_get(scene);
@@ -568,7 +565,7 @@ int seq_effect_find_selected(Scene *scene,
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
if (seq->type == SEQ_TYPE_SOUND_RAM && BKE_sequence_effect_get_num_inputs(type) != 0) {
- *error_str = N_("Cannot apply effects to audio sequence strips");
+ *r_error_str = N_("Cannot apply effects to audio sequence strips");
return 0;
}
if ((seq != activeseq) && (seq != seq2)) {
@@ -582,15 +579,15 @@ int seq_effect_find_selected(Scene *scene,
seq3 = seq;
}
else {
- *error_str = N_("Cannot apply effect to more than 3 sequence strips");
+ *r_error_str = N_("Cannot apply effect to more than 3 sequence strips");
return 0;
}
}
}
}
- /* make sequence selection a little bit more intuitive
- * for 3 strips: the last-strip should be sequence3 */
+ /* Make sequence selection a little bit more intuitive
+ * for 3 strips: the last-strip should be seq3. */
if (seq3 != NULL && seq2 != NULL) {
Sequence *tmp = seq2;
seq2 = seq3;
@@ -599,11 +596,11 @@ int seq_effect_find_selected(Scene *scene,
switch (BKE_sequence_effect_get_num_inputs(type)) {
case 0:
- *selseq1 = *selseq2 = *selseq3 = NULL;
- return 1; /* success */
+ *r_selseq1 = *r_selseq2 = *r_selseq3 = NULL;
+ return 1; /* Success. */
case 1:
if (seq2 == NULL) {
- *error_str = N_("At least one selected sequence strip is needed");
+ *r_error_str = N_("At least one selected sequence strip is needed");
return 0;
}
if (seq1 == NULL) {
@@ -615,7 +612,7 @@ int seq_effect_find_selected(Scene *scene,
ATTR_FALLTHROUGH;
case 2:
if (seq1 == NULL || seq2 == NULL) {
- *error_str = N_("2 selected sequence strips are needed");
+ *r_error_str = N_("2 selected sequence strips are needed");
return 0;
}
if (seq3 == NULL) {
@@ -625,13 +622,13 @@ int seq_effect_find_selected(Scene *scene,
}
if (seq1 == NULL && seq2 == NULL && seq3 == NULL) {
- *error_str = N_("TODO: in what cases does this happen?");
+ *r_error_str = N_("TODO: in what cases does this happen?");
return 0;
}
- *selseq1 = seq1;
- *selseq2 = seq2;
- *selseq3 = seq3;
+ *r_selseq1 = seq1;
+ *r_selseq2 = seq2;
+ *r_selseq3 = seq3;
return 1;
}
@@ -640,8 +637,8 @@ static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
{
Sequence *seq1, *seq2, *seq3;
- /* try to find a replacement input sequence, and flag for later deletion if
- * no replacement can be found */
+ /* Try to find a replacement input sequence, and flag for later deletion if
+ * no replacement can be found. */
if (!seq) {
return NULL;
@@ -650,13 +647,13 @@ static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
return ((seq->flag & SELECT) ? NULL : seq);
}
else if (!(seq->flag & SELECT)) {
- /* try to find replacement for effect inputs */
+ /* Try to find replacement for effect inputs. */
seq1 = del_seq_find_replace_recurs(scene, seq->seq1);
seq2 = del_seq_find_replace_recurs(scene, seq->seq2);
seq3 = del_seq_find_replace_recurs(scene, seq->seq3);
if (seq1 == seq->seq1 && seq2 == seq->seq2 && seq3 == seq->seq3) {
- /* pass */
+ /* Pass. */
}
else if (seq1 || seq2 || seq3) {
seq->seq1 = (seq1) ? seq1 : (seq2) ? seq2 : seq3;
@@ -666,7 +663,7 @@ static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1);
}
else {
- seq->flag |= SELECT; /* mark for delete */
+ seq->flag |= SELECT; /* Mark for delete. */
}
}
@@ -724,23 +721,23 @@ static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short de
if (seq->type == SEQ_TYPE_META) {
recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
}
- BKE_sequence_free(scene, seq);
+ BKE_sequence_free(scene, seq, true);
}
seq = seqn;
}
}
-static Sequence *cut_seq_hard(
- Main *bmain, Scene *scene, Sequence *seq, ListBase *new_seq_list, int cutframe)
+static Sequence *split_seq_hard(
+ Main *bmain, Scene *scene, Sequence *seq, ListBase *new_seq_list, int split_frame)
{
TransSeq ts;
Sequence *seqn = NULL;
bool skip_dup = false;
- /* Unlike soft-cut, it's important to use the same value for both strips. */
- const bool is_end_exact = ((seq->start + seq->len) == cutframe);
+ /* Unlike soft-split, it's important to use the same value for both strips. */
+ const bool is_end_exact = ((seq->start + seq->len) == split_frame);
- /* backup values */
+ /* Backup values. */
ts.start = seq->start;
ts.machine = seq->machine;
ts.startstill = seq->startstill;
@@ -753,43 +750,42 @@ static Sequence *cut_seq_hard(
ts.anim_endofs = seq->anim_endofs;
ts.len = seq->len;
- /* First Strip! */
- /* strips with extended stillfames before */
-
- /* Precaution, needed because the length saved on-disk may not match the length saved in the
- * blend file, or our code may have minor differences reading file length between versions.
- * This causes hard-cut to fail, see: T47862 */
if (seq->type != SEQ_TYPE_META) {
+ /* Precaution, needed because the length saved on-disk may not match the length saved in the
+ * blend file, or our code may have minor differences reading file length between versions.
+ * This causes hard-split to fail, see: T47862. */
BKE_sequence_reload_new_file(bmain, scene, seq, true);
BKE_sequence_calc(scene, seq);
}
- /* Important to offset the start when 'cutframe == seq->start'
+ /* First Strip. */
+ /* Important to offset the start when 'split_frame == seq->start'
* because we need at least one frame of content after start/end still have clipped it. */
- if ((seq->startstill) && (cutframe <= seq->start)) {
- /* don't do funny things with METAs ... */
+ if ((seq->startstill) && (split_frame <= seq->start)) {
+ /* Don't do funny things with METAs. */
if (seq->type == SEQ_TYPE_META) {
skip_dup = true;
- seq->startstill = seq->start - cutframe;
+ seq->startstill = seq->start - split_frame;
}
else {
- seq->start = cutframe - 1;
- seq->startstill = cutframe - seq->startdisp - 1;
+ seq->start = split_frame - 1;
+ seq->startstill = split_frame - seq->startdisp - 1;
seq->anim_endofs += seq->len - 1;
seq->endstill = 0;
}
}
- /* normal strip */
+ /* Normal strip. */
else if ((is_end_exact == false) &&
- ((cutframe >= seq->start) && (cutframe <= (seq->start + seq->len)))) {
+ ((split_frame >= seq->start) && (split_frame <= (seq->start + seq->len)))) {
seq->endofs = 0;
seq->endstill = 0;
- seq->anim_endofs += (seq->start + seq->len) - cutframe;
+ seq->anim_endofs += (seq->start + seq->len) - split_frame;
}
- /* strips with extended stillframes after */
- else if ((is_end_exact == true) || (((seq->start + seq->len) < cutframe) && (seq->endstill))) {
- seq->endstill -= seq->enddisp - cutframe;
- /* don't do funny things with METAs ... */
+ /* Strips with extended stillframes. */
+ else if ((is_end_exact == true) ||
+ (((seq->start + seq->len) < split_frame) && (seq->endstill))) {
+ seq->endstill -= seq->enddisp - split_frame;
+ /* Don't do funny things with METAs. */
if (seq->type == SEQ_TYPE_META) {
skip_dup = true;
}
@@ -799,7 +795,7 @@ static Sequence *cut_seq_hard(
BKE_sequence_calc(scene, seq);
if (!skip_dup) {
- /* Duplicate AFTER the first change */
+ /* Duplicate AFTER the first change. */
seqn = BKE_sequence_dupli_recursive(
scene, scene, new_seq_list, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
}
@@ -807,57 +803,57 @@ static Sequence *cut_seq_hard(
if (seqn) {
seqn->flag |= SELECT;
- /* Important not to re-assign this (unlike soft-cut) */
#if 0
- is_end_exact = ((seqn->start + seqn->len) == cutframe);
+ is_end_exact = ((seqn->start + seqn->len) == split_frame);
#endif
- /* Second Strip! */
- /* strips with extended stillframes before */
- if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
+ /* Second Strip. */
+ /* strips with extended stillframes. */
+ if ((seqn->startstill) && (split_frame == seqn->start + 1)) {
seqn->start = ts.start;
- seqn->startstill = ts.start - cutframe;
+ seqn->startstill = ts.start - split_frame;
seqn->anim_endofs = ts.anim_endofs;
seqn->endstill = ts.endstill;
}
- /* normal strip */
+ /* Normal strip. */
else if ((is_end_exact == false) &&
- ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len)))) {
- seqn->start = cutframe;
+ ((split_frame >= seqn->start) && (split_frame <= (seqn->start + seqn->len)))) {
+ seqn->start = split_frame;
seqn->startstill = 0;
seqn->startofs = 0;
seqn->endofs = ts.endofs;
- seqn->anim_startofs += cutframe - ts.start;
+ seqn->anim_startofs += split_frame - ts.start;
seqn->anim_endofs = ts.anim_endofs;
seqn->endstill = ts.endstill;
}
- /* strips with extended stillframes after */
+ /* Strips with extended stillframes after. */
else if ((is_end_exact == true) ||
- (((seqn->start + seqn->len) < cutframe) && (seqn->endstill))) {
- seqn->start = cutframe;
+ (((seqn->start + seqn->len) < split_frame) && (seqn->endstill))) {
+ seqn->start = split_frame;
seqn->startofs = 0;
seqn->anim_startofs += ts.len - 1;
- seqn->endstill = ts.enddisp - cutframe - 1;
+ seqn->endstill = ts.enddisp - split_frame - 1;
seqn->startstill = 0;
}
BKE_sequence_reload_new_file(bmain, scene, seqn, false);
BKE_sequence_calc(scene, seqn);
+ BKE_sequence_invalidate_cache_in_range(scene, seq, seqn, SEQ_CACHE_ALL_TYPES);
}
return seqn;
}
-static Sequence *cut_seq_soft(
- Main *UNUSED(bmain), Scene *scene, Sequence *seq, ListBase *new_seq_list, int cutframe)
+static Sequence *split_seq_soft(
+ Main *UNUSED(bmain), Scene *scene, Sequence *seq, ListBase *new_seq_list, int split_frame)
{
TransSeq ts;
Sequence *seqn = NULL;
bool skip_dup = false;
- bool is_end_exact = ((seq->start + seq->len) == cutframe);
+ bool is_end_exact = ((seq->start + seq->len) == split_frame);
- /* backup values */
+ /* Backup values. */
ts.start = seq->start;
ts.machine = seq->machine;
ts.startstill = seq->startstill;
@@ -870,33 +866,33 @@ static Sequence *cut_seq_soft(
ts.anim_endofs = seq->anim_endofs;
ts.len = seq->len;
- /* First Strip! */
- /* strips with extended stillfames before */
-
- /* Important to offset the start when 'cutframe == seq->start'
+ /* First Strip. */
+ /* Strips with extended stillfames. */
+ /* Important to offset the start when 'split_frame == seq->start'
* because we need at least one frame of content after start/end still have clipped it. */
- if ((seq->startstill) && (cutframe <= seq->start)) {
+ if ((seq->startstill) && (split_frame <= seq->start)) {
/* don't do funny things with METAs ... */
if (seq->type == SEQ_TYPE_META) {
skip_dup = true;
- seq->startstill = seq->start - cutframe;
+ seq->startstill = seq->start - split_frame;
}
else {
- seq->start = cutframe - 1;
- seq->startstill = cutframe - seq->startdisp - 1;
+ seq->start = split_frame - 1;
+ seq->startstill = split_frame - seq->startdisp - 1;
seq->endofs = seq->len - 1;
seq->endstill = 0;
}
}
- /* normal strip */
- else if ((is_end_exact == false) && (cutframe >= seq->start) &&
- (cutframe <= (seq->start + seq->len))) {
- seq->endofs = (seq->start + seq->len) - cutframe;
+ /* Normal strip. */
+ else if ((is_end_exact == false) && (split_frame >= seq->start) &&
+ (split_frame <= (seq->start + seq->len))) {
+ seq->endofs = (seq->start + seq->len) - split_frame;
}
- /* strips with extended stillframes after */
- else if ((is_end_exact == true) || (((seq->start + seq->len) < cutframe) && (seq->endstill))) {
- seq->endstill -= seq->enddisp - cutframe;
- /* don't do funny things with METAs ... */
+ /* Strips with extended stillframes. */
+ else if ((is_end_exact == true) ||
+ (((seq->start + seq->len) < split_frame) && (seq->endstill))) {
+ seq->endstill -= seq->enddisp - split_frame;
+ /* Don't do funny things with METAs. */
if (seq->type == SEQ_TYPE_META) {
skip_dup = true;
}
@@ -905,7 +901,7 @@ static Sequence *cut_seq_soft(
BKE_sequence_calc(scene, seq);
if (!skip_dup) {
- /* Duplicate AFTER the first change */
+ /* Duplicate AFTER the first change. */
seqn = BKE_sequence_dupli_recursive(
scene, scene, new_seq_list, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
}
@@ -913,55 +909,58 @@ static Sequence *cut_seq_soft(
if (seqn) {
seqn->flag |= SELECT;
- is_end_exact = ((seqn->start + seqn->len) == cutframe);
+ is_end_exact = ((seqn->start + seqn->len) == split_frame);
- /* Second Strip! */
- /* strips with extended stillframes before */
- if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
+ /* Second Strip. */
+ /* Strips with extended stillframes. */
+ if ((seqn->startstill) && (split_frame == seqn->start + 1)) {
seqn->start = ts.start;
- seqn->startstill = ts.start - cutframe;
+ seqn->startstill = ts.start - split_frame;
seqn->endofs = ts.endofs;
seqn->endstill = ts.endstill;
}
- /* normal strip */
- else if ((is_end_exact == false) && (cutframe >= seqn->start) &&
- (cutframe <= (seqn->start + seqn->len))) {
+ /* Normal strip. */
+ else if ((is_end_exact == false) && (split_frame >= seqn->start) &&
+ (split_frame <= (seqn->start + seqn->len))) {
seqn->startstill = 0;
- seqn->startofs = cutframe - ts.start;
+ seqn->startofs = split_frame - ts.start;
seqn->endofs = ts.endofs;
seqn->endstill = ts.endstill;
}
- /* strips with extended stillframes after */
+ /* Strips with extended stillframes. */
else if ((is_end_exact == true) ||
- (((seqn->start + seqn->len) < cutframe) && (seqn->endstill))) {
- seqn->start = cutframe - ts.len + 1;
+ (((seqn->start + seqn->len) < split_frame) && (seqn->endstill))) {
+ seqn->start = split_frame - ts.len + 1;
seqn->startofs = ts.len - 1;
- seqn->endstill = ts.enddisp - cutframe - 1;
+ seqn->endstill = ts.enddisp - split_frame - 1;
seqn->startstill = 0;
}
BKE_sequence_calc(scene, seqn);
+ BKE_sequence_invalidate_cache_in_range(scene, seq, seqn, SEQ_CACHE_ALL_TYPES);
}
return seqn;
}
-/* like duplicate, but only duplicate and cut overlapping strips,
- * strips to the left of the cutframe are ignored and strips to the right
- * are moved to the end of slist
- * we have to work on the same slist (not using a separate list), since
+/* Like duplicate, but only duplicate and split overlapping strips,
+ * strips to the left of the split_frame are ignored and strips to the right
+ * are moved to the end of slist.
+ * We have to work on the same slist (not using a separate list), since
* otherwise dupli_seq can't check for duplicate names properly and
- * may generate strips with the same name (which will mess up animdata)
+ * may generate strips with the same name which will mess up animdata.
*/
-static bool cut_seq_list(Main *bmain,
- Scene *scene,
- ListBase *slist,
- int cutframe,
- int channel,
- bool use_cursor_position,
- Sequence *(*cut_seq)(Main *bmain, Scene *, Sequence *, ListBase *, int))
+static bool split_seq_list(
+ Main *bmain,
+ Scene *scene,
+ ListBase *slist,
+ int split_frame,
+ int channel,
+ bool use_cursor_position,
+ Sequence *(*split_seq)(Main *bmain, Scene *, Sequence *, ListBase *, int))
+
{
Sequence *seq, *seq_next_iter;
Sequence *seq_first_new = NULL;
@@ -969,11 +968,11 @@ static bool cut_seq_list(Main *bmain,
seq = slist->first;
while (seq && seq != seq_first_new) {
- seq_next_iter = seq->next; /* we need this because we may remove seq */
+ seq_next_iter = seq->next; /* We need this because we may remove seq. */
seq->tmp = NULL;
if (use_cursor_position) {
- if (seq->machine == channel && seq->startdisp < cutframe && seq->enddisp > cutframe) {
- Sequence *seqn = cut_seq(bmain, scene, seq, slist, cutframe);
+ if (seq->machine == channel && seq->startdisp < split_frame && seq->enddisp > split_frame) {
+ Sequence *seqn = split_seq(bmain, scene, seq, slist, split_frame);
if (seqn) {
if (seq_first_new == NULL) {
seq_first_new = seqn;
@@ -983,19 +982,19 @@ static bool cut_seq_list(Main *bmain,
}
else {
if (seq->flag & SELECT) {
- if (cutframe > seq->startdisp && cutframe < seq->enddisp) {
- Sequence *seqn = cut_seq(bmain, scene, seq, slist, cutframe);
+ if (split_frame > seq->startdisp && split_frame < seq->enddisp) {
+ Sequence *seqn = split_seq(bmain, scene, seq, slist, split_frame);
if (seqn) {
if (seq_first_new == NULL) {
seq_first_new = seqn;
}
}
}
- else if (seq->enddisp <= cutframe) {
- /* do nothing */
+ else if (seq->enddisp <= split_frame) {
+ /* Pass. */
}
- else if (seq->startdisp >= cutframe) {
- /* move to tail */
+ else if (seq->startdisp >= split_frame) {
+ /* Move to tail. */
BLI_remlink(slist, seq);
BLI_addtail(slist, seq);
@@ -1018,7 +1017,7 @@ static bool sequence_offset_after_frame(Scene *scene, const int delta, const int
bool done = false;
TimeMarker *marker;
- /* all strips >= cfra are shifted */
+ /* All strips >= cfra are shifted. */
if (ed == NULL) {
return 0;
@@ -1081,12 +1080,12 @@ static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene)
}
BLI_strncpy(from, last_seq->strip->dir, sizeof(from));
- // XXX if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
- // return;
+ /* XXX if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
+ * return; */
BLI_strncpy(to, from, sizeof(to));
- // XXX if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
- // return;
+ /* XXX if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
+ * return; */
if (STREQ(to, from)) {
return;
@@ -1097,11 +1096,11 @@ static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene)
if (STREQLEN(seq->strip->dir, from, strlen(from))) {
printf("found %s\n", seq->strip->dir);
- /* strip off the beginning */
+ /* Strip off the beginning. */
stripped[0] = 0;
BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
- /* new path */
+ /* New path. */
BLI_snprintf(seq->strip->dir, sizeof(seq->strip->dir), "%s%s", to, stripped);
printf("new %s\n", seq->strip->dir);
}
@@ -1118,12 +1117,12 @@ static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
bool first = false, done;
bool do_all = RNA_boolean_get(op->ptr, "all");
- /* get first and last frame */
+ /* Get first and last frame. */
boundbox_seq(scene, &rectf);
sfra = (int)rectf.xmin;
efra = (int)rectf.xmax;
- /* first check if the current frame has a gap already */
+ /* Check if the current frame has a gap already. */
for (cfra = CFRA; cfra >= sfra; cfra--) {
if (BKE_sequencer_evaluate_frame(scene, cfra)) {
first = true;
@@ -1132,7 +1131,7 @@ static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
}
for (; cfra < efra; cfra++) {
- /* first == 0 means there's still no strip to remove a gap for */
+ /* There's still no strip to remove a gap for. */
if (first == false) {
if (BKE_sequencer_evaluate_frame(scene, cfra)) {
first = true;
@@ -1160,19 +1159,19 @@ static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Remove Gaps";
ot->idname = "SEQUENCER_OT_gap_remove";
ot->description =
"Remove gap at current frame to first strip at the right, independent of selection or "
"locked state of strips";
- /* api callbacks */
+ /* Api callbacks. */
// ot->invoke = sequencer_snap_invoke;
ot->exec = sequencer_gap_remove_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
@@ -1192,19 +1191,19 @@ static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Insert Gaps";
ot->idname = "SEQUENCER_OT_gap_insert";
ot->description =
"Insert gap at current frame to first strips at the right, independent of selection or "
"locked state of strips";
- /* api callbacks */
+ /* Api callbacks. */
// ot->invoke = sequencer_snap_invoke;
ot->exec = sequencer_gap_insert_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_int(ot->srna,
@@ -1234,7 +1233,7 @@ static int seq_get_snaplimit(View2D *v2d)
}
#endif
-/* Operator functions */
+/* Operator functions. */
bool sequencer_edit_poll(bContext *C)
{
return (BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL);
@@ -1278,7 +1277,7 @@ bool sequencer_view_strips_poll(bContext *C)
return 0;
}
-/* snap operator*/
+/* Snap operator. */
static int sequencer_snap_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1289,14 +1288,11 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
snap_frame = RNA_int_get(op->ptr, "frame");
- /* also check metas */
+ /* Check metas. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK) &&
BKE_sequence_tx_test(seq)) {
if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
- /* simple but no anim update */
- /* seq->start = snap_frame-seq->startofs+seq->startstill; */
-
BKE_sequence_translate(
scene, seq, (snap_frame - seq->startofs + seq->startstill) - seq->start);
}
@@ -1314,8 +1310,8 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
}
}
- /* test for effects and overlap
- * don't use SEQP_BEGIN since that would be recursive */
+ /* Test for effects and overlap.
+ * Don't use SEQP_BEGIN since that would be recursive. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK)) {
seq->flag &= ~SEQ_OVERLAP;
@@ -1336,7 +1332,6 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
}
}
- /* as last: */
BKE_sequencer_sort(scene);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -1359,17 +1354,17 @@ static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
void SEQUENCER_OT_snap(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Snap Strips to Playhead";
ot->idname = "SEQUENCER_OT_snap";
ot->description = "Frame where selected strips will be snapped";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_snap_invoke;
ot->exec = sequencer_snap_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_int(ot->srna,
@@ -1391,7 +1386,7 @@ typedef struct SlipData {
bool *trim;
int num_seq;
bool slow;
- int slow_offset; /* offset at the point where offset was turned on */
+ int slow_offset; /* Offset at the point where offset was turned on. */
NumInput num_input;
} SlipData;
@@ -1425,7 +1420,7 @@ static void transseq_restore(TransSeq *ts, Sequence *seq)
seq->len = ts->len;
}
-static int slip_add_sequences_rec(
+static int slip_add_sequences_recursive(
ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
{
Sequence *seq;
@@ -1438,8 +1433,8 @@ static int slip_add_sequences_rec(
num_items++;
if (seq->type == SEQ_TYPE_META) {
- /* trim the sub-sequences */
- num_items += slip_add_sequences_rec(
+ /* Trim the sub-sequences. */
+ num_items += slip_add_sequences_recursive(
&seq->seqbase, seq_array, trim, num_items + offset, false);
}
else if (seq->type & SEQ_TYPE_EFFECT) {
@@ -1451,7 +1446,7 @@ static int slip_add_sequences_rec(
return num_items;
}
-static int slip_count_sequences_rec(ListBase *seqbasep, bool first_level)
+static int slip_count_sequences_recursive(ListBase *seqbasep, bool first_level)
{
Sequence *seq;
int trimmed_sequences = 0;
@@ -1461,8 +1456,8 @@ static int slip_count_sequences_rec(ListBase *seqbasep, bool first_level)
trimmed_sequences++;
if (seq->type == SEQ_TYPE_META) {
- /* trim the sub-sequences */
- trimmed_sequences += slip_count_sequences_rec(&seq->seqbase, false);
+ /* Trim the sub-sequences. */
+ trimmed_sequences += slip_count_sequences_recursive(&seq->seqbase, false);
}
}
}
@@ -1479,8 +1474,8 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
int num_seq, i;
View2D *v2d = UI_view2d_fromcontext(C);
- /* first recursively count the trimmed elements */
- num_seq = slip_count_sequences_rec(ed->seqbasep, true);
+ /* Recursively count the trimmed elements. */
+ num_seq = slip_count_sequences_recursive(ed->seqbasep, true);
if (num_seq == 0) {
return OPERATOR_CANCELLED;
@@ -1498,7 +1493,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
data->num_input.unit_sys = USER_UNIT_NONE;
data->num_input.unit_type[0] = 0;
- slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
+ slip_add_sequences_recursive(ed->seqbasep, data->seq_array, data->trim, 0, true);
for (i = 0; i < num_seq; i++) {
transseq_backup(data->ts + i, data->seq_array[i]);
@@ -1513,7 +1508,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
WM_event_add_modal_handler(C, op);
- /* notify so we draw extensions immediately */
+ /* Notify so we draw extensions immediately. */
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_RUNNING_MODAL;
@@ -1521,64 +1516,86 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
{
+ /* Only data types supported for now. */
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ bool changed = false;
- /* only data types supported for now */
- if (offset != 0) {
- Editing *ed = BKE_sequencer_editing_get(scene, false);
- int i;
-
- /* we iterate in reverse so metastrips are iterated after their children */
- for (i = data->num_seq - 1; i >= 0; i--) {
- Sequence *seq = data->seq_array[i];
- int endframe;
- /* we have the offset, do the terrible math */
-
- /* first, do the offset */
- seq->start = data->ts[i].start + offset;
+ /* Iterate in reverse so meta-strips are iterated after their children. */
+ for (int i = data->num_seq - 1; i >= 0; i--) {
+ Sequence *seq = data->seq_array[i];
+ int endframe;
- if (data->trim[i]) {
- /* find the endframe */
- endframe = seq->start + seq->len;
+ /* Offset seq start. */
+ seq->start = data->ts[i].start + offset;
- /* now compute the terrible offsets */
- if (endframe > seq->enddisp) {
- seq->endstill = 0;
- seq->endofs = endframe - seq->enddisp;
- }
- else if (endframe <= seq->enddisp) {
- seq->endstill = seq->enddisp - endframe;
- seq->endofs = 0;
- }
+ if (data->trim[i]) {
+ /* Find the end-frame. */
+ endframe = seq->start + seq->len;
- if (seq->start > seq->startdisp) {
- seq->startstill = seq->start - seq->startdisp;
- seq->startofs = 0;
- }
- else if (seq->start <= seq->startdisp) {
- seq->startstill = 0;
- seq->startofs = seq->startdisp - seq->start;
- }
+ /* Compute the sequence offsets. */
+ if (endframe > seq->enddisp) {
+ seq->endstill = 0;
+ seq->endofs = endframe - seq->enddisp;
+ changed = true;
}
- else {
- /* if no real trim, don't change the data, rather transform the strips themselves */
- seq->startdisp = data->ts[i].startdisp + offset;
- seq->enddisp = data->ts[i].enddisp + offset;
+ else if (endframe <= seq->enddisp) {
+ seq->endstill = seq->enddisp - endframe;
+ seq->endofs = 0;
+ changed = true;
}
- /* effects are only added if we they are in a meta-strip.
- * In this case, dependent strips will just be transformed and
- * we can skip calculating for effects.
- * This way we can avoid an extra loop just for effects*/
- if (!(seq->type & SEQ_TYPE_EFFECT)) {
- BKE_sequence_calc(scene, seq);
+ if (seq->start > seq->startdisp) {
+ seq->startstill = seq->start - seq->startdisp;
+ seq->startofs = 0;
+ changed = true;
+ }
+ else if (seq->start <= seq->startdisp) {
+ seq->startstill = 0;
+ seq->startofs = seq->startdisp - seq->start;
+ changed = true;
}
}
- BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ else {
+ /* No transform data (likely effect strip). Only move start and end. */
+ seq->startdisp = data->ts[i].startdisp + offset;
+ seq->enddisp = data->ts[i].enddisp + offset;
+ changed = true;
+ }
- return true;
+ /* Effects are only added if we they are in a meta-strip.
+ * In this case, dependent strips will just be transformed and
+ * we can skip calculating for effects.
+ * This way we can avoid an extra loop just for effects. */
+ if (!(seq->type & SEQ_TYPE_EFFECT)) {
+ BKE_sequence_calc(scene, seq);
+ }
+ }
+ if (changed) {
+ BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
}
+ return changed;
+}
- return false;
+/* Make sure, that each strip contains at least 1 frame of content. */
+static void sequencer_slip_apply_limits(SlipData *data, int *offset)
+{
+ for (int i = 0; i < data->num_seq; i++) {
+ if (data->trim[i]) {
+ Sequence *seq = data->seq_array[i];
+ int seq_content_start = data->ts[i].start + *offset;
+ int seq_content_end = seq_content_start + seq->len + seq->anim_startofs + seq->anim_endofs;
+ int diff = 0;
+
+ if (seq_content_start >= seq->enddisp) {
+ diff = seq->enddisp - seq_content_start - 1;
+ }
+
+ if (seq_content_end <= seq->startdisp) {
+ diff = seq->startdisp - seq_content_end + 1;
+ }
+ *offset += diff;
+ }
+ }
}
static int sequencer_slip_exec(bContext *C, wmOperator *op)
@@ -1590,8 +1607,8 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
int offset = RNA_int_get(op->ptr, "offset");
bool success = false;
- /* first recursively count the trimmed elements */
- num_seq = slip_count_sequences_rec(ed->seqbasep, true);
+ /* Recursively count the trimmed elements. */
+ num_seq = slip_count_sequences_recursive(ed->seqbasep, true);
if (num_seq == 0) {
return OPERATOR_CANCELLED;
@@ -1603,12 +1620,13 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
data->num_seq = num_seq;
- slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
+ slip_add_sequences_recursive(ed->seqbasep, data->seq_array, data->trim, 0, true);
for (i = 0; i < num_seq; i++) {
transseq_backup(data->ts + i, data->seq_array[i]);
}
+ sequencer_slip_apply_limits(data, &offset);
success = sequencer_slip_recursively(scene, data, offset);
MEM_freeN(data->seq_array);
@@ -1626,11 +1644,11 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
}
}
-static void sequencer_slip_update_header(Scene *scene, ScrArea *sa, SlipData *data, int offset)
+static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *data, int offset)
{
char msg[UI_MAX_DRAW_STR];
- if (sa) {
+ if (area) {
if (hasNumInput(&data->num_input)) {
char num_str[NUM_STR_REP_LEN];
outputNumInput(&data->num_input, num_str, &scene->unit);
@@ -1641,7 +1659,7 @@ static void sequencer_slip_update_header(Scene *scene, ScrArea *sa, SlipData *da
}
}
- ED_area_status_text(sa, msg);
+ ED_area_status_text(area, msg);
}
static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -1649,16 +1667,18 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SlipData *data = (SlipData *)op->customdata;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
const bool has_numInput = hasNumInput(&data->num_input);
bool handled = true;
- /* Modal numinput active, try to handle numeric inputs first... */
+ /* Modal numinput active, try to handle numeric inputs. */
if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
- float offset;
- applyNumInput(&data->num_input, &offset);
+ float offset_fl;
+ applyNumInput(&data->num_input, &offset_fl);
+ int offset = round_fl_to_int(offset_fl);
- sequencer_slip_update_header(scene, sa, data, (int)offset);
+ sequencer_slip_apply_limits(data, &offset);
+ sequencer_slip_update_header(scene, area, data, offset);
RNA_int_set(op->ptr, "offset", offset);
@@ -1686,11 +1706,12 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
mouse_x = event->mval[0];
}
- /* choose the side based on which side of the playhead the mouse is on */
+ /* Choose the side based on which side of the playhead the mouse is. */
UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
offset = mouseloc[0] - data->init_mouseloc[0];
- sequencer_slip_update_header(scene, sa, data, offset);
+ sequencer_slip_apply_limits(data, &offset);
+ sequencer_slip_update_header(scene, area, data, offset);
RNA_int_set(op->ptr, "offset", offset);
@@ -1702,22 +1723,22 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
}
case LEFTMOUSE:
- case RETKEY:
- case SPACEKEY: {
+ case EVT_RETKEY:
+ case EVT_SPACEKEY: {
MEM_freeN(data->seq_array);
MEM_freeN(data->trim);
MEM_freeN(data->ts);
MEM_freeN(data);
op->customdata = NULL;
- if (sa) {
- ED_area_status_text(sa, NULL);
+ if (area) {
+ ED_area_status_text(area, NULL);
}
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
}
- case ESCKEY:
+ case EVT_ESCKEY:
case RIGHTMOUSE: {
int i;
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -1742,15 +1763,15 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
- if (sa) {
- ED_area_status_text(sa, NULL);
+ if (area) {
+ ED_area_status_text(area, NULL);
}
return OPERATOR_CANCELLED;
}
- case RIGHTSHIFTKEY:
- case LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
+ case EVT_LEFTSHIFTKEY:
if (!has_numInput) {
if (event->val == KM_PRESS) {
data->slow = true;
@@ -1767,12 +1788,14 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
break;
}
- /* Modal numinput inactive, try to handle numeric inputs last... */
+ /* Modal numinput inactive, try to handle numeric inputs. */
if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
- float offset;
- applyNumInput(&data->num_input, &offset);
+ float offset_fl;
+ applyNumInput(&data->num_input, &offset_fl);
+ int offset = round_fl_to_int(offset_fl);
- sequencer_slip_update_header(scene, sa, data, (int)offset);
+ sequencer_slip_apply_limits(data, &offset);
+ sequencer_slip_update_header(scene, area, data, offset);
RNA_int_set(op->ptr, "offset", offset);
@@ -1786,18 +1809,18 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
void SEQUENCER_OT_slip(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Trim Strips";
ot->idname = "SEQUENCER_OT_slip";
ot->description = "Trim the contents of the active strip";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_slip_invoke;
ot->modal = sequencer_slip_modal;
ot->exec = sequencer_slip_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_int(ot->srna,
@@ -1811,7 +1834,7 @@ void SEQUENCER_OT_slip(struct wmOperatorType *ot)
INT32_MAX);
}
-/* mute operator */
+/* Mute operator. */
static int sequencer_mute_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1823,7 +1846,7 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op)
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if ((seq->flag & SEQ_LOCK) == 0) {
- if (selected) { /* mute unselected */
+ if (selected) {
if (seq->flag & SELECT) {
seq->flag |= SEQ_MUTE;
BKE_sequence_invalidate_dependent(scene, seq);
@@ -1846,23 +1869,23 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_mute(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Mute Strips";
ot->idname = "SEQUENCER_OT_mute";
ot->description = "Mute (un)selected strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_mute_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(
ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
}
-/* unmute operator */
+/* Unmute operator. */
static int sequencer_unmute_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1874,7 +1897,7 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op)
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if ((seq->flag & SEQ_LOCK) == 0) {
- if (selected) { /* unmute unselected */
+ if (selected) {
if (seq->flag & SELECT) {
seq->flag &= ~SEQ_MUTE;
BKE_sequence_invalidate_dependent(scene, seq);
@@ -1897,23 +1920,23 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Unmute Strips";
ot->idname = "SEQUENCER_OT_unmute";
ot->description = "Unmute (un)selected strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_unmute_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(
ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
}
-/* lock operator */
+/* Lock operator. */
static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -1933,20 +1956,20 @@ static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_lock(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Lock Strips";
ot->idname = "SEQUENCER_OT_lock";
ot->description = "Lock strips so they can't be transformed";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_lock_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* unlock operator */
+/* Unlock operator. */
static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -1966,20 +1989,20 @@ static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Unlock Strips";
ot->idname = "SEQUENCER_OT_unlock";
ot->description = "Unlock strips so they can be transformed";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_unlock_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* reload operator */
+/* Reload operator. */
static int sequencer_reload_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -2010,17 +2033,17 @@ void SEQUENCER_OT_reload(struct wmOperatorType *ot)
{
PropertyRNA *prop;
- /* identifiers */
+ /* Identifiers. */
ot->name = "Reload Strips";
ot->idname = "SEQUENCER_OT_reload";
ot->description = "Reload strips in the sequencer";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_reload_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER; /* no undo, the data changed is stored outside 'main' */
+ /* Flags. */
+ ot->flag = OPTYPE_REGISTER; /* No undo, the data changed is stored outside 'main'. */
prop = RNA_def_boolean(ot->srna,
"adjust_length",
@@ -2030,7 +2053,7 @@ void SEQUENCER_OT_reload(struct wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* reload operator */
+/* Reload operator. */
static bool sequencer_refresh_all_poll(bContext *C)
{
if (G.is_rendering) {
@@ -2053,12 +2076,12 @@ static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Refresh Sequencer";
ot->idname = "SEQUENCER_OT_refresh_all";
ot->description = "Refresh the sequencer editor";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_refresh_all_exec;
ot->poll = sequencer_refresh_all_poll;
}
@@ -2074,7 +2097,7 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, error_msg);
return OPERATOR_CANCELLED;
}
- /* see reassigning would create a cycle */
+ /* Check if reassigning would create recursivity. */
if (seq_is_predecessor(seq1, last_seq) || seq_is_predecessor(seq2, last_seq) ||
seq_is_predecessor(seq3, last_seq)) {
BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: no cycles allowed");
@@ -2109,16 +2132,16 @@ static bool sequencer_effect_poll(bContext *C)
void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Reassign Inputs";
ot->idname = "SEQUENCER_OT_reassign_inputs";
ot->description = "Reassign the inputs for the effect strip";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_reassign_inputs_exec;
ot->poll = sequencer_effect_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2144,65 +2167,73 @@ static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
}
void SEQUENCER_OT_swap_inputs(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Swap Inputs";
ot->idname = "SEQUENCER_OT_swap_inputs";
ot->description = "Swap the first two inputs for the effect strip";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_swap_inputs_exec;
ot->poll = sequencer_effect_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* cut operator */
-static const EnumPropertyItem prop_cut_types[] = {
- {SEQ_CUT_SOFT, "SOFT", 0, "Soft", ""},
- {SEQ_CUT_HARD, "HARD", 0, "Hard", ""},
+/* Split operator. */
+static const EnumPropertyItem prop_split_types[] = {
+ {SEQ_SPLIT_SOFT, "SOFT", 0, "Soft", ""},
+ {SEQ_SPLIT_HARD, "HARD", 0, "Hard", ""},
{0, NULL, 0, NULL, NULL},
};
-static int sequencer_cut_exec(bContext *C, wmOperator *op)
+static int sequencer_split_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
- int cut_side, cut_hard, cut_frame, cut_channel;
+ int split_side, split_hard, split_frame, split_channel;
bool changed, use_cursor_position, ignore_selection;
bool seq_selected = false;
- cut_frame = RNA_int_get(op->ptr, "frame");
- cut_channel = RNA_int_get(op->ptr, "channel");
+ split_frame = RNA_int_get(op->ptr, "frame");
+ split_channel = RNA_int_get(op->ptr, "channel");
use_cursor_position = RNA_boolean_get(op->ptr, "use_cursor_position");
- cut_hard = RNA_enum_get(op->ptr, "type");
- cut_side = RNA_enum_get(op->ptr, "side");
+ split_hard = RNA_enum_get(op->ptr, "type");
+ split_side = RNA_enum_get(op->ptr, "side");
ignore_selection = RNA_boolean_get(op->ptr, "ignore_selection");
- if (cut_hard == SEQ_CUT_HARD) {
- changed = cut_seq_list(
- bmain, scene, ed->seqbasep, cut_frame, cut_channel, use_cursor_position, cut_seq_hard);
+ if (split_hard == SEQ_SPLIT_HARD) {
+ changed = split_seq_list(bmain,
+ scene,
+ ed->seqbasep,
+ split_frame,
+ split_channel,
+ use_cursor_position,
+ split_seq_hard);
}
else {
- changed = cut_seq_list(
- bmain, scene, ed->seqbasep, cut_frame, cut_channel, use_cursor_position, cut_seq_soft);
- }
-
- if (changed) { /* got new strips ? */
+ changed = split_seq_list(bmain,
+ scene,
+ ed->seqbasep,
+ split_frame,
+ split_channel,
+ use_cursor_position,
+ split_seq_soft);
+ }
+ if (changed) { /* Got new strips? */
Sequence *seq;
-
if (ignore_selection) {
if (use_cursor_position) {
SEQP_BEGIN (ed, seq) {
- if (seq->enddisp == cut_frame && seq->machine == cut_channel) {
+ if (seq->enddisp == split_frame && seq->machine == split_channel) {
seq_selected = seq->flag & SEQ_ALLSEL;
}
}
SEQ_END;
if (!seq_selected) {
SEQP_BEGIN (ed, seq) {
- if (seq->startdisp == cut_frame && seq->machine == cut_channel) {
+ if (seq->startdisp == split_frame && seq->machine == split_channel) {
seq->flag &= ~SEQ_ALLSEL;
}
}
@@ -2211,15 +2242,15 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op)
}
}
else {
- if (cut_side != SEQ_SIDE_BOTH) {
+ if (split_side != SEQ_SIDE_BOTH) {
SEQP_BEGIN (ed, seq) {
- if (cut_side == SEQ_SIDE_LEFT) {
- if (seq->startdisp >= cut_frame) {
+ if (split_side == SEQ_SIDE_LEFT) {
+ if (seq->startdisp >= split_frame) {
seq->flag &= ~SEQ_ALLSEL;
}
}
else {
- if (seq->enddisp <= cut_frame) {
+ if (seq->enddisp <= split_frame) {
seq->flag &= ~SEQ_ALLSEL;
}
}
@@ -2234,10 +2265,8 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op)
}
SEQ_END;
- /* as last: */
BKE_sequencer_sort(scene);
}
-
if (changed) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -2248,51 +2277,50 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op)
}
}
-static int sequencer_cut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int sequencer_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
- int cut_side = RNA_enum_get(op->ptr, "side");
- int cut_frame = CFRA;
+ int split_side = RNA_enum_get(op->ptr, "side");
+ int split_frame = CFRA;
- if (cut_side == SEQ_SIDE_MOUSE) {
+ if (split_side == SEQ_SIDE_MOUSE) {
if (ED_operator_sequencer_active(C) && v2d) {
- cut_side = mouse_frame_side(v2d, event->mval[0], cut_frame);
+ split_side = mouse_frame_side(v2d, event->mval[0], split_frame);
}
else {
- cut_side = SEQ_SIDE_BOTH;
+ split_side = SEQ_SIDE_BOTH;
}
}
-
float mouseloc[2];
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
-
if (RNA_boolean_get(op->ptr, "use_cursor_position")) {
RNA_int_set(op->ptr, "frame", mouseloc[0]);
}
else {
- RNA_int_set(op->ptr, "frame", cut_frame);
+ RNA_int_set(op->ptr, "frame", split_frame);
}
RNA_int_set(op->ptr, "channel", mouseloc[1]);
- RNA_enum_set(op->ptr, "side", cut_side);
- /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */
- return sequencer_cut_exec(C, op);
+ RNA_enum_set(op->ptr, "side", split_side);
+ /*RNA_enum_set(op->ptr, "type", split_hard); */
+
+ return sequencer_split_exec(C, op);
}
-void SEQUENCER_OT_cut(struct wmOperatorType *ot)
+void SEQUENCER_OT_split(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Cut Strips";
- ot->idname = "SEQUENCER_OT_cut";
- ot->description = "Cut the selected strips";
+ /* Identifiers. */
+ ot->name = "Split Strips";
+ ot->idname = "SEQUENCER_OT_split";
+ ot->description = "Split the selected strips in two";
- /* api callbacks */
- ot->invoke = sequencer_cut_invoke;
- ot->exec = sequencer_cut_exec;
+ /* Api callbacks. */
+ ot->invoke = sequencer_split_invoke;
+ ot->exec = sequencer_split_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
PropertyRNA *prop;
@@ -2302,7 +2330,7 @@ void SEQUENCER_OT_cut(struct wmOperatorType *ot)
INT_MIN,
INT_MAX,
"Frame",
- "Frame where selected strips will be cut",
+ "Frame where selected strips will be split",
INT_MIN,
INT_MAX);
RNA_def_int(ot->srna,
@@ -2316,21 +2344,23 @@ void SEQUENCER_OT_cut(struct wmOperatorType *ot)
INT_MAX);
RNA_def_enum(ot->srna,
"type",
- prop_cut_types,
- SEQ_CUT_SOFT,
+ prop_split_types,
+ SEQ_SPLIT_SOFT,
"Type",
- "The type of cut operation to perform on strips");
+ "The type of split operation to perform on strips");
+
RNA_def_boolean(ot->srna,
"use_cursor_position",
0,
"Use Cursor Position",
- "Cut at position of the cursor instead of playhead");
+ "Split at position of the cursor instead of playhead");
+
prop = RNA_def_enum(ot->srna,
"side",
prop_side_types,
SEQ_SIDE_MOUSE,
"Side",
- "The side that remains selected after cutting");
+ "The side that remains selected after splitting");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
@@ -2346,8 +2376,8 @@ void SEQUENCER_OT_cut(struct wmOperatorType *ot)
#undef SEQ_SIDE_MOUSE
-/* duplicate operator */
-static int apply_unique_name_cb(Sequence *seq, void *arg_pt)
+/* Duplicate operator. */
+static int apply_unique_name_fn(Sequence *seq, void *arg_pt)
{
Scene *scene = (Scene *)arg_pt;
char name[sizeof(seq->name) - 2];
@@ -2373,11 +2403,11 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
if (nseqbase.first) {
Sequence *seq = nseqbase.first;
- /* rely on the nseqbase list being added at the end */
+ /* Rely on the nseqbase list being added at the end. */
BLI_movelisttolist(ed->seqbasep, &nseqbase);
for (; seq; seq = seq->next) {
- BKE_sequencer_recursive_apply(seq, apply_unique_name_cb, scene);
+ BKE_sequencer_recursive_apply(seq, apply_unique_name_fn, scene);
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2389,20 +2419,20 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_duplicate(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Duplicate Strips";
ot->idname = "SEQUENCER_OT_duplicate";
ot->description = "Duplicate the selected strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_add_duplicate_exec;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* delete operator */
+/* Delete operator. */
static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
@@ -2413,7 +2443,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
bool nothing_selected = true;
seq = BKE_sequencer_active_get(scene);
- if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
+ if (seq && seq->flag & SELECT) { /* Avoid a loop since this is likely to be selected. */
nothing_selected = false;
}
else {
@@ -2429,7 +2459,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
- /* for effects and modifiers, try to find a replacement input */
+ /* For effects and modifiers, try to find a replacement input. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (!(seq->flag & SELECT)) {
if ((seq->type & SEQ_TYPE_EFFECT)) {
@@ -2441,17 +2471,17 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- /* delete all selected strips */
+ /* Delete all selected strips. */
recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
- /* updates lengths etc */
+ /* Update lengths, etc. */
seq = ed->seqbasep->first;
while (seq) {
BKE_sequence_calc(scene, seq);
seq = seq->next;
}
- /* free parent metas */
+ /* Free parent metas. */
ms = ed->metastack.last;
while (ms) {
BKE_sequence_calc(scene, ms->parseq);
@@ -2467,11 +2497,11 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- /* bounding box of 30 pixels is used for markers shortcuts,
- * prevent conflict with markers shortcuts here
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ /* Bounding box of 30 pixels is used for markers shortcuts,
+ * prevent conflict with markers shortcuts here.
*/
if (event->mval[1] <= 30) {
return OPERATOR_PASS_THROUGH;
@@ -2484,35 +2514,35 @@ static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *e
void SEQUENCER_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Erase Strips";
ot->idname = "SEQUENCER_OT_delete";
ot->description = "Erase selected strips from the sequencer";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_delete_invoke;
ot->exec = sequencer_delete_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* offset clear operator */
+/* Offset clear operator. */
static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq;
- /* for effects, try to find a replacement input */
+ /* For effects, try to find a replacement input. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
seq->startofs = seq->endofs = seq->startstill = seq->endstill = 0;
}
}
- /* updates lengths etc */
+ /* Update lengths, etc. */
seq = ed->seqbasep->first;
while (seq) {
BKE_sequence_calc(scene, seq);
@@ -2535,20 +2565,20 @@ static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Clear Strip Offset";
ot->idname = "SEQUENCER_OT_offset_clear";
ot->description = "Clear strip offsets from the start and end frames";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_offset_clear_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* separate_images operator */
+/* Separate_images operator. */
static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -2560,13 +2590,13 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
int start_ofs, cfra, frame_end;
int step = RNA_int_get(op->ptr, "length");
- seq = ed->seqbasep->first; /* poll checks this is valid */
+ seq = ed->seqbasep->first; /* Poll checks this is valid. */
while (seq) {
if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) && (seq->len > 1)) {
Sequence *seq_next;
- /* remove seq so overlap tests don't conflict,
+ /* Remove seq so overlap tests don't conflict,
* see seq_free_sequence below for the real freeing. */
BLI_remlink(ed->seqbasep, seq);
/* if (seq->ipo) id_us_min(&seq->ipo->id); */
@@ -2576,7 +2606,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
frame_end = BKE_sequence_tx_get_final_right(seq, false);
while (cfra < frame_end) {
- /* new seq */
+ /* New seq. */
se = BKE_sequencer_give_stripelem(seq, cfra);
seq_new = BKE_sequence_dupli_recursive(
@@ -2587,11 +2617,11 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
seq_new->len = 1;
seq_new->endstill = step - 1;
- /* new strip */
+ /* New strip. */
strip_new = seq_new->strip;
strip_new->us = 1;
- /* new stripdata (only one element now!) */
+ /* New stripdata, only one element now. */
/* Note this assume all elements (images) have the same dimension,
* since we only copy the name here. */
se_new = MEM_reallocN(strip_new->stripdata, sizeof(*se_new));
@@ -2614,7 +2644,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
}
seq_next = seq->next;
- BKE_sequence_free(scene, seq);
+ BKE_sequence_free(scene, seq, true);
seq = seq_next;
}
else {
@@ -2622,7 +2652,6 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
}
}
- /* as last: */
BKE_sequencer_sort(scene);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2632,25 +2661,25 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_images_separate(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Separate Images";
ot->idname = "SEQUENCER_OT_images_separate";
ot->description = "On image sequence strips, it returns a strip for each image";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_separate_images_exec;
ot->invoke = WM_operator_props_popup_confirm;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
}
-/* META Operators */
+/* META Operators. */
-/* separate_meta_toggle operator */
+/* Separate_meta_toggle operator. */
static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -2659,7 +2688,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
MetaStack *ms;
if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) {
- /* Enter Metastrip */
+ /* Enter metastrip. */
ms = MEM_mallocN(sizeof(MetaStack), "metastack");
BLI_addtail(&ed->metastack, ms);
ms->parseq = last_seq;
@@ -2671,7 +2700,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
BKE_sequencer_active_set(scene, NULL);
}
else {
- /* Exit Metastrip (if possible) */
+ /* Exit metastrip if possible. */
Sequence *seq;
@@ -2684,18 +2713,18 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
ed->seqbasep = ms->oldbasep;
- /* for old files, update from meta */
+ /* For old files, update from meta. */
if (ms->disp_range[0] == ms->disp_range[1]) {
copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
}
- /* recalc all: the meta can have effects connected to it */
+ /* Recalc all: the meta can have effects connected to it. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
BKE_sequence_calc(scene, seq);
}
/* 2.73+, keeping endpoints is important!
- * moving them around means you can't usefully use metas in a complex edit. */
+ * Moving them around means you can't usefully use metas in a complex edit. */
#if 1
BKE_sequence_tx_set_final_left(ms->parseq, ms->disp_range[0]);
BKE_sequence_tx_set_final_right(ms->parseq, ms->disp_range[1]);
@@ -2723,20 +2752,20 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Toggle Meta Strip";
ot->idname = "SEQUENCER_OT_meta_toggle";
ot->description = "Toggle a metastrip (to edit enclosed strips)";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_meta_toggle_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* separate_meta_make operator */
+/* Separate_meta_make operator. */
static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -2750,9 +2779,9 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- /* remove all selected from main list, and put in meta */
+ /* Remove all selected from main list, and put in meta. */
- seqm = BKE_sequence_alloc(ed->seqbasep, 1, 1, SEQ_TYPE_META); /* channel number set later */
+ seqm = BKE_sequence_alloc(ed->seqbasep, 1, 1, SEQ_TYPE_META); /* Channel number set later. */
strcpy(seqm->name + 2, "MetaStrip");
seqm->flag = SELECT;
@@ -2787,16 +2816,16 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_meta_make(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Make Meta Strip";
ot->idname = "SEQUENCER_OT_meta_make";
ot->description = "Group selected strips into a metastrip";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_meta_make_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@@ -2819,7 +2848,7 @@ static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
}
}
-/* separate_meta_make operator */
+/* Separate_meta_make operator. */
static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -2840,9 +2869,9 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
BLI_listbase_clear(&last_seq->seqbase);
BLI_remlink(ed->seqbasep, last_seq);
- BKE_sequence_free(scene, last_seq);
+ BKE_sequence_free(scene, last_seq, true);
- /* empty meta strip, delete all effects depending on it */
+ /* Empty meta strip, delete all effects depending on it. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if ((seq->type & SEQ_TYPE_EFFECT) && seq_depends_on_meta(seq, last_seq)) {
seq->flag |= SEQ_FLAG_DELETE;
@@ -2851,8 +2880,8 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
- /* test for effects and overlap
- * don't use SEQP_BEGIN since that would be recursive */
+ /* Test for effects and overlap
+ * don't use SEQP_BEGIN since that would be recursive. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
seq->flag &= ~SEQ_OVERLAP;
@@ -2872,44 +2901,44 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "UnMeta Strip";
ot->idname = "SEQUENCER_OT_meta_separate";
ot->description = "Put the contents of a metastrip back in the sequencer";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_meta_separate_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* view_all operator */
+/* View_all operator. */
static int sequencer_view_all_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
rctf box;
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
boundbox_seq(CTX_data_scene(C), &box);
- UI_view2d_smooth_view(C, ar, &box, smooth_viewtx);
+ UI_view2d_smooth_view(C, region, &box, smooth_viewtx);
return OPERATOR_FINISHED;
}
void SEQUENCER_OT_view_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
+ /* Identifiers. */
+ ot->name = "Frame All";
ot->idname = "SEQUENCER_OT_view_all";
ot->description = "View all the strips in the sequencer";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_view_all_exec;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER;
}
@@ -2923,26 +2952,26 @@ static int sequencer_view_frame_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_view_frame(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Frame";
+ /* Identifiers. */
+ ot->name = "Go to Current Frame";
ot->idname = "SEQUENCER_OT_view_frame";
- ot->description = "Reset viewable area to show range around current frame";
+ ot->description = "Move the view to the playhead";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_view_frame_exec;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = 0;
}
-/* view_all operator */
+/* View_all operator. */
static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
{
- bScreen *sc = CTX_wm_screen(C);
+ bScreen *screen = CTX_wm_screen(C);
ScrArea *area = CTX_wm_area(C);
#if 0
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceSeq *sseq = area->spacedata.first;
Scene *scene = CTX_data_scene(C);
#endif
@@ -2950,26 +2979,26 @@ static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
v2d->cur = v2d->tot;
UI_view2d_curRect_validate(v2d);
- UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
+ UI_view2d_sync(screen, area, v2d, V2D_LOCK_COPY);
#if 0
- /* Like zooming on an image view */
+ /* Like zooming on an image view. */
float zoomX, zoomY;
int width, height, imgwidth, imgheight;
- width = ar->winx;
- height = ar->winy;
+ width = region->winx;
+ height = region->winy;
seq_reset_imageofs(sseq);
imgwidth = (scene->r.size * scene->r.xsch) / 100;
imgheight = (scene->r.size * scene->r.ysch) / 100;
- /* Apply aspect, doesn't need to be that accurate */
+ /* Apply aspect, doesn't need to be that accurate. */
imgwidth = (int)(imgwidth * (scene->r.xasp / scene->r.yasp));
if (((imgwidth >= width) || (imgheight >= height)) && ((width > 0) && (height > 0))) {
- /* Find the zoom value that will fit the image in the image space */
+ /* Find the zoom value that will fit the image in the image space. */
zoomX = ((float)width) / ((float)imgwidth);
zoomY = ((float)height) / ((float)imgheight);
sseq->zoom = (zoomX < zoomY) ? zoomX : zoomY;
@@ -2987,16 +3016,16 @@ static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View All";
+ /* Identifiers. */
+ ot->name = "Frame All";
ot->idname = "SEQUENCER_OT_view_all_preview";
ot->description = "Zoom preview to fit in the area";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_view_all_preview_exec;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER;
}
@@ -3022,16 +3051,16 @@ static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Sequencer View Zoom Ratio";
ot->idname = "SEQUENCER_OT_view_zoom_ratio";
ot->description = "Change zoom ratio of sequencer preview";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_view_zoom_ratio_exec;
ot->poll = ED_operator_sequencer_active;
- /* properties */
+ /* Properties. */
RNA_def_float(ot->srna,
"ratio",
1.0f,
@@ -3056,7 +3085,7 @@ static const EnumPropertyItem view_type_items[] = {
};
#endif
-/* view_all operator */
+/* View_all operator. */
static int sequencer_view_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
@@ -3073,25 +3102,25 @@ static int sequencer_view_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "View Toggle";
ot->idname = "SEQUENCER_OT_view_toggle";
ot->description = "Toggle between sequencer views (sequence, preview, both)";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_view_toggle_exec;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER;
}
-/* view_selected operator */
+/* View_selected operator. */
static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *last_seq = BKE_sequencer_active_get(scene);
Sequence *seq;
@@ -3136,7 +3165,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
cur_new.ymin = ymin;
cur_new.ymax = ymax;
- /* only zoom out vertically */
+ /* Only zoom out vertically. */
if (orig_height > BLI_rctf_size_y(&cur_new)) {
ymid = BLI_rctf_cent_y(&cur_new);
@@ -3144,7 +3173,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
cur_new.ymax = ymid + (orig_height / 2);
}
- UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
+ UI_view2d_smooth_view(C, region, &cur_new, smooth_viewtx);
return OPERATOR_FINISHED;
}
@@ -3155,16 +3184,16 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_view_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "View Selected";
+ /* Identifiers. */
+ ot->name = "Frame Selected";
ot->idname = "SEQUENCER_OT_view_selected";
ot->description = "Zoom the sequencer on the selected strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_view_selected_exec;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER;
}
@@ -3187,7 +3216,7 @@ static bool strip_jump_internal(Scene *scene,
static bool sequencer_strip_jump_poll(bContext *C)
{
- /* prevent changes during render */
+ /* Prevent changes during render. */
if (G.is_rendering) {
return 0;
}
@@ -3195,14 +3224,14 @@ static bool sequencer_strip_jump_poll(bContext *C)
return sequencer_edit_poll(C);
}
-/* jump frame to edit point operator */
+/* Jump frame to edit point operator. */
static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
const bool next = RNA_boolean_get(op->ptr, "next");
const bool center = RNA_boolean_get(op->ptr, "center");
- /* currently do_skip_mute is always true */
+ /* Currently do_skip_mute is always true. */
if (!strip_jump_internal(scene, next ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT, true, center)) {
return OPERATOR_CANCELLED;
}
@@ -3214,19 +3243,19 @@ static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Jump to Strip";
ot->idname = "SEQUENCER_OT_strip_jump";
ot->description = "Move frame to previous edit point";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_strip_jump_exec;
ot->poll = sequencer_strip_jump_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_UNDO;
- /* properties */
+ /* Properties. */
RNA_def_boolean(ot->srna, "next", true, "Next Strip", "");
RNA_def_boolean(ot->srna, "center", true, "Use strip center", "");
}
@@ -3284,7 +3313,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
if (seq) {
- /* disallow effect strips */
+ /* Disallow effect strips. */
if (BKE_sequence_effect_get_num_inputs(seq->type) >= 1 &&
(seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3)) {
return OPERATOR_CANCELLED;
@@ -3303,7 +3332,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
break;
}
- // XXX - should be a generic function
+ /* XXX - Should be a generic function. */
for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
if ((iseq->type & SEQ_TYPE_EFFECT) &&
(seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
@@ -3311,11 +3340,11 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
}
}
- /* do this in a new loop since both effects need to be calculated first */
+ /* Do this in a new loop since both effects need to be calculated first. */
for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
if ((iseq->type & SEQ_TYPE_EFFECT) &&
(seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
- /* this may now overlap */
+ /* This may now overlap. */
if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) {
BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
}
@@ -3334,19 +3363,19 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_swap(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Swap Strip";
ot->idname = "SEQUENCER_OT_swap";
ot->description = "Swap active strip with strip to the right or left";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_swap_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* Properties. */
RNA_def_enum(
ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
}
@@ -3380,7 +3409,7 @@ static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
}
if (se) {
- // prevent setting the render size if sequence values aren't initialized
+ /* Prevent setting the render size if sequence values aren't initialized. */
if ((se->orig_width > 0) && (se->orig_height > 0)) {
scene->r.xsch = se->orig_width;
scene->r.ysch = se->orig_height;
@@ -3394,19 +3423,17 @@ static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_rendersize(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Set Render Size";
ot->idname = "SEQUENCER_OT_rendersize";
ot->description = "Set render size and aspect from active sequence";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_rendersize_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
}
static void seq_copy_del_sound(Scene *scene, Sequence *seq)
@@ -3429,8 +3456,6 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
- ListBase nseqbase = {NULL, NULL};
-
BKE_sequencer_free_clipboard();
if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
@@ -3439,33 +3464,12 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
}
BKE_sequence_base_dupli_recursive(
- scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME, LIB_ID_CREATE_NO_USER_REFCOUNT);
-
- /* To make sure the copied strips have unique names between each other add
- * them temporarily to the end of the original seqbase. (bug 25932)
- */
- if (nseqbase.first) {
- Sequence *seq, *first_seq = nseqbase.first;
- BLI_movelisttolist(ed->seqbasep, &nseqbase);
-
- for (seq = first_seq; seq; seq = seq->next) {
- BKE_sequencer_recursive_apply(seq, apply_unique_name_cb, scene);
- }
-
- seqbase_clipboard.first = first_seq;
- seqbase_clipboard.last = ed->seqbasep->last;
-
- if (first_seq->prev) {
- first_seq->prev->next = NULL;
- ed->seqbasep->last = first_seq->prev;
- first_seq->prev = NULL;
- }
- }
+ scene, scene, &seqbase_clipboard, ed->seqbasep, 0, LIB_ID_CREATE_NO_USER_REFCOUNT);
seqbase_clipboard_frame = scene->r.cfra;
- /* Need to remove anything that references the current scene */
- for (Sequence *seq = seqbase_clipboard.first; seq; seq = seq->next) {
+ /* Remove anything that references the current scene. */
+ LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) {
seq_copy_del_sound(scene, seq);
}
@@ -3478,26 +3482,24 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_copy(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Copy";
ot->idname = "SEQUENCER_OT_copy";
ot->description = "Copy selected strips to clipboard";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_copy_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER;
-
- /* properties */
}
static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = BKE_sequencer_editing_get(scene, true); /* create if needed */
+ Editing *ed = BKE_sequencer_editing_get(scene, true); /* Create if needed. */
ListBase nseqbase = {NULL, NULL};
int ofs;
Sequence *iseq, *iseq_first;
@@ -3509,28 +3511,19 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
* must happen on the clipboard itself, so that copying does user counting
* on the actual data-blocks. */
BKE_sequencer_base_clipboard_pointers_restore(&seqbase_clipboard, bmain);
- BKE_sequence_base_dupli_recursive(
- scene, scene, &nseqbase, &seqbase_clipboard, SEQ_DUPE_UNIQUE_NAME, 0);
- BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard);
-
- /* transform pasted strips before adding */
- if (ofs) {
- for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
- BKE_sequence_translate(scene, iseq, ofs);
- }
- }
+ BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, 0, 0);
iseq_first = nseqbase.first;
BLI_movelisttolist(ed->seqbasep, &nseqbase);
- /* make sure the pasted strips have unique names between them */
- for (iseq = iseq_first; iseq; iseq = iseq->next) {
- BKE_sequencer_recursive_apply(iseq, apply_unique_name_cb, scene);
- }
-
- /* ensure pasted strips don't overlap */
for (iseq = iseq_first; iseq; iseq = iseq->next) {
+ /* Make sure, that pasted strips have unique names. */
+ BKE_sequencer_recursive_apply(iseq, apply_unique_name_fn, scene);
+ /* Translate after name has been changed, otherwise this will affect animdata of original
+ * strip. */
+ BKE_sequence_translate(scene, iseq, ofs);
+ /* Ensure, that pasted strips don't overlap. */
if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) {
BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
}
@@ -3538,25 +3531,24 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ ED_outliner_select_sync_from_sequence_tag(C);
return OPERATOR_FINISHED;
}
void SEQUENCER_OT_paste(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Paste";
ot->idname = "SEQUENCER_OT_paste";
ot->description = "Paste strips from clipboard";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_paste_exec;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
}
static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
@@ -3607,22 +3599,20 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_swap_data(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Sequencer Swap Data";
ot->idname = "SEQUENCER_OT_swap_data";
ot->description = "Swap 2 sequencer strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_swap_data_exec;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
}
-/* box select operator */
+/* Box select operator. */
static int view_ghost_border_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -3630,7 +3620,7 @@ static int view_ghost_border_exec(bContext *C, wmOperator *op)
rctf rect;
- /* convert coordinates of rect to 'tot' rect coordinates */
+ /* Convert coordinates of rect to 'tot' rect coordinates. */
WM_operator_properties_border_to_rctf(op, &rect);
UI_view2d_region_to_view_rctf(v2d, &rect, &rect);
@@ -3657,30 +3647,28 @@ static int view_ghost_border_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* ****** Box Select ****** */
void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Border Offset View";
ot->idname = "SEQUENCER_OT_view_ghost_border";
ot->description = "Set the boundaries of the border used for offset-view";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = WM_gesture_box_invoke;
ot->exec = view_ghost_border_exec;
ot->modal = WM_gesture_box_modal;
ot->poll = sequencer_view_preview_poll;
ot->cancel = WM_gesture_box_cancel;
- /* flags */
+ /* Flags. */
ot->flag = 0;
- /* rna */
+ /* Properties. */
WM_operator_properties_gesture_box(ot);
}
-/* rebuild_proxy operator */
-
+/* Rebuild_proxy operator. */
static int sequencer_rebuild_proxy_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
@@ -3731,16 +3719,16 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Rebuild Proxy and Timecode Indices";
ot->idname = "SEQUENCER_OT_rebuild_proxy";
ot->description = "Rebuild all selected proxies and timecode indices using the job system";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_rebuild_proxy_invoke;
ot->exec = sequencer_rebuild_proxy_exec;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER;
}
@@ -3748,7 +3736,7 @@ static int sequencer_enable_proxies_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
{
- return WM_operator_props_dialog_popup(C, op, 200, 100);
+ return WM_operator_props_dialog_popup(C, op, 200);
}
static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
@@ -3826,16 +3814,16 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Set Selected Strip Proxies";
ot->idname = "SEQUENCER_OT_enable_proxies";
ot->description = "Enable selected proxies on all selected Movie, Image and Meta strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_enable_proxies_invoke;
ot->exec = sequencer_enable_proxies_exec;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER;
RNA_def_boolean(ot->srna, "proxy_25", false, "25%", "");
@@ -3845,8 +3833,7 @@ void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite", "");
}
-/* change ops */
-
+/* Change effect inputs operator. */
static const EnumPropertyItem prop_change_effect_input_types[] = {
{0, "A_B", 0, "A -> B", ""},
{1, "B_C", 0, "B -> C", ""},
@@ -3887,9 +3874,8 @@ static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
- /* important else we don't get the imbuf cache flushed */
+ /* Invalidate cache. */
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
-
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -3897,21 +3883,22 @@ static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_change_effect_input(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Change Effect Input";
ot->idname = "SEQUENCER_OT_change_effect_input";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_change_effect_input_exec;
ot->poll = sequencer_effect_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->prop = RNA_def_enum(
ot->srna, "swap", prop_change_effect_input_types, 0, "Swap", "The effect inputs to swap");
}
+/* Change effect type operator. */
static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -3919,14 +3906,14 @@ static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
Sequence *seq = BKE_sequencer_active_get(scene);
const int new_type = RNA_enum_get(op->ptr, "type");
- /* free previous effect and init new effect */
+ /* Free previous effect and init new effect. */
struct SeqEffectHandle sh;
if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
return OPERATOR_CANCELLED;
}
- /* can someone explain the logic behind only allowing to increase this,
+ /* Can someone explain the logic behind only allowing to increase this,
* copied from 2.4x - campbell */
if (BKE_sequence_effect_get_num_inputs(seq->type) <
BKE_sequence_effect_get_num_inputs(new_type)) {
@@ -3943,10 +3930,8 @@ static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
sh.init(seq);
}
- /* update */
BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
-
- /* important else we don't get the imbuf cache flushed */
+ /* Invalidate cache. */
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -3956,15 +3941,15 @@ static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Change Effect Type";
ot->idname = "SEQUENCER_OT_change_effect_type";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_change_effect_type_exec;
ot->poll = sequencer_effect_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->prop = RNA_def_enum(ot->srna,
@@ -3975,6 +3960,7 @@ void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot)
"Sequencer effect type");
}
+/* Change path operator. */
static int sequencer_change_path_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -3990,7 +3976,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
int len;
StripElem *se;
- /* need to find min/max frame for placeholders */
+ /* Need to find min/max frame for placeholders. */
if (use_placeholders) {
len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe, &numdigits);
}
@@ -4028,16 +4014,16 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
RNA_END;
}
- /* reset these else we wont see all the images */
+ /* Reset these else we wont see all the images. */
seq->anim_startofs = seq->anim_endofs = 0;
- /* correct start/end frames so we don't move
- * important not to set seq->len = len; allow the function to handle it */
+ /* Correct start/end frames so we don't move.
+ * Important not to set seq->len = len; allow the function to handle it. */
BKE_sequence_reload_new_file(bmain, scene, seq, true);
BKE_sequence_calc(scene, seq);
- /* important else we don't get the imbuf cache flushed */
+ /* Invalidate cache. */
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
}
else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
@@ -4051,7 +4037,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
BKE_sound_load(bmain, sound);
}
else {
- /* lame, set rna filepath */
+ /* Lame, set rna filepath. */
PointerRNA seq_ptr;
PropertyRNA *prop;
char filepath[FILE_MAX];
@@ -4080,7 +4066,7 @@ static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEve
RNA_string_set(op->ptr, "directory", seq->strip->dir);
RNA_string_set(op->ptr, "filepath", filepath);
- /* set default display depending on seq type */
+ /* Set default display depending on seq type. */
if (seq->type == SEQ_TYPE_IMAGE) {
RNA_boolean_set(op->ptr, "filter_movie", false);
}
@@ -4095,16 +4081,16 @@ static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEve
void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Change Data/Files";
ot->idname = "SEQUENCER_OT_change_path";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_change_path_exec;
ot->invoke = sequencer_change_path_invoke;
ot->poll = sequencer_strip_has_path_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_filesel(ot,
@@ -4122,6 +4108,7 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
"Use placeholders for missing frames of the strip");
}
+/* Export subtitles operator. */
static int sequencer_export_subtitles_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
@@ -4164,7 +4151,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", filepath);
BLI_path_extension_ensure(filepath, sizeof(filepath), ".srt");
- /* Avoid File write exceptions */
+ /* Avoid File write exceptions. */
if (!BLI_exists(filepath)) {
BLI_make_existing_file(filepath);
if (!BLI_file_touch(filepath)) {
@@ -4191,7 +4178,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
BLI_listbase_sort(&text_seq, BKE_sequencer_cmp_time_startdisp);
- /* time to open and write! */
+ /* Open and write file. */
file = BLI_fopen(filepath, "w");
for (seq = text_seq.first; seq; seq = seq_next) {
@@ -4234,17 +4221,17 @@ static bool sequencer_strip_is_text_poll(bContext *C)
void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Export Subtitles";
ot->idname = "SEQUENCER_OT_export_subtitles";
ot->description = "Export .srt file containing text strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_export_subtitles_exec;
ot->invoke = sequencer_export_subtitles_invoke;
ot->poll = sequencer_strip_is_text_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_filesel(ot,
@@ -4256,6 +4243,7 @@ void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot)
FILE_SORT_ALPHA);
}
+/* Set range to strips operator. */
static int sequencer_set_range_to_strips_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -4304,16 +4292,16 @@ void SEQUENCER_OT_set_range_to_strips(struct wmOperatorType *ot)
{
PropertyRNA *prop;
- /* identifiers */
+ /* Identifiers. */
ot->name = "Set Range to Strips";
ot->idname = "SEQUENCER_OT_set_range_to_strips";
ot->description = "Set the frame range to the selected strips start and end";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_set_range_to_strips_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_boolean(ot->srna, "preview", false, "Preview", "Set the preview range instead");
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 0a51578da3b..708682cd04f 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -24,10 +24,10 @@
#ifndef __SEQUENCER_INTERN_H__
#define __SEQUENCER_INTERN_H__
-#include "RNA_access.h"
#include "DNA_sequence_types.h"
+#include "RNA_access.h"
-/* internal exports only */
+/* Internal exports only. */
struct ARegion;
struct ARegionType;
@@ -42,10 +42,10 @@ struct rctf;
struct wmOperator;
/* sequencer_draw.c */
-void draw_timeline_seq(const struct bContext *C, struct ARegion *ar);
+void draw_timeline_seq(const struct bContext *C, struct ARegion *region);
void sequencer_draw_preview(const struct bContext *C,
struct Scene *scene,
- struct ARegion *ar,
+ struct ARegion *region,
struct SpaceSeq *sseq,
int cfra,
int offset,
@@ -54,9 +54,10 @@ void sequencer_draw_preview(const struct bContext *C,
void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]);
void sequencer_special_update_set(Sequence *seq);
+float sequence_handle_size_get_clamped(struct Sequence *seq, const float pixelx);
/* UNUSED */
-// void seq_reset_imageofs(struct SpaceSeq *sseq);
+/* void seq_reset_imageofs(struct SpaceSeq *sseq); */
struct ImBuf *sequencer_ibuf_get(struct Main *bmain,
struct Depsgraph *depsgraph,
@@ -82,28 +83,28 @@ void recurs_sel_seq(struct Sequence *seqm);
int seq_effect_find_selected(struct Scene *scene,
struct Sequence *activeseq,
int type,
- struct Sequence **selseq1,
- struct Sequence **selseq2,
- struct Sequence **selseq3,
- const char **error_str);
+ struct Sequence **r_selseq1,
+ struct Sequence **r_selseq2,
+ struct Sequence **r_selseq3,
+ const char **r_error_str);
-/* operator helpers */
+/* Operator helpers. */
bool sequencer_edit_poll(struct bContext *C);
/* UNUSED */
-// bool sequencer_strip_poll(struct bContext *C);
+/* bool sequencer_strip_poll(struct bContext *C); */
bool sequencer_strip_has_path_poll(struct bContext *C);
bool sequencer_view_preview_poll(struct bContext *C);
bool sequencer_view_strips_poll(struct bContext *C);
-/* externs */
+/* Externs. */
extern EnumPropertyItem sequencer_prop_effect_types[];
extern EnumPropertyItem prop_side_types[];
-/* operators */
+/* Operators. */
struct wmKeyConfig;
struct wmOperatorType;
-void SEQUENCER_OT_cut(struct wmOperatorType *ot);
+void SEQUENCER_OT_split(struct wmOperatorType *ot);
void SEQUENCER_OT_slip(struct wmOperatorType *ot);
void SEQUENCER_OT_mute(struct wmOperatorType *ot);
void SEQUENCER_OT_unmute(struct wmOperatorType *ot);
@@ -151,7 +152,7 @@ void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot);
void SEQUENCER_OT_set_range_to_strips(struct wmOperatorType *ot);
-/* preview specific operators */
+/* Preview specific operators. */
void SEQUENCER_OT_view_all_preview(struct wmOperatorType *ot);
/* sequencer_select.c */
@@ -177,8 +178,8 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot);
void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot);
enum {
- SEQ_CUT_SOFT,
- SEQ_CUT_HARD,
+ SEQ_SPLIT_SOFT,
+ SEQ_SPLIT_HARD,
};
enum {
SEQ_SELECTED,
@@ -192,8 +193,8 @@ enum {
SEQ_SELECT_LR_RIGHT,
};
-/* defines used internally */
-#define SCE_MARKERS 0 // XXX - dummy
+/* Defines used internally. */
+#define SCE_MARKERS 0 /* XXX - dummy */
/* sequencer_ops.c */
void sequencer_operatortypes(void);
@@ -221,7 +222,7 @@ void SEQUENCER_OT_sample(struct wmOperatorType *ot);
/* sequencer_preview.c */
void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq);
-/* sequencer_add */
+/* sequencer_add.c */
int sequencer_image_seq_get_minmax_frame(struct wmOperator *op,
int sfra,
int *r_minframe,
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index b90dc5e10ff..e0f7179c3f9 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -35,7 +35,7 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-/* own include */
+/* Own include. */
#include "sequencer_intern.h"
/*********************** Add modifier operator *************************/
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index af03035d10f..ac00838a079 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -21,18 +21,18 @@
* \ingroup spseq
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include "DNA_space_types.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_sequencer.h"
#include "ED_markers.h"
-#include "ED_transform.h" /* transform keymap */
#include "ED_select_utils.h"
+#include "ED_sequencer.h"
+#include "ED_transform.h" /* Transform keymap. */
#include "BKE_sequencer.h"
@@ -43,7 +43,7 @@
void sequencer_operatortypes(void)
{
/* sequencer_edit.c */
- WM_operatortype_append(SEQUENCER_OT_cut);
+ WM_operatortype_append(SEQUENCER_OT_split);
WM_operatortype_append(SEQUENCER_OT_slip);
WM_operatortype_append(SEQUENCER_OT_mute);
WM_operatortype_append(SEQUENCER_OT_unmute);
diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c
index 8ec3ed850d2..7d416884721 100644
--- a/source/blender/editors/space_sequencer/sequencer_preview.c
+++ b/source/blender/editors/space_sequencer/sequencer_preview.c
@@ -27,9 +27,9 @@
#include "BLI_listbase.h"
#include "BLI_threads.h"
-#include "BKE_sound.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_sound.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -52,9 +52,9 @@ typedef struct PreviewJobAudio {
struct PreviewJobAudio *next, *prev;
struct Main *bmain;
bSound *sound;
- int lr; /* sample left or right */
+ int lr; /* Sample left or right. */
int startframe;
- bool waveform; /* reload sound or waveform */
+ bool waveform; /* Reload sound or waveform. */
} PreviewJobAudio;
static void free_preview_job(void *data)
@@ -66,7 +66,7 @@ static void free_preview_job(void *data)
MEM_freeN(pj);
}
-/* only this runs inside thread */
+/* Only this runs inside thread. */
static void preview_startjob(void *data, short *stop, short *do_update, float *progress)
{
PreviewJob *pj = data;
@@ -89,7 +89,7 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p
while (previewjb) {
sound = previewjb->sound;
- /* make sure we cleanup the loading flag! */
+ /* Make sure we cleanup the loading flag! */
BLI_spin_lock(sound->spinlock);
sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
BLI_spin_unlock(sound->spinlock);
@@ -127,10 +127,9 @@ static void preview_endjob(void *data)
void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
{
- /* first, get the preview job, if it exists */
wmJob *wm_job;
PreviewJob *pj;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
PreviewJobAudio *audiojob = MEM_callocN(sizeof(PreviewJobAudio), "preview_audio");
wm_job = WM_jobs_get(CTX_wm_manager(C),
CTX_wm_window(C),
@@ -139,6 +138,7 @@ void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
WM_JOB_PROGRESS,
WM_JOB_TYPE_SEQ_BUILD_PREVIEW);
+ /* Get the preview job if it exists. */
pj = WM_jobs_customdata_get(wm_job);
if (!pj) {
@@ -152,8 +152,6 @@ void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
WM_jobs_callbacks(wm_job, preview_startjob, NULL, NULL, preview_endjob);
}
- /* attempt to lock mutex of job here */
-
audiojob->bmain = CTX_data_main(C);
audiojob->sound = seq->sound;
@@ -167,5 +165,5 @@ void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index c55d77800ff..243a6e193eb 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -23,12 +23,12 @@
#include <math.h>
#include <string.h>
-#include "BLI_utildefines.h"
#include "BLI_task.h"
+#include "BLI_utildefines.h"
#include "IMB_colormanagement.h"
-#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "atomic_ops.h"
@@ -42,7 +42,7 @@ static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3])
yuv[1] = 0.492f * (rgb[2] - yuv[0]);
yuv[2] = 0.877f * (rgb[0] - yuv[0]);
- /* Normalize */
+ /* Normalize. */
yuv[1] *= 255.0f / (122 * 2.0f);
yuv[1] += 0.5f;
@@ -50,24 +50,24 @@ static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3])
yuv[2] += 0.5f;
}
-static void scope_put_pixel(unsigned char *table, unsigned char *pos)
+static void scope_put_pixel(uchar *table, uchar *pos)
{
- unsigned char newval = table[*pos];
+ uchar newval = table[*pos];
pos[0] = pos[1] = pos[2] = newval;
pos[3] = 255;
}
-static void scope_put_pixel_single(unsigned char *table, unsigned char *pos, int col)
+static void scope_put_pixel_single(uchar *table, uchar *pos, int col)
{
char newval = table[pos[col]];
pos[col] = newval;
pos[3] = 255;
}
-static void wform_put_line(int w, unsigned char *last_pos, unsigned char *new_pos)
+static void wform_put_line(int w, uchar *last_pos, uchar *new_pos)
{
if (last_pos > new_pos) {
- unsigned char *temp = new_pos;
+ uchar *temp = new_pos;
new_pos = last_pos;
last_pos = temp;
}
@@ -81,10 +81,10 @@ static void wform_put_line(int w, unsigned char *last_pos, unsigned char *new_po
}
}
-static void wform_put_line_single(int w, unsigned char *last_pos, unsigned char *new_pos, int col)
+static void wform_put_line_single(int w, uchar *last_pos, uchar *new_pos, int col)
{
if (last_pos > new_pos) {
- unsigned char *temp = new_pos;
+ uchar *temp = new_pos;
new_pos = last_pos;
last_pos = temp;
}
@@ -98,12 +98,12 @@ static void wform_put_line_single(int w, unsigned char *last_pos, unsigned char
}
}
-static void wform_put_border(unsigned char *tgt, int w, int h)
+static void wform_put_border(uchar *tgt, int w, int h)
{
int x, y;
for (x = 0; x < w; x++) {
- unsigned char *p = tgt + 4 * x;
+ uchar *p = tgt + 4 * x;
p[1] = p[3] = 155;
p[4 * w + 1] = p[4 * w + 3] = 155;
p = tgt + 4 * (w * (h - 1) + x);
@@ -112,7 +112,7 @@ static void wform_put_border(unsigned char *tgt, int w, int h)
}
for (y = 0; y < h; y++) {
- unsigned char *p = tgt + 4 * w * y;
+ uchar *p = tgt + 4 * w * y;
p[1] = p[3] = 155;
p[4 + 1] = p[4 + 3] = 155;
p = tgt + 4 * (w * y + w - 1);
@@ -121,7 +121,7 @@ static void wform_put_border(unsigned char *tgt, int w, int h)
}
}
-static void wform_put_gridrow(unsigned char *tgt, float perc, int w, int h)
+static void wform_put_gridrow(uchar *tgt, float perc, int w, int h)
{
int i;
@@ -134,7 +134,7 @@ static void wform_put_gridrow(unsigned char *tgt, float perc, int w, int h)
}
}
-static void wform_put_grid(unsigned char *tgt, int w, int h)
+static void wform_put_grid(uchar *tgt, int w, int h)
{
wform_put_gridrow(tgt, 90.0, w, h);
wform_put_gridrow(tgt, 70.0, w, h);
@@ -145,27 +145,27 @@ static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- const unsigned char *src = (unsigned char *)ibuf->rect;
- unsigned char *tgt = (unsigned char *)rval->rect;
+ const uchar *src = (uchar *)ibuf->rect;
+ uchar *tgt = (uchar *)rval->rect;
int w = ibuf->x + 3;
int h = 515;
float waveform_gamma = 0.2;
- unsigned char wtable[256];
+ uchar wtable[256];
wform_put_grid(tgt, w, h);
wform_put_border(tgt, w, h);
for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
+ wtable[x] = (uchar)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
}
for (y = 0; y < ibuf->y; y++) {
- unsigned char *last_p = NULL;
+ uchar *last_p = NULL;
for (x = 0; x < ibuf->x; x++) {
- const unsigned char *rgb = src + 4 * (ibuf->x * y + x);
+ const uchar *rgb = src + 4 * (ibuf->x * y + x);
float v = (float)IMB_colormanagement_get_luminance_byte(rgb) / 255.0f;
- unsigned char *p = tgt;
+ uchar *p = tgt;
p += 4 * (w * ((int)(v * (h - 3)) + 1) + x + 1);
scope_put_pixel(wtable, p);
@@ -187,25 +187,25 @@ static ImBuf *make_waveform_view_from_ibuf_float(ImBuf *ibuf)
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
const float *src = ibuf->rect_float;
- unsigned char *tgt = (unsigned char *)rval->rect;
+ uchar *tgt = (uchar *)rval->rect;
int w = ibuf->x + 3;
int h = 515;
float waveform_gamma = 0.2;
- unsigned char wtable[256];
+ uchar wtable[256];
wform_put_grid(tgt, w, h);
for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
+ wtable[x] = (uchar)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
}
for (y = 0; y < ibuf->y; y++) {
- unsigned char *last_p = NULL;
+ uchar *last_p = NULL;
for (x = 0; x < ibuf->x; x++) {
const float *rgb = src + 4 * (ibuf->x * y + x);
float v = IMB_colormanagement_get_luminance(rgb);
- unsigned char *p = tgt;
+ uchar *p = tgt;
CLAMP(v, 0.0f, 1.0f);
@@ -241,28 +241,28 @@ static ImBuf *make_sep_waveform_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
- const unsigned char *src = (const unsigned char *)ibuf->rect;
- unsigned char *tgt = (unsigned char *)rval->rect;
+ const uchar *src = (const uchar *)ibuf->rect;
+ uchar *tgt = (uchar *)rval->rect;
int w = ibuf->x + 3;
int sw = ibuf->x / 3;
int h = 515;
float waveform_gamma = 0.2;
- unsigned char wtable[256];
+ uchar wtable[256];
wform_put_grid(tgt, w, h);
for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
+ wtable[x] = (uchar)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
}
for (y = 0; y < ibuf->y; y++) {
- unsigned char *last_p[3] = {NULL, NULL, NULL};
+ uchar *last_p[3] = {NULL, NULL, NULL};
for (x = 0; x < ibuf->x; x++) {
int c;
- const unsigned char *rgb = src + 4 * (ibuf->x * y + x);
+ const uchar *rgb = src + 4 * (ibuf->x * y + x);
for (c = 0; c < 3; c++) {
- unsigned char *p = tgt;
+ uchar *p = tgt;
p += 4 * (w * ((rgb[c] * (h - 3)) / 255 + 1) + c * sw + x / 3 + 1);
scope_put_pixel_single(wtable, p, c);
@@ -287,27 +287,27 @@ static ImBuf *make_sep_waveform_view_from_ibuf_float(ImBuf *ibuf)
ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
int x, y;
const float *src = ibuf->rect_float;
- unsigned char *tgt = (unsigned char *)rval->rect;
+ uchar *tgt = (uchar *)rval->rect;
int w = ibuf->x + 3;
int sw = ibuf->x / 3;
int h = 515;
float waveform_gamma = 0.2;
- unsigned char wtable[256];
+ uchar wtable[256];
wform_put_grid(tgt, w, h);
for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
+ wtable[x] = (uchar)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
}
for (y = 0; y < ibuf->y; y++) {
- unsigned char *last_p[3] = {NULL, NULL, NULL};
+ uchar *last_p[3] = {NULL, NULL, NULL};
for (x = 0; x < ibuf->x; x++) {
int c;
const float *rgb = src + 4 * (ibuf->x * y + x);
for (c = 0; c < 3; c++) {
- unsigned char *p = tgt;
+ uchar *p = tgt;
float v = rgb[c];
CLAMP(v, 0.0f, 1.0f);
@@ -343,18 +343,18 @@ ImBuf *make_sep_waveform_view_from_ibuf(ImBuf *ibuf)
static void draw_zebra_byte(ImBuf *src, ImBuf *ibuf, float perc)
{
- unsigned int limit = 255.0f * perc / 100.0f;
- unsigned char *p = (unsigned char *)src->rect;
- unsigned char *o = (unsigned char *)ibuf->rect;
+ uint limit = 255.0f * perc / 100.0f;
+ uchar *p = (uchar *)src->rect;
+ uchar *o = (uchar *)ibuf->rect;
int x;
int y;
for (y = 0; y < ibuf->y; y++) {
for (x = 0; x < ibuf->x; x++) {
- unsigned char r = *p++;
- unsigned char g = *p++;
- unsigned char b = *p++;
- unsigned char a = *p++;
+ uchar r = *p++;
+ uchar g = *p++;
+ uchar b = *p++;
+ uchar a = *p++;
if (r >= limit || g >= limit || b >= limit) {
if (((x + y) & 0x08) != 0) {
@@ -375,7 +375,7 @@ static void draw_zebra_float(ImBuf *src, ImBuf *ibuf, float perc)
{
float limit = perc / 100.0f;
const float *p = src->rect_float;
- unsigned char *o = (unsigned char *)ibuf->rect;
+ uchar *o = (uchar *)ibuf->rect;
int x;
int y;
@@ -417,7 +417,7 @@ ImBuf *make_zebra_view_from_ibuf(ImBuf *src, float perc)
static void draw_histogram_marker(ImBuf *ibuf, int x)
{
- unsigned char *p = (unsigned char *)ibuf->rect;
+ uchar *p = (uchar *)ibuf->rect;
int barh = ibuf->y * 0.1;
int i;
@@ -431,7 +431,7 @@ static void draw_histogram_marker(ImBuf *ibuf, int x)
static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col)
{
- unsigned char *p = (unsigned char *)ibuf->rect;
+ uchar *p = (uchar *)ibuf->rect;
int barh = ibuf->y * val * 0.9f;
int i;
@@ -447,21 +447,20 @@ static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col)
typedef struct MakeHistogramViewData {
const ImBuf *ibuf;
- uint32_t (*bins)[HIS_STEPS];
} MakeHistogramViewData;
-static void make_histogram_view_from_ibuf_byte_cb_ex(void *__restrict userdata,
- const int y,
- const TaskParallelTLS *__restrict tls)
+static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata,
+ const int y,
+ const TaskParallelTLS *__restrict tls)
{
MakeHistogramViewData *data = userdata;
const ImBuf *ibuf = data->ibuf;
- const unsigned char *src = (unsigned char *)ibuf->rect;
+ const uchar *src = (uchar *)ibuf->rect;
uint32_t(*cur_bins)[HIS_STEPS] = tls->userdata_chunk;
for (int x = 0; x < ibuf->x; x++) {
- const unsigned char *pixel = src + (y * ibuf->x + x) * 4;
+ const uchar *pixel = src + (y * ibuf->x + x) * 4;
for (int j = 3; j--;) {
cur_bins[j][pixel[j]]++;
@@ -469,17 +468,16 @@ static void make_histogram_view_from_ibuf_byte_cb_ex(void *__restrict userdata,
}
}
-static void make_histogram_view_from_ibuf_finalize(void *__restrict userdata,
- void *__restrict userdata_chunk)
+static void make_histogram_view_from_ibuf_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- MakeHistogramViewData *data = userdata;
- uint32_t(*bins)[HIS_STEPS] = data->bins;
-
- uint32_t(*cur_bins)[HIS_STEPS] = userdata_chunk;
+ uint32_t(*join_bins)[HIS_STEPS] = chunk_join;
+ uint32_t(*bins)[HIS_STEPS] = chunk;
for (int j = 3; j--;) {
for (int i = 0; i < HIS_STEPS; i++) {
- bins[j][i] += cur_bins[j][i];
+ join_bins[j][i] += bins[j][i];
}
}
}
@@ -488,23 +486,22 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
int x;
- unsigned int nr, ng, nb;
+ uint nr, ng, nb;
- unsigned int bins[3][HIS_STEPS];
+ uint bins[3][HIS_STEPS];
memset(bins, 0, sizeof(bins));
MakeHistogramViewData data = {
.ibuf = ibuf,
- .bins = bins,
};
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (ibuf->y >= 256);
settings.userdata_chunk = bins;
settings.userdata_chunk_size = sizeof(bins);
- settings.func_finalize = make_histogram_view_from_ibuf_finalize;
- BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_byte_cb_ex, &settings);
+ settings.func_reduce = make_histogram_view_from_ibuf_reduce;
+ BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_byte_fn, &settings);
nr = nb = ng = 0;
for (x = 0; x < HIS_STEPS; x++) {
@@ -534,7 +531,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
}
}
- wform_put_border((unsigned char *)rval->rect, rval->x, rval->y);
+ wform_put_border((uchar *)rval->rect, rval->x, rval->y);
return rval;
}
@@ -551,9 +548,9 @@ BLI_INLINE int get_bin_float(float f)
return (int)(((f + 0.25f) / 1.5f) * 512);
}
-static void make_histogram_view_from_ibuf_float_cb_ex(void *__restrict userdata,
- const int y,
- const TaskParallelTLS *__restrict tls)
+static void make_histogram_view_from_ibuf_float_fn(void *__restrict userdata,
+ const int y,
+ const TaskParallelTLS *__restrict tls)
{
const MakeHistogramViewData *data = userdata;
const ImBuf *ibuf = data->ibuf;
@@ -576,21 +573,20 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
int nr, ng, nb;
int x;
- unsigned int bins[3][HIS_STEPS];
+ uint bins[3][HIS_STEPS];
memset(bins, 0, sizeof(bins));
MakeHistogramViewData data = {
.ibuf = ibuf,
- .bins = bins,
};
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (ibuf->y >= 256);
settings.userdata_chunk = bins;
settings.userdata_chunk_size = sizeof(bins);
- settings.func_finalize = make_histogram_view_from_ibuf_finalize;
- BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_float_cb_ex, &settings);
+ settings.func_reduce = make_histogram_view_from_ibuf_reduce;
+ BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_float_fn, &settings);
nr = nb = ng = 0;
for (x = 0; x < HIS_STEPS; x++) {
@@ -619,7 +615,7 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
draw_histogram_marker(rval, get_bin_float(0.0));
draw_histogram_marker(rval, get_bin_float(1.0));
- wform_put_border((unsigned char *)rval->rect, rval->x, rval->y);
+ wform_put_border((uchar *)rval->rect, rval->x, rval->y);
return rval;
}
@@ -636,8 +632,7 @@ ImBuf *make_histogram_view_from_ibuf(ImBuf *ibuf)
}
}
-static void vectorscope_put_cross(
- unsigned char r, unsigned char g, unsigned char b, char *tgt, int w, int h, int size)
+static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, int h, int size)
{
float rgb[3], yuv[3];
char *p;
@@ -676,10 +671,10 @@ static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
int w = 515;
int h = 515;
float scope_gamma = 0.2;
- unsigned char wtable[256];
+ uchar wtable[256];
for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char)(pow(((float)x + 1) / 256, scope_gamma) * 255);
+ wtable[x] = (uchar)(pow(((float)x + 1) / 256, scope_gamma) * 255);
}
for (x = 0; x < 256; x++) {
@@ -702,7 +697,7 @@ static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
rgb_to_yuv_normalized(rgb, yuv);
p = tgt + 4 * (w * (int)((yuv[2] * (h - 3) + 1)) + (int)((yuv[1] * (w - 3) + 1)));
- scope_put_pixel(wtable, (unsigned char *)p);
+ scope_put_pixel(wtable, (uchar *)p);
}
}
@@ -721,10 +716,10 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
int w = 515;
int h = 515;
float scope_gamma = 0.2;
- unsigned char wtable[256];
+ uchar wtable[256];
for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char)(pow(((float)x + 1) / 256, scope_gamma) * 255);
+ wtable[x] = (uchar)(pow(((float)x + 1) / 256, scope_gamma) * 255);
}
for (x = 0; x <= 255; x++) {
@@ -743,14 +738,12 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
memcpy(rgb, src1, 3 * sizeof(float));
- CLAMP(rgb[0], 0.0f, 1.0f);
- CLAMP(rgb[1], 0.0f, 1.0f);
- CLAMP(rgb[2], 0.0f, 1.0f);
+ clamp_v3(rgb, 0.0f, 1.0f);
rgb_to_yuv_normalized(rgb, yuv);
p = tgt + 4 * (w * (int)((yuv[2] * (h - 3) + 1)) + (int)((yuv[1] * (w - 3) + 1)));
- scope_put_pixel(wtable, (unsigned char *)p);
+ scope_put_pixel(wtable, (uchar *)p);
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index a5bb66ca65f..c5472ed88e5 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -21,13 +21,13 @@
* \ingroup spseq
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include <string.h>
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "DNA_scene_types.h"
@@ -40,16 +40,16 @@
#include "RNA_define.h"
-/* for menu/popup icons etc etc*/
+/* For menu, popup, icons, etc. */
#include "ED_outliner.h"
#include "ED_screen.h"
-#include "ED_sequencer.h"
#include "ED_select_utils.h"
+#include "ED_sequencer.h"
#include "UI_view2d.h"
-/* own include */
+/* Own include. */
#include "sequencer_intern.h"
static void *find_nearest_marker(int UNUSED(d1), int UNUSED(d2))
@@ -147,7 +147,7 @@ static void select_active_side_range(ListBase *seqbase,
}
}
-/* used for mouse selection in SEQUENCER_OT_select */
+/* Used for mouse selection in SEQUENCER_OT_select */
static void select_linked_time(ListBase *seqbase, Sequence *seq_link)
{
Sequence *seq;
@@ -158,7 +158,7 @@ static void select_linked_time(ListBase *seqbase, Sequence *seq_link)
int right_match = (seq->enddisp == seq_link->enddisp) ? 1 : 0;
if (left_match && right_match) {
- /* a direct match, copy the selection settinhs */
+ /* Direct match, copy the selection settings. */
seq->flag &= ~(SELECT | SEQ_LEFTSEL | SEQ_RIGHTSEL);
seq->flag |= seq_link->flag & (SELECT | SEQ_LEFTSEL | SEQ_RIGHTSEL);
@@ -166,7 +166,7 @@ static void select_linked_time(ListBase *seqbase, Sequence *seq_link)
}
else if (seq_link->flag & SELECT && (left_match || right_match)) {
- /* clear for reselection */
+ /* Clear for reselection. */
seq->flag &= ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
if (left_match && seq_link->flag & SEQ_LEFTSEL) {
@@ -248,12 +248,11 @@ static void select_neighbor_from_last(Scene *scene, int lr)
}
}
if (changed) {
- /* pass */
+ /* Pass. */
}
}
#endif
-/* (de)select operator */
static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
{
int action = RNA_enum_get(op->ptr, "action");
@@ -302,22 +301,21 @@ static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_select_all(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "(De)select All";
ot->idname = "SEQUENCER_OT_select_all";
ot->description = "Select or deselect all strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_de_select_all_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_UNDO;
WM_operator_properties_select_all(ot);
}
-/* (de)select operator */
static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -343,16 +341,16 @@ static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Select Inverse";
ot->idname = "SEQUENCER_OT_select_inverse";
ot->description = "Select unselected strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_select_inverse_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_UNDO;
}
@@ -385,18 +383,18 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
wait_to_deselect_others = false;
}
- marker = find_nearest_marker(SCE_MARKERS, 1); // XXX - dummy function for now
+ marker = find_nearest_marker(SCE_MARKERS, 1); /* XXX - dummy function for now */
seq = find_nearest_seq(scene, v2d, &hand, mval);
- // XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip
+ /* XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip */
if (seq && linked_time && (left_right == SEQ_SELECT_LR_MOUSE)) {
left_right = SEQ_SELECT_LR_NONE;
}
if (marker) {
int oldflag;
- /* select timeline marker */
+ /* Select timeline marker. */
if (extend) {
oldflag = marker->flag;
if (oldflag & SELECT) {
@@ -415,7 +413,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
ret_value = OPERATOR_FINISHED;
}
else if (left_right != SEQ_SELECT_LR_NONE) {
- /* use different logic for this */
+ /* Use different logic for this. */
float x;
if (extend == false) {
ED_sequencer_deselect_all(scene);
@@ -494,7 +492,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
}
}
- /* On Alt selection, select the strip and bordering handles */
+ /* On Alt selection, select the strip and bordering handles. */
if (linked_handle) {
if (!ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT)) {
/* First click selects the strip and its adjacent handles (if valid).
@@ -510,7 +508,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
select_surrounding_handles(scene, seq);
}
else {
- /* always select the strip under the cursor */
+ /* Always select the strip under the cursor. */
seq->flag |= SELECT;
/* First click selects adjacent handles on that side.
@@ -635,21 +633,21 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
};
PropertyRNA *prop;
- /* identifiers */
+ /* Identifiers. */
ot->name = "Select";
ot->idname = "SEQUENCER_OT_select";
ot->description = "Select a strip (last selected becomes the \"active strip\")";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_select_exec;
ot->invoke = WM_generic_select_invoke;
ot->modal = WM_generic_select_modal;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_UNDO;
- /* properties */
+ /* Properties. */
WM_operator_properties_generic_select(ot);
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
prop = RNA_def_boolean(ot->srna,
@@ -660,7 +658,7 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_boolean(
ot->srna, "linked_handle", 0, "Linked Handle", "Select handles next to the active strip");
- /* for animation this is an enum but atm having an enum isn't useful for us */
+ /* For animation this is enum but atm having an enum isn't useful for us. */
RNA_def_enum(ot->srna,
"left_right",
sequencer_select_left_right_types,
@@ -671,7 +669,7 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
ot->srna, "linked_time", 0, "Linked Time", "Select other strips at the same time");
}
-/* run recursively to select linked */
+/* Run recursively to select linked. */
static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool linked)
{
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -693,7 +691,7 @@ static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool li
}
if (!linked) {
- /* if not linked we only want to touch each seq once, newseq */
+ /* If not linked we only want to touch each seq once, newseq. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
seq->tmp = NULL;
}
@@ -702,7 +700,7 @@ static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool li
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if ((seq->flag & SELECT) == sel) {
if (linked || (seq->tmp == NULL)) {
- /* only get unselected neighbors */
+ /* Only get unselected neighbors. */
neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
if (neighbor) {
if (sel) {
@@ -738,7 +736,6 @@ static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool li
return changed;
}
-/* select more operator */
static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -756,22 +753,19 @@ static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Select More";
ot->idname = "SEQUENCER_OT_select_more";
ot->description = "Select more strips adjacent to the current selection";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_select_more_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
}
-/* select less operator */
static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -789,22 +783,19 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Select Less";
ot->idname = "SEQUENCER_OT_select_less";
ot->description = "Shrink the current selection of adjacent selected strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_select_less_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
}
-/* select pick linked operator (uses the mouse) */
static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
@@ -815,10 +806,10 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, cons
Sequence *mouse_seq;
int selected, hand;
- /* this works like UV, not mesh */
+ /* This works like UV, not mesh. */
mouse_seq = find_nearest_seq(scene, v2d, &hand, event->mval);
if (!mouse_seq) {
- return OPERATOR_FINISHED; /* user error as with mesh?? */
+ return OPERATOR_FINISHED; /* User error as with mesh?? */
}
if (extend == 0) {
@@ -842,23 +833,22 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, cons
void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Select Pick Linked";
ot->idname = "SEQUENCER_OT_select_linked_pick";
ot->description = "Select a chain of linked strips nearest to the mouse pointer";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_select_linked_pick_invoke;
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* Properties. */
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
}
-/* select linked operator */
static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -878,22 +868,19 @@ static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Select Linked";
ot->idname = "SEQUENCER_OT_select_linked";
ot->description = "Select all strips adjacent to the current selection";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_select_linked_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
}
-/* select handles operator */
static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -928,19 +915,19 @@ static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_select_handles(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Select Handles";
ot->idname = "SEQUENCER_OT_select_handles";
ot->description = "Select gizmo handles on the sides of the selected strip";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_select_handles_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* Properties. */
RNA_def_enum(ot->srna,
"side",
prop_side_types,
@@ -949,7 +936,6 @@ void SEQUENCER_OT_select_handles(wmOperatorType *ot)
"The side of the handle that is selected");
}
-/* select side operator */
static int sequencer_select_side_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -962,7 +948,7 @@ static int sequencer_select_side_exec(bContext *C, wmOperator *op)
copy_vn_i(frame_ranges, ARRAY_SIZE(frame_ranges), frame_init);
- for (Sequence *seq = ed->seqbasep->first; seq; seq = seq->next) {
+ LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
if (UNLIKELY(seq->machine >= MAXSEQ)) {
continue;
}
@@ -993,19 +979,19 @@ static int sequencer_select_side_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_select_side(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Select Side";
ot->idname = "SEQUENCER_OT_select_side";
ot->description = "Select strips on the nominated side of the selected strips";
- /* api callbacks */
+ /* Api callbacks. */
ot->exec = sequencer_select_side_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* Properties. */
RNA_def_enum(ot->srna,
"side",
prop_side_types,
@@ -1014,19 +1000,20 @@ void SEQUENCER_OT_select_side(wmOperatorType *ot)
"The side to which the selection is applied");
}
-/* box_select operator */
static int sequencer_box_select_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ View2D *v2d = UI_view2d_fromcontext(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
+
if (ed == NULL) {
return OPERATOR_CANCELLED;
}
- View2D *v2d = UI_view2d_fromcontext(C);
-
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ const bool handles = RNA_boolean_get(op->ptr, "include_handles");
const bool select = (sel_op != SEL_OP_SUB);
+
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
ED_sequencer_deselect_all(scene);
}
@@ -1035,12 +1022,48 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op)
WM_operator_properties_border_to_rctf(op, &rectf);
UI_view2d_region_to_view_rctf(v2d, &rectf, &rectf);
- for (Sequence *seq = ed->seqbasep->first; seq; seq = seq->next) {
+ LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
rctf rq;
seq_rectf(seq, &rq);
if (BLI_rctf_isect(&rq, &rectf, NULL)) {
- SET_FLAG_FROM_TEST(seq->flag, select, SELECT);
- recurs_sel_seq(seq);
+ if (handles) {
+ /* Get the handles draw size. */
+ float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
+ float handsize = sequence_handle_size_get_clamped(seq, pixelx);
+
+ /* Right handle. */
+ if (rectf.xmax > (seq->enddisp - handsize)) {
+ if (select) {
+ seq->flag |= SELECT | SEQ_RIGHTSEL;
+ }
+ else {
+ /* Deselect the strip if it's left with no handles selected. */
+ if ((seq->flag & SEQ_RIGHTSEL) && ((seq->flag & SEQ_LEFTSEL) == 0)) {
+ seq->flag &= ~SELECT;
+ }
+ seq->flag &= ~SEQ_RIGHTSEL;
+ }
+ }
+ /* Left handle. */
+ if (rectf.xmin < (seq->startdisp + handsize)) {
+ if (select) {
+ seq->flag |= SELECT | SEQ_LEFTSEL;
+ }
+ else {
+ /* Deselect the strip if it's left with no handles selected. */
+ if ((seq->flag & SEQ_LEFTSEL) && ((seq->flag & SEQ_RIGHTSEL) == 0)) {
+ seq->flag &= ~SELECT;
+ }
+ seq->flag &= ~SEQ_LEFTSEL;
+ }
+ }
+ }
+
+ /* Regular box selection. */
+ else {
+ SET_FLAG_FROM_TEST(seq->flag, select, SELECT);
+ seq->flag &= ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ }
}
}
@@ -1051,7 +1074,6 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* ****** Box Select ****** */
static int sequencer_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
@@ -1072,12 +1094,14 @@ static int sequencer_box_select_invoke(bContext *C, wmOperator *op, const wmEven
void SEQUENCER_OT_select_box(wmOperatorType *ot)
{
- /* identifiers */
+ PropertyRNA *prop;
+
+ /* Identifiers. */
ot->name = "Box Select";
ot->idname = "SEQUENCER_OT_select_box";
ot->description = "Select strips using box selection";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = sequencer_box_select_invoke;
ot->exec = sequencer_box_select_exec;
ot->modal = WM_gesture_box_modal;
@@ -1085,20 +1109,21 @@ void SEQUENCER_OT_select_box(wmOperatorType *ot)
ot->poll = ED_operator_sequencer_active;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_UNDO;
- /* properties */
+ /* Properties. */
WM_operator_properties_gesture_box(ot);
WM_operator_properties_select_operation_simple(ot);
- PropertyRNA *prop = RNA_def_boolean(
+ prop = RNA_def_boolean(
ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a tweak event");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "include_handles", 0, "Select Handles", "Select the strips and their handles");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ****** Selected Grouped ****** */
-
enum {
SEQ_SELECT_GROUP_TYPE,
SEQ_SELECT_GROUP_TYPE_BASIC,
@@ -1323,7 +1348,7 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int
BKE_sequence_iterator_next(&iter)) {
seq = iter.seq;
- /* Ignore all seqs already selected! */
+ /* Ignore all seqs already selected. */
/* Ignore all seqs not sharing some time with active one. */
/* Ignore all seqs of incompatible types (audio vs video). */
if (!SEQ_CHANNEL_CHECK(seq, channel) || (seq->flag & SELECT) || (seq->startdisp >= enddisp) ||
@@ -1332,7 +1357,7 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int
continue;
}
- /* If the seq is an effect one, we need extra checking! */
+ /* If the seq is an effect one, we need extra checking. */
if (SEQ_IS_EFFECT(seq) && ((seq->seq1 && seq->seq1->tmp) || (seq->seq2 && seq->seq2->tmp) ||
(seq->seq3 && seq->seq3->tmp))) {
if (startdisp > seq->startdisp) {
@@ -1355,7 +1380,7 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int
BKE_sequence_iterator_begin(ed, &iter, true);
}
- /* Video strips below active one, or any strip for audio (order do no matters here!). */
+ /* Video strips below active one, or any strip for audio (order doesn't matter here). */
else if (seq->machine < machine || is_audio) {
seq->flag |= SELECT;
changed = true;
@@ -1376,17 +1401,17 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq, *actseq = BKE_sequencer_active_get(scene);
+ if (actseq == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active sequence!");
+ return OPERATOR_CANCELLED;
+ }
+
const int type = RNA_enum_get(op->ptr, "type");
const int channel = RNA_boolean_get(op->ptr, "use_active_channel") ? actseq->machine : 0;
const bool extend = RNA_boolean_get(op->ptr, "extend");
bool changed = false;
- if (actseq == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active sequence!");
- return OPERATOR_CANCELLED;
- }
-
if (!extend) {
SEQP_BEGIN (ed, seq) {
seq->flag &= ~SELECT;
@@ -1433,20 +1458,20 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_select_grouped(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Select Grouped";
ot->description = "Select all strips grouped by various properties";
ot->idname = "SEQUENCER_OT_select_grouped";
- /* api callbacks */
+ /* Api callbacks. */
ot->invoke = WM_menu_invoke;
ot->exec = sequencer_select_grouped_exec;
ot->poll = sequencer_edit_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* Properties. */
ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_select_grouped_types, 0, "Type", "");
RNA_def_boolean(ot->srna,
"extend",
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index 534d02c7bf3..d397c255b03 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -21,232 +21,35 @@
* \ingroup spseq
*/
-#include "MEM_guardedalloc.h"
+#include "ED_util_imbuf.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
+#include "RNA_define.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_context.h"
-#include "BKE_main.h"
-#include "BKE_sequencer.h"
-#include "BKE_screen.h"
-
-#include "WM_api.h"
#include "WM_types.h"
-#include "ED_image.h"
-#include "ED_screen.h"
-#include "ED_space_api.h"
-
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_colormanagement.h"
-
-#include "UI_view2d.h"
-
-/* own include */
+/* Own include. */
#include "sequencer_intern.h"
/******************** sample backdrop operator ********************/
-
-typedef struct ImageSampleInfo {
- ARegionType *art;
- void *draw_handle;
- int x, y;
- int channels;
-
- unsigned char col[4];
- float colf[4];
- float linearcol[4];
-
- unsigned char *colp;
- const float *colfp;
-
- int draw;
- int color_manage;
-} ImageSampleInfo;
-
-static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
-{
- Scene *scene = CTX_data_scene(C);
- ImageSampleInfo *info = arg_info;
-
- if (info->draw) {
- ED_image_draw_info(scene,
- ar,
- info->color_manage,
- false,
- info->channels,
- info->x,
- info->y,
- info->colp,
- info->colfp,
- info->linearcol,
- NULL,
- NULL);
- }
-}
-
-static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Main *bmain = CTX_data_main(C);
- struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
- ARegion *ar = CTX_wm_region(C);
- ImBuf *ibuf = sequencer_ibuf_get(bmain, depsgraph, scene, sseq, CFRA, 0, NULL);
- ImageSampleInfo *info = op->customdata;
- float fx, fy;
-
- if (ibuf == NULL) {
- IMB_freeImBuf(ibuf);
- info->draw = 0;
- return;
- }
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy);
-
- fx /= scene->r.xasp / scene->r.yasp;
-
- fx += (float)scene->r.xsch / 2.0f;
- fy += (float)scene->r.ysch / 2.0f;
- fx *= (float)ibuf->x / (float)scene->r.xsch;
- fy *= (float)ibuf->y / (float)scene->r.ysch;
-
- if (fx >= 0.0f && fy >= 0.0f && fx < ibuf->x && fy < ibuf->y) {
- const float *fp;
- unsigned char *cp;
- int x = (int)fx, y = (int)fy;
-
- info->x = x;
- info->y = y;
- info->draw = 1;
- info->channels = ibuf->channels;
-
- info->colp = NULL;
- info->colfp = NULL;
-
- if (ibuf->rect) {
- cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
-
- info->col[0] = cp[0];
- info->col[1] = cp[1];
- info->col[2] = cp[2];
- info->col[3] = cp[3];
- info->colp = info->col;
-
- info->colf[0] = (float)cp[0] / 255.0f;
- info->colf[1] = (float)cp[1] / 255.0f;
- info->colf[2] = (float)cp[2] / 255.0f;
- info->colf[3] = (float)cp[3] / 255.0f;
- info->colfp = info->colf;
-
- copy_v4_v4(info->linearcol, info->colf);
- IMB_colormanagement_colorspace_to_scene_linear_v4(
- info->linearcol, false, ibuf->rect_colorspace);
-
- info->color_manage = true;
- }
- if (ibuf->rect_float) {
- fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
-
- info->colf[0] = fp[0];
- info->colf[1] = fp[1];
- info->colf[2] = fp[2];
- info->colf[3] = fp[3];
- info->colfp = info->colf;
-
- /* sequencer's image buffers are in non-linear space, need to make them linear */
- copy_v4_v4(info->linearcol, info->colf);
- BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->linearcol);
-
- info->color_manage = true;
- }
- }
- else {
- info->draw = 0;
- }
-
- IMB_freeImBuf(ibuf);
- ED_area_tag_redraw(CTX_wm_area(C));
-}
-
-static void sample_exit(bContext *C, wmOperator *op)
-{
- ImageSampleInfo *info = op->customdata;
-
- ED_region_draw_cb_exit(info->art, info->draw_handle);
- ED_area_tag_redraw(CTX_wm_area(C));
- MEM_freeN(info);
-}
-
-static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceSeq *sseq = CTX_wm_space_seq(C);
- ImageSampleInfo *info;
-
- if (sseq->mainb != SEQ_DRAW_IMG_IMBUF) {
- return OPERATOR_CANCELLED;
- }
-
- info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
- info->art = ar->type;
- info->draw_handle = ED_region_draw_cb_activate(
- ar->type, sample_draw, info, REGION_DRAW_POST_PIXEL);
- op->customdata = info;
-
- sample_apply(C, op, event);
-
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- switch (event->type) {
- case LEFTMOUSE:
- case RIGHTMOUSE: /* XXX hardcoded */
- if (event->val == KM_RELEASE) {
- sample_exit(C, op);
- return OPERATOR_CANCELLED;
- }
- break;
- case MOUSEMOVE:
- sample_apply(C, op, event);
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void sample_cancel(bContext *C, wmOperator *op)
-{
- sample_exit(C, op);
-}
-
-static bool sample_poll(bContext *C)
-{
- SpaceSeq *sseq = CTX_wm_space_seq(C);
- return sseq && BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL;
-}
-
void SEQUENCER_OT_sample(wmOperatorType *ot)
{
- /* identifiers */
+ /* Identifiers. */
ot->name = "Sample Color";
ot->idname = "SEQUENCER_OT_sample";
ot->description = "Use mouse to sample color in current frame";
- /* api callbacks */
- ot->invoke = sample_invoke;
- ot->modal = sample_modal;
- ot->cancel = sample_cancel;
- ot->poll = sample_poll;
+ /* Api callbacks. */
+ ot->invoke = ED_imbuf_sample_invoke;
+ ot->modal = ED_imbuf_sample_modal;
+ ot->cancel = ED_imbuf_sample_cancel;
+ ot->poll = ED_imbuf_sample_poll;
- /* flags */
+ /* Flags. */
ot->flag = OPTYPE_BLOCKING;
+
+ /* Not implemented. */
+ PropertyRNA *prop;
+ prop = RNA_def_int(ot->srna, "size", 1, 1, 128, "Sample Size", "", 1, 64);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 53202b65838..f52cfdd34c0 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -21,12 +21,12 @@
* \ingroup spseq
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "DNA_gpencil_types.h"
-#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
+#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
@@ -35,17 +35,19 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
+#include "BKE_sequencer_offscreen.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
-#include "ED_view3d.h" /* only for sequencer view3d drawing callback */
+#include "ED_space_api.h"
+#include "ED_view3d.h"
+#include "ED_view3d_offscreen.h" /* Only for sequencer view3d drawing callback. */
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "RNA_access.h"
@@ -55,37 +57,38 @@
#include "IMB_imbuf.h"
-#include "sequencer_intern.h" // own include
+/* Own include. */
+#include "sequencer_intern.h"
/**************************** common state *****************************/
-static void sequencer_scopes_tag_refresh(ScrArea *sa)
+static void sequencer_scopes_tag_refresh(ScrArea *area)
{
- SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
+ SpaceSeq *sseq = (SpaceSeq *)area->spacedata.first;
sseq->scopes.reference_ibuf = NULL;
}
/* ******************** manage regions ********************* */
-static ARegion *sequencer_find_region(ScrArea *sa, short type)
+static ARegion *sequencer_find_region(ScrArea *area, short type)
{
- ARegion *ar = NULL;
+ ARegion *region = NULL;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == type) {
- return ar;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == type) {
+ return region;
}
}
- return ar;
+ return region;
}
/* ******************** default callbacks for sequencer space ***************** */
-static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene)
+static SpaceLink *sequencer_new(const ScrArea *UNUSED(area), const Scene *scene)
{
- ARegion *ar;
+ ARegion *region;
SpaceSeq *sseq;
sseq = MEM_callocN(sizeof(SpaceSeq), "initsequencer");
@@ -93,102 +96,101 @@ static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene)
sseq->chanshown = 0;
sseq->view = SEQ_VIEW_SEQUENCE;
sseq->mainb = SEQ_DRAW_IMG_IMBUF;
- sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKERS;
-
- /* tool header */
- ar = MEM_callocN(sizeof(ARegion), "tool header for sequencer");
-
- BLI_addtail(&sseq->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOL_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- ar->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
-
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for sequencer");
-
- BLI_addtail(&sseq->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
-
- /* buttons/list view */
- ar = MEM_callocN(sizeof(ARegion), "buttons for sequencer");
-
- BLI_addtail(&sseq->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_RIGHT;
- ar->flag = RGN_FLAG_HIDDEN;
-
- /* toolbar */
- ar = MEM_callocN(sizeof(ARegion), "tools for sequencer");
-
- BLI_addtail(&sseq->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOLS;
- ar->alignment = RGN_ALIGN_LEFT;
- ar->flag = RGN_FLAG_HIDDEN;
-
- /* preview region */
- /* NOTE: if you change values here, also change them in sequencer_init_preview_region */
- ar = MEM_callocN(sizeof(ARegion), "preview region for sequencer");
- BLI_addtail(&sseq->regionbase, ar);
- ar->regiontype = RGN_TYPE_PREVIEW;
- ar->alignment = RGN_ALIGN_TOP;
- ar->flag |= RGN_FLAG_HIDDEN;
- /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- ar->v2d.keepzoom = V2D_KEEPASPECT | V2D_KEEPZOOM | V2D_LIMITZOOM;
- ar->v2d.minzoom = 0.001f;
- ar->v2d.maxzoom = 1000.0f;
- ar->v2d.tot.xmin = -960.0f; /* 1920 width centered */
- ar->v2d.tot.ymin = -540.0f; /* 1080 height centered */
- ar->v2d.tot.xmax = 960.0f;
- ar->v2d.tot.ymax = 540.0f;
- ar->v2d.min[0] = 0.0f;
- ar->v2d.min[1] = 0.0f;
- ar->v2d.max[0] = 12000.0f;
- ar->v2d.max[1] = 12000.0f;
- ar->v2d.cur = ar->v2d.tot;
- ar->v2d.align = V2D_ALIGN_FREE;
- ar->v2d.keeptot = V2D_KEEPTOT_FREE;
-
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for sequencer");
-
- BLI_addtail(&sseq->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
-
- /* seq space goes from (0,8) to (0, efra) */
-
- ar->v2d.tot.xmin = 0.0f;
- ar->v2d.tot.ymin = 0.0f;
- ar->v2d.tot.xmax = scene->r.efra;
- ar->v2d.tot.ymax = 8.0f;
-
- ar->v2d.cur = ar->v2d.tot;
-
- ar->v2d.min[0] = 10.0f;
- ar->v2d.min[1] = 0.5f;
-
- ar->v2d.max[0] = MAXFRAMEF;
- ar->v2d.max[1] = MAXSEQ;
-
- ar->v2d.minzoom = 0.01f;
- ar->v2d.maxzoom = 100.0f;
-
- ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
- ar->v2d.keepzoom = 0;
- ar->v2d.keeptot = 0;
- ar->v2d.align = V2D_ALIGN_NO_NEG_Y;
+ sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKERS | SEQ_SHOW_FCURVES;
+
+ /* Tool header. */
+ region = MEM_callocN(sizeof(ARegion), "tool header for sequencer");
+
+ BLI_addtail(&sseq->regionbase, region);
+ region->regiontype = RGN_TYPE_TOOL_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ region->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
+
+ /* Header. */
+ region = MEM_callocN(sizeof(ARegion), "header for sequencer");
+
+ BLI_addtail(&sseq->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+
+ /* Buttons/list view. */
+ region = MEM_callocN(sizeof(ARegion), "buttons for sequencer");
+
+ BLI_addtail(&sseq->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_RIGHT;
+ region->flag = RGN_FLAG_HIDDEN;
+
+ /* Toolbar. */
+ region = MEM_callocN(sizeof(ARegion), "tools for sequencer");
+
+ BLI_addtail(&sseq->regionbase, region);
+ region->regiontype = RGN_TYPE_TOOLS;
+ region->alignment = RGN_ALIGN_LEFT;
+ region->flag = RGN_FLAG_HIDDEN;
+
+ /* Preview region. */
+ /* NOTE: if you change values here, also change them in sequencer_init_preview_region. */
+ region = MEM_callocN(sizeof(ARegion), "preview region for sequencer");
+ BLI_addtail(&sseq->regionbase, region);
+ region->regiontype = RGN_TYPE_PREVIEW;
+ region->alignment = RGN_ALIGN_TOP;
+ region->flag |= RGN_FLAG_HIDDEN;
+ /* For now, aspect ratio should be maintained, and zoom is clamped within sane default limits. */
+ region->v2d.keepzoom = V2D_KEEPASPECT | V2D_KEEPZOOM | V2D_LIMITZOOM;
+ region->v2d.minzoom = 0.001f;
+ region->v2d.maxzoom = 1000.0f;
+ region->v2d.tot.xmin = -960.0f; /* 1920 width centered. */
+ region->v2d.tot.ymin = -540.0f; /* 1080 height centered. */
+ region->v2d.tot.xmax = 960.0f;
+ region->v2d.tot.ymax = 540.0f;
+ region->v2d.min[0] = 0.0f;
+ region->v2d.min[1] = 0.0f;
+ region->v2d.max[0] = 12000.0f;
+ region->v2d.max[1] = 12000.0f;
+ region->v2d.cur = region->v2d.tot;
+ region->v2d.align = V2D_ALIGN_FREE;
+ region->v2d.keeptot = V2D_KEEPTOT_FREE;
+
+ /* Main region. */
+ region = MEM_callocN(sizeof(ARegion), "main region for sequencer");
+
+ BLI_addtail(&sseq->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
+
+ /* Seq space goes from (0,8) to (0, efra). */
+ region->v2d.tot.xmin = 0.0f;
+ region->v2d.tot.ymin = 0.0f;
+ region->v2d.tot.xmax = scene->r.efra;
+ region->v2d.tot.ymax = 8.0f;
+
+ region->v2d.cur = region->v2d.tot;
+
+ region->v2d.min[0] = 10.0f;
+ region->v2d.min[1] = 0.5f;
+
+ region->v2d.max[0] = MAXFRAMEF;
+ region->v2d.max[1] = MAXSEQ;
+
+ region->v2d.minzoom = 0.01f;
+ region->v2d.maxzoom = 100.0f;
+
+ region->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ region->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
+ region->v2d.keepzoom = 0;
+ region->v2d.keeptot = 0;
+ region->v2d.align = V2D_ALIGN_NO_NEG_Y;
return (SpaceLink *)sseq;
}
-/* not spacelink itself */
+/* Not spacelink itself. */
static void sequencer_free(SpaceLink *sl)
{
SpaceSeq *sseq = (SpaceSeq *)sl;
SequencerScopes *scopes = &sseq->scopes;
- // XXX if (sseq->gpd) BKE_gpencil_free(sseq->gpd);
+ /* XXX if (sseq->gpd) BKE_gpencil_free(sseq->gpd); */
if (scopes->zebra_ibuf) {
IMB_freeImBuf(scopes->zebra_ibuf);
@@ -211,98 +213,98 @@ static void sequencer_free(SpaceLink *sl)
}
}
-/* spacetype; init callback */
-static void sequencer_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+/* Spacetype init callback. */
+static void sequencer_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
-static void sequencer_refresh(const bContext *C, ScrArea *sa)
+static void sequencer_refresh(const bContext *C, ScrArea *area)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *window = CTX_wm_window(C);
- SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
- ARegion *ar_main = sequencer_find_region(sa, RGN_TYPE_WINDOW);
- ARegion *ar_preview = sequencer_find_region(sa, RGN_TYPE_PREVIEW);
+ SpaceSeq *sseq = (SpaceSeq *)area->spacedata.first;
+ ARegion *region_main = sequencer_find_region(area, RGN_TYPE_WINDOW);
+ ARegion *region_preview = sequencer_find_region(area, RGN_TYPE_PREVIEW);
bool view_changed = false;
switch (sseq->view) {
case SEQ_VIEW_SEQUENCE:
- if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
- ar_main->flag &= ~RGN_FLAG_HIDDEN;
- ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
+ if (region_main && (region_main->flag & RGN_FLAG_HIDDEN)) {
+ region_main->flag &= ~RGN_FLAG_HIDDEN;
+ region_main->v2d.flag &= ~V2D_IS_INITIALISED;
view_changed = true;
}
- if (ar_preview && !(ar_preview->flag & RGN_FLAG_HIDDEN)) {
- ar_preview->flag |= RGN_FLAG_HIDDEN;
- ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
- WM_event_remove_handlers((bContext *)C, &ar_preview->handlers);
+ if (region_preview && !(region_preview->flag & RGN_FLAG_HIDDEN)) {
+ region_preview->flag |= RGN_FLAG_HIDDEN;
+ region_preview->v2d.flag &= ~V2D_IS_INITIALISED;
+ WM_event_remove_handlers((bContext *)C, &region_preview->handlers);
view_changed = true;
}
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
+ if (region_main && region_main->alignment != RGN_ALIGN_NONE) {
+ region_main->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
- ar_preview->alignment = RGN_ALIGN_NONE;
+ if (region_preview && region_preview->alignment != RGN_ALIGN_NONE) {
+ region_preview->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
break;
case SEQ_VIEW_PREVIEW:
- if (ar_main && !(ar_main->flag & RGN_FLAG_HIDDEN)) {
- ar_main->flag |= RGN_FLAG_HIDDEN;
- ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
- WM_event_remove_handlers((bContext *)C, &ar_main->handlers);
+ if (region_main && !(region_main->flag & RGN_FLAG_HIDDEN)) {
+ region_main->flag |= RGN_FLAG_HIDDEN;
+ region_main->v2d.flag &= ~V2D_IS_INITIALISED;
+ WM_event_remove_handlers((bContext *)C, &region_main->handlers);
view_changed = true;
}
- if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
- ar_preview->flag &= ~RGN_FLAG_HIDDEN;
- ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
- ar_preview->v2d.cur = ar_preview->v2d.tot;
+ if (region_preview && (region_preview->flag & RGN_FLAG_HIDDEN)) {
+ region_preview->flag &= ~RGN_FLAG_HIDDEN;
+ region_preview->v2d.flag &= ~V2D_IS_INITIALISED;
+ region_preview->v2d.cur = region_preview->v2d.tot;
view_changed = true;
}
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
+ if (region_main && region_main->alignment != RGN_ALIGN_NONE) {
+ region_main->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
- ar_preview->alignment = RGN_ALIGN_NONE;
+ if (region_preview && region_preview->alignment != RGN_ALIGN_NONE) {
+ region_preview->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
break;
case SEQ_VIEW_SEQUENCE_PREVIEW:
- if (ar_main && ar_preview) {
+ if (region_main && region_preview) {
/* Get available height (without DPI correction). */
- const float height = (sa->winy - ED_area_headersize()) / UI_DPI_FAC;
+ const float height = (area->winy - ED_area_headersize()) / UI_DPI_FAC;
/* We reuse hidden region's size, allows to find same layout as before if we just switch
* between one 'full window' view and the combined one. This gets lost if we switch to both
* 'full window' views before, though... Better than nothing. */
- if (ar_main->flag & RGN_FLAG_HIDDEN) {
- ar_main->flag &= ~RGN_FLAG_HIDDEN;
- ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
- ar_preview->sizey = (int)(height - ar_main->sizey);
+ if (region_main->flag & RGN_FLAG_HIDDEN) {
+ region_main->flag &= ~RGN_FLAG_HIDDEN;
+ region_main->v2d.flag &= ~V2D_IS_INITIALISED;
+ region_preview->sizey = (int)(height - region_main->sizey);
view_changed = true;
}
- if (ar_preview->flag & RGN_FLAG_HIDDEN) {
- ar_preview->flag &= ~RGN_FLAG_HIDDEN;
- ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
- ar_preview->v2d.cur = ar_preview->v2d.tot;
- ar_main->sizey = (int)(height - ar_preview->sizey);
+ if (region_preview->flag & RGN_FLAG_HIDDEN) {
+ region_preview->flag &= ~RGN_FLAG_HIDDEN;
+ region_preview->v2d.flag &= ~V2D_IS_INITIALISED;
+ region_preview->v2d.cur = region_preview->v2d.tot;
+ region_main->sizey = (int)(height - region_preview->sizey);
view_changed = true;
}
- if (ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
+ if (region_main->alignment != RGN_ALIGN_NONE) {
+ region_main->alignment = RGN_ALIGN_NONE;
view_changed = true;
}
- if (ar_preview->alignment != RGN_ALIGN_TOP) {
- ar_preview->alignment = RGN_ALIGN_TOP;
+ if (region_preview->alignment != RGN_ALIGN_TOP) {
+ region_preview->alignment = RGN_ALIGN_TOP;
view_changed = true;
}
- /* Final check that both preview and main height are reasonable! */
- if (ar_preview->sizey < 10 || ar_main->sizey < 10 ||
- ar_preview->sizey + ar_main->sizey > height) {
- ar_preview->sizey = (int)(height * 0.4f + 0.5f);
- ar_main->sizey = (int)(height - ar_preview->sizey);
+ /* Final check that both preview and main height are reasonable. */
+ if (region_preview->sizey < 10 || region_main->sizey < 10 ||
+ region_preview->sizey + region_main->sizey > height) {
+ region_preview->sizey = (int)(height * 0.4f + 0.5f);
+ region_main->sizey = (int)(height - region_preview->sizey);
view_changed = true;
}
}
@@ -310,8 +312,8 @@ static void sequencer_refresh(const bContext *C, ScrArea *sa)
}
if (view_changed) {
- ED_area_initialize(wm, window, sa);
- ED_area_tag_redraw(sa);
+ ED_area_initialize(wm, window, area);
+ ED_area_tag_redraw(area);
}
}
@@ -319,8 +321,8 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl)
{
SpaceSeq *sseqn = MEM_dupallocN(sl);
- /* clear or remove stuff from old */
- // XXX sseq->gpd = gpencil_data_duplicate(sseq->gpd, false);
+ /* Clear or remove stuff from old. */
+ /* XXX sseq->gpd = gpencil_data_duplicate(sseq->gpd, false); */
memset(&sseqn->scopes, 0, sizeof(sseqn->scopes));
@@ -328,29 +330,29 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl)
}
static void sequencer_listener(wmWindow *UNUSED(win),
- ScrArea *sa,
+ ScrArea *area,
wmNotifier *wmn,
Scene *UNUSED(scene))
{
- /* context changes */
+ /* Context changes. */
switch (wmn->category) {
case NC_SCENE:
switch (wmn->data) {
case ND_FRAME:
case ND_SEQUENCER:
- sequencer_scopes_tag_refresh(sa);
+ sequencer_scopes_tag_refresh(area);
break;
}
break;
case NC_WINDOW:
case NC_SPACE:
if (wmn->data == ND_SPACE_SEQUENCER) {
- sequencer_scopes_tag_refresh(sa);
+ sequencer_scopes_tag_refresh(area);
}
break;
case NC_GPENCIL:
if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
}
@@ -361,15 +363,15 @@ static void sequencer_listener(wmWindow *UNUSED(win),
static bool image_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
int hand;
if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, ICON_FILE_IMAGE, ICON_FILE_BLANK)) { /* rule might not work? */
- if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL) {
+ if (ELEM(drag->icon, ICON_FILE_IMAGE, ICON_FILE_BLANK)) { /* Rule might not work? */
+ if (find_nearest_seq(scene, &region->v2d, &hand, event->mval) == NULL) {
return 1;
}
}
@@ -381,15 +383,15 @@ static bool image_drop_poll(bContext *C,
static bool movie_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
int hand;
if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) { /* rule might not work? */
- if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL) {
+ if (ELEM(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) { /* Rule might not work? */
+ if (find_nearest_seq(scene, &region->v2d, &hand, event->mval) == NULL) {
return 1;
}
}
@@ -400,15 +402,15 @@ static bool movie_drop_poll(bContext *C,
static bool sound_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
int hand;
if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, ICON_FILE_SOUND, ICON_FILE_BLANK)) { /* rule might not work? */
- if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL) {
+ if (ELEM(drag->icon, ICON_FILE_SOUND, ICON_FILE_BLANK)) { /* Rule might not work? */
+ if (find_nearest_seq(scene, &region->v2d, &hand, event->mval) == NULL) {
return 1;
}
}
@@ -418,7 +420,7 @@ static bool sound_drop_poll(bContext *C,
static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- /* copy drag path to properties */
+ /* Copy drag path to properties. */
if (RNA_struct_find_property(drop->ptr, "filepath")) {
RNA_string_set(drop->ptr, "filepath", drag->path);
}
@@ -437,7 +439,7 @@ static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
}
}
-/* this region dropbox definition */
+/* This region dropbox definition. */
static void sequencer_dropboxes(void)
{
ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
@@ -450,7 +452,7 @@ static void sequencer_dropboxes(void)
/* ************* end drop *********** */
/* DO NOT make this static, this hides the symbol and breaks API generation script. */
-extern const char *sequencer_context_dir[]; /* quiet warning. */
+extern const char *sequencer_context_dir[]; /* Quiet warning. */
const char *sequencer_context_dir[] = {"edit_mask", NULL};
static int sequencer_context(const bContext *C, const char *member, bContextDataResult *result)
@@ -487,78 +489,78 @@ static void sequencer_gizmos(void)
}
/* *********************** sequencer (main) region ************************ */
-/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_main_region_init(wmWindowManager *wm, ARegion *ar)
+/* Add handlers, stuff you only do once or on area/region changes. */
+static void sequencer_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
ListBase *lb;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
#if 0
keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
#endif
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
- /* own keymap */
+ /* Own keymap. */
keymap = WM_keymap_ensure(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
- /* add drop boxes */
+ /* Add drop boxes. */
lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
- WM_event_add_dropbox_handler(&ar->handlers, lb);
+ WM_event_add_dropbox_handler(&region->handlers, lb);
}
-static void sequencer_main_region_draw(const bContext *C, ARegion *ar)
+/* Strip editing timeline. */
+static void sequencer_main_region_draw(const bContext *C, ARegion *region)
{
- /* NLE - strip editing timeline interface */
- draw_timeline_seq(C, ar);
+ draw_timeline_seq(C, region);
}
static void sequencer_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
- /* context changes */
+ /* Context changes. */
switch (wmn->category) {
case NC_SCENE:
switch (wmn->data) {
case ND_FRAME:
case ND_FRAME_RANGE:
case ND_MARKERS:
- case ND_RENDER_OPTIONS: /* for FPS and FPS Base */
+ case ND_RENDER_OPTIONS: /* For FPS and FPS Base. */
case ND_SEQUENCER:
case ND_RENDER_RESULT:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_ANIMATION:
switch (wmn->data) {
case ND_KEYFRAME:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_SEQUENCER) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCREEN:
if (ELEM(wmn->data, ND_ANIMPLAY)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -568,13 +570,13 @@ static void sequencer_main_region_message_subscribe(const struct bContext *UNUSE
struct WorkSpace *UNUSED(workspace),
struct Scene *scene,
struct bScreen *UNUSED(screen),
- struct ScrArea *UNUSED(sa),
- struct ARegion *ar,
+ struct ScrArea *UNUSED(area),
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -623,73 +625,72 @@ static void sequencer_main_region_message_subscribe(const struct bContext *UNUSE
}
/* *********************** header region ************************ */
-/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+/* Add handlers, stuff you only do once or on area/region changes. */
+static void sequencer_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void sequencer_header_region_draw(const bContext *C, ARegion *ar)
+static void sequencer_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
/* *********************** toolbar region ************************ */
-/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_tools_region_init(wmWindowManager *wm, ARegion *ar)
+/* Add handlers, stuff you only do once or on area/region changes. */
+static void sequencer_tools_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void sequencer_tools_region_draw(const bContext *C, ARegion *ar)
+static void sequencer_tools_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
/* *********************** preview region ************************ */
-static void sequencer_preview_region_init(wmWindowManager *wm, ARegion *ar)
+static void sequencer_preview_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
#if 0
keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
#endif
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
- /* own keymap */
+ /* Own keymap. */
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerPreview", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void sequencer_preview_region_draw(const bContext *C, ARegion *ar)
+static void sequencer_preview_region_draw(const bContext *C, ARegion *region)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceSeq *sseq = sa->spacedata.first;
+ ScrArea *area = CTX_wm_area(C);
+ SpaceSeq *sseq = area->spacedata.first;
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
- const bool show_split = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) &&
- (sseq->mainb == SEQ_DRAW_IMG_IMBUF));
+ const bool draw_overlay = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW));
/* XXX temp fix for wrong setting in sseq->mainb */
if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
sseq->mainb = SEQ_DRAW_IMG_IMBUF;
}
- if (!show_split || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE) {
- sequencer_draw_preview(C, scene, ar, sseq, scene->r.cfra, 0, false, false);
+ if (!draw_overlay || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE) {
+ sequencer_draw_preview(C, scene, region, sseq, scene->r.cfra, 0, false, false);
}
- if (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
+ if (draw_overlay && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
int over_cfra;
if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) {
@@ -701,14 +702,14 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *ar)
if (over_cfra != scene->r.cfra || sseq->overlay_type != SEQ_DRAW_OVERLAY_RECT) {
sequencer_draw_preview(
- C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true, false);
+ C, scene, region, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true, false);
}
}
- WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
+ WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
- const rcti *rect = ED_region_visible_rect(ar);
+ const rcti *rect = ED_region_visible_rect(region);
int xoffset = rect->xmin + U.widget_unit;
int yoffset = rect->ymax;
ED_scene_draw_fps(scene, xoffset, &yoffset);
@@ -716,16 +717,16 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *ar)
}
static void sequencer_preview_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
- /* context changes */
+ /* Context changes. */
switch (wmn->category) {
case NC_GPENCIL:
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
@@ -735,32 +736,32 @@ static void sequencer_preview_region_listener(wmWindow *UNUSED(win),
case ND_SEQUENCER:
case ND_RENDER_OPTIONS:
case ND_DRAW_RENDER_VIEWPORT:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_ANIMATION:
switch (wmn->data) {
case ND_KEYFRAME:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_SEQUENCER) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ID:
switch (wmn->data) {
case NA_RENAME:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_MASK:
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -768,58 +769,58 @@ static void sequencer_preview_region_listener(wmWindow *UNUSED(win),
/* *********************** buttons region ************************ */
-/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar)
+/* Add handlers, stuff you only do once or on area/region changes. */
+static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
- UI_panel_category_active_set_default(ar, "Strip");
- ED_region_panels_init(wm, ar);
+ UI_panel_category_active_set_default(region, "Strip");
+ ED_region_panels_init(wm, region);
}
-static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar)
+static void sequencer_buttons_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
static void sequencer_buttons_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
- /* context changes */
+ /* Context changes. */
switch (wmn->category) {
case NC_GPENCIL:
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
switch (wmn->data) {
case ND_FRAME:
case ND_SEQUENCER:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_SEQUENCER) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
}
-static void sequencer_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void sequencer_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceSeq *sseq = (SpaceSeq *)slink;
@@ -836,7 +837,7 @@ static void sequencer_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id
/* ************************************* */
-/* only called once, from space/spacetypes.c */
+/* Only called once, from space/spacetypes.c. */
void ED_spacetype_sequencer(void)
{
SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
@@ -858,7 +859,8 @@ void ED_spacetype_sequencer(void)
st->listener = sequencer_listener;
st->id_remap = sequencer_id_remap;
- /* regions: main window */
+ /* Create regions: */
+ /* Main window. */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_WINDOW;
art->init = sequencer_main_region_init;
@@ -866,10 +868,9 @@ void ED_spacetype_sequencer(void)
art->listener = sequencer_main_region_listener;
art->message_subscribe = sequencer_main_region_message_subscribe;
art->keymapflag = ED_KEYMAP_TOOL | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
-
BLI_addhead(&st->regiontypes, art);
- /* preview */
+ /* Preview. */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_PREVIEW;
art->init = sequencer_preview_region_init;
@@ -879,7 +880,7 @@ void ED_spacetype_sequencer(void)
ED_KEYMAP_GPENCIL;
BLI_addhead(&st->regiontypes, art);
- /* regions: listview/buttons */
+ /* Listview/buttons. */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_UI;
art->prefsizex = UI_SIDEBAR_PANEL_WIDTH * 1.3f;
@@ -891,7 +892,7 @@ void ED_spacetype_sequencer(void)
BLI_addhead(&st->regiontypes, art);
sequencer_buttons_register(art);
- /* regions: tool(bar) */
+ /* Toolbar. */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer tools region");
art->regionid = RGN_TYPE_TOOLS;
art->prefsizex = 58; /* XXX */
@@ -903,7 +904,7 @@ void ED_spacetype_sequencer(void)
art->draw = sequencer_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
- /* regions: tool header */
+ /* Tool header. */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer tool header region");
art->regionid = RGN_TYPE_TOOL_HEADER;
art->prefsizey = HEADERY;
@@ -914,7 +915,7 @@ void ED_spacetype_sequencer(void)
art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header;
BLI_addhead(&st->regiontypes, art);
- /* regions: header */
+ /* Header. */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_HEADER;
art->prefsizey = HEADERY;
@@ -923,17 +924,16 @@ void ED_spacetype_sequencer(void)
art->init = sequencer_header_region_init;
art->draw = sequencer_header_region_draw;
art->listener = sequencer_main_region_listener;
-
BLI_addhead(&st->regiontypes, art);
- /* regions: hud */
+ /* Hud. */
art = ED_area_type_hud(st->spaceid);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
- /* set the sequencer callback when not in background mode */
+ /* Set the sequencer callback when not in background mode. */
if (G.background == 0) {
- sequencer_view3d_cb = ED_view3d_draw_offscreen_imbuf_simple;
+ sequencer_view3d_fn = ED_view3d_draw_offscreen_imbuf_simple;
}
}
diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c
index 69060daa171..34d7f8b0216 100644
--- a/source/blender/editors/space_statusbar/space_statusbar.c
+++ b/source/blender/editors/space_statusbar/space_statusbar.c
@@ -18,8 +18,8 @@
* \ingroup spstatusbar
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -37,24 +37,24 @@
#include "UI_view2d.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
/* ******************** default callbacks for statusbar space ******************** */
static SpaceLink *statusbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceStatusBar *sstatusbar;
sstatusbar = MEM_callocN(sizeof(*sstatusbar), "init statusbar");
sstatusbar->spacetype = SPACE_STATUSBAR;
/* header region */
- ar = MEM_callocN(sizeof(*ar), "header for statusbar");
- BLI_addtail(&sstatusbar->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_NONE;
+ region = MEM_callocN(sizeof(*region), "header for statusbar");
+ BLI_addtail(&sstatusbar->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = RGN_ALIGN_NONE;
return (SpaceLink *)sstatusbar;
}
@@ -65,7 +65,7 @@ static void statusbar_free(SpaceLink *UNUSED(sl))
}
/* spacetype; init callback */
-static void statusbar_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void statusbar_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -96,8 +96,8 @@ static void statusbar_keymap(struct wmKeyConfig *UNUSED(keyconf))
}
static void statusbar_header_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -105,27 +105,27 @@ static void statusbar_header_region_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_SCREEN:
if (ELEM(wmn->data, ND_LAYER, ND_ANIMPLAY)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_WM:
if (wmn->data == ND_JOB) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
if (wmn->data == ND_RENDER_RESULT) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_INFO) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -135,13 +135,13 @@ static void statusbar_header_region_message_subscribe(const bContext *UNUSED(C),
WorkSpace *UNUSED(workspace),
Scene *UNUSED(scene),
bScreen *UNUSED(screen),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
struct wmMsgBus *mbus)
{
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index b477e3838bd..76d61193ce0 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -29,14 +29,14 @@
#include "BLI_blenlib.h"
-#include "BKE_global.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_lib_id.h"
#include "BKE_screen.h"
#include "BKE_text.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -47,15 +47,15 @@
#include "RNA_access.h"
+#include "GPU_framebuffer.h"
#include "text_format.h"
#include "text_intern.h" /* own include */
-#include "GPU_framebuffer.h"
/* ******************** default callbacks for text space ***************** */
static SpaceLink *text_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceText *stext;
stext = MEM_callocN(sizeof(SpaceText), "inittext");
@@ -68,31 +68,31 @@ static SpaceLink *text_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
stext->showlinenrs = true;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for text");
+ region = MEM_callocN(sizeof(ARegion), "header for text");
- BLI_addtail(&stext->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&stext->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* footer */
- ar = MEM_callocN(sizeof(ARegion), "footer for text");
- BLI_addtail(&stext->regionbase, ar);
- ar->regiontype = RGN_TYPE_FOOTER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_TOP : RGN_ALIGN_BOTTOM;
+ region = MEM_callocN(sizeof(ARegion), "footer for text");
+ BLI_addtail(&stext->regionbase, region);
+ region->regiontype = RGN_TYPE_FOOTER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_TOP : RGN_ALIGN_BOTTOM;
/* properties region */
- ar = MEM_callocN(sizeof(ARegion), "properties region for text");
+ region = MEM_callocN(sizeof(ARegion), "properties region for text");
- BLI_addtail(&stext->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_RIGHT;
- ar->flag = RGN_FLAG_HIDDEN;
+ BLI_addtail(&stext->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_RIGHT;
+ region->flag = RGN_FLAG_HIDDEN;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for text");
+ region = MEM_callocN(sizeof(ARegion), "main region for text");
- BLI_addtail(&stext->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&stext->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
return (SpaceLink *)stext;
}
@@ -107,7 +107,7 @@ static void text_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void text_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void text_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -123,11 +123,11 @@ static SpaceLink *text_duplicate(SpaceLink *sl)
}
static void text_listener(wmWindow *UNUSED(win),
- ScrArea *sa,
+ ScrArea *area,
wmNotifier *wmn,
Scene *UNUSED(scene))
{
- SpaceText *st = sa->spacedata.first;
+ SpaceText *st = area->spacedata.first;
/* context changes */
switch (wmn->category) {
@@ -141,14 +141,14 @@ static void text_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_DISPLAY:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case ND_CURSOR:
if (st->text && st->text == wmn->reference) {
- text_scroll_to_cursor__area(st, sa, true);
+ text_scroll_to_cursor__area(st, area, true);
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
}
@@ -159,15 +159,15 @@ static void text_listener(wmWindow *UNUSED(win),
text_update_edited(st->text);
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
ATTR_FALLTHROUGH; /* fall down to tag redraw */
case NA_ADDED:
case NA_REMOVED:
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
break;
case NA_SELECTED:
if (st->text && st->text == wmn->reference) {
- text_scroll_to_cursor__area(st, sa, true);
+ text_scroll_to_cursor__area(st, area, true);
}
break;
@@ -176,7 +176,7 @@ static void text_listener(wmWindow *UNUSED(win),
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_TEXT) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
break;
}
@@ -269,30 +269,30 @@ static int text_context(const bContext *C, const char *member, bContextDataResul
/********************* main region ********************/
/* add handlers, stuff you only do once or on area/region changes */
-static void text_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void text_main_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
ListBase *lb;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_STANDARD, region->winx, region->winy);
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "Text Generic", SPACE_TEXT, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Text", SPACE_TEXT, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
/* add drop boxes */
lb = WM_dropboxmap_find("Text", SPACE_TEXT, RGN_TYPE_WINDOW);
- WM_event_add_dropbox_handler(&ar->handlers, lb);
+ WM_event_add_dropbox_handler(&region->handlers, lb);
}
-static void text_main_region_draw(const bContext *C, ARegion *ar)
+static void text_main_region_draw(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
SpaceText *st = CTX_wm_space_text(C);
- // View2D *v2d = &ar->v2d;
+ // View2D *v2d = &region->v2d;
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
@@ -301,7 +301,7 @@ static void text_main_region_draw(const bContext *C, ARegion *ar)
// UI_view2d_view_ortho(v2d);
/* data... */
- draw_text_main(st, ar);
+ draw_text_main(st, region);
/* reset view matrix */
// UI_view2d_view_restore(C);
@@ -309,13 +309,13 @@ static void text_main_region_draw(const bContext *C, ARegion *ar)
/* scrollers? */
}
-static void text_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
+static void text_cursor(wmWindow *win, ScrArea *area, ARegion *region)
{
- SpaceText *st = sa->spacedata.first;
+ SpaceText *st = area->spacedata.first;
int wmcursor = WM_CURSOR_TEXT_EDIT;
if (st->text && BLI_rcti_isect_pt(&st->runtime.scroll_region_handle,
- win->eventstate->x - ar->winrct.xmin,
+ win->eventstate->x - region->winrct.xmin,
st->runtime.scroll_region_handle.ymin)) {
wmcursor = WM_CURSOR_DEFAULT;
}
@@ -328,7 +328,7 @@ static void text_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
static bool text_drop_poll(bContext *UNUSED(C),
wmDrag *drag,
const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
if (drag->type == WM_DRAG_PATH) {
/* rule might not work? */
@@ -348,7 +348,7 @@ static void text_drop_copy(wmDrag *drag, wmDropBox *drop)
static bool text_drop_paste_poll(bContext *UNUSED(C),
wmDrag *drag,
const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const char **UNUSED(r_tooltip))
{
return (drag->type == WM_DRAG_ID);
}
@@ -378,49 +378,49 @@ static void text_dropboxes(void)
/****************** header region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void text_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void text_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void text_header_region_draw(const bContext *C, ARegion *ar)
+static void text_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
/****************** properties region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void text_properties_region_init(wmWindowManager *wm, ARegion *ar)
+static void text_properties_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ ED_region_panels_init(wm, region);
/* own keymaps */
keymap = WM_keymap_ensure(wm->defaultconf, "Text Generic", SPACE_TEXT, 0);
- WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void text_properties_region_draw(const bContext *C, ARegion *ar)
+static void text_properties_region_draw(const bContext *C, ARegion *region)
{
SpaceText *st = CTX_wm_space_text(C);
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
/* this flag trick is make sure buttons have been added already */
if (st->flags & ST_FIND_ACTIVATE) {
- if (UI_textbutton_activate_rna(C, ar, st, "find_text")) {
+ if (UI_textbutton_activate_rna(C, region, st, "find_text")) {
/* if the panel was already open we need to do another redraw */
- ScrArea *sa = CTX_wm_area(C);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_TEXT, sa);
+ ScrArea *area = CTX_wm_area(C);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_TEXT, area);
}
st->flags &= ~ST_FIND_ACTIVATE;
}
}
-static void text_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+static void text_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceText *stext = (SpaceText *)slink;
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index a560b8af70f..1f034bdbd09 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -29,16 +29,16 @@
#include "BLI_ghash.h"
#include "BKE_context.h"
+#include "BKE_screen.h"
#include "BKE_text.h"
#include "BKE_text_suggestions.h"
-#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_screen.h"
#include "ED_text.h"
#include "ED_undo.h"
-#include "ED_screen.h"
#include "UI_interface.h"
@@ -49,7 +49,7 @@
/** \name Public API
* \{ */
-int text_do_suggest_select(SpaceText *st, ARegion *ar)
+int text_do_suggest_select(SpaceText *st, ARegion *region)
{
SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
TextLine *tmp;
@@ -84,7 +84,7 @@ int text_do_suggest_select(SpaceText *st, ARegion *ar)
text_update_character_width(st);
x = TXT_BODY_LEFT(st) + (st->runtime.cwidth_px * (st->text->curc - st->left));
- y = ar->winy - st->runtime.lheight_px * l - 2;
+ y = region->winy - st->runtime.lheight_px * l - 2;
w = SUGG_LIST_WIDTH * st->runtime.cwidth_px + U.widget_unit;
h = SUGG_LIST_SIZE * st->runtime.lheight_px + 0.4f * U.widget_unit;
@@ -335,8 +335,8 @@ static int doc_scroll = 0;
static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
int draw = 0, tools = 0, swallow = 0, scroll = 1;
Text *text = CTX_data_edit_text(C);
@@ -356,7 +356,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
switch (event->type) {
case LEFTMOUSE:
if (event->val == KM_PRESS) {
- if (text_do_suggest_select(st, ar)) {
+ if (text_do_suggest_select(st, region)) {
swallow = 1;
}
else {
@@ -374,7 +374,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
break;
case MIDDLEMOUSE:
if (event->val == KM_PRESS) {
- if (text_do_suggest_select(st, ar)) {
+ if (text_do_suggest_select(st, region)) {
ED_text_undo_push_init(C);
confirm_suggestion(st->text);
text_update_line_edited(st->text->curl);
@@ -394,7 +394,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
draw = 1;
}
break;
- case ESCKEY:
+ case EVT_ESCKEY:
if (event->val == KM_PRESS) {
draw = swallow = 1;
if (tools & TOOL_SUGG_LIST) {
@@ -410,8 +410,8 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
retval = OPERATOR_CANCELLED;
}
break;
- case RETKEY:
- case PADENTER:
+ case EVT_RETKEY:
+ case EVT_PADENTER:
if (event->val == KM_PRESS) {
if (tools & TOOL_SUGG_LIST) {
ED_text_undo_push_init(C);
@@ -429,8 +429,8 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
retval = OPERATOR_FINISHED;
}
break;
- case LEFTARROWKEY:
- case BACKSPACEKEY:
+ case EVT_LEFTARROWKEY:
+ case EVT_BACKSPACEKEY:
if (event->val == KM_PRESS) {
if (tools & TOOL_SUGG_LIST) {
if (event->ctrl) {
@@ -462,7 +462,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
}
}
break;
- case RIGHTARROWKEY:
+ case EVT_RIGHTARROWKEY:
if (event->val == KM_PRESS) {
if (tools & TOOL_SUGG_LIST) {
if (event->ctrl) {
@@ -494,11 +494,11 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
}
}
break;
- case PAGEDOWNKEY:
+ case EVT_PAGEDOWNKEY:
scroll = SUGG_LIST_SIZE - 1;
ATTR_FALLTHROUGH;
case WHEELDOWNMOUSE:
- case DOWNARROWKEY:
+ case EVT_DOWNARROWKEY:
if (event->val == KM_PRESS) {
if (tools & TOOL_DOCUMENT) {
doc_scroll++;
@@ -528,11 +528,11 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
}
}
break;
- case PAGEUPKEY:
+ case EVT_PAGEUPKEY:
scroll = SUGG_LIST_SIZE - 1;
ATTR_FALLTHROUGH;
case WHEELUPMOUSE:
- case UPARROWKEY:
+ case EVT_UPARROWKEY:
if (event->val == KM_PRESS) {
if (tools & TOOL_DOCUMENT) {
if (doc_scroll > 0) {
@@ -559,8 +559,8 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
}
}
break;
- case RIGHTSHIFTKEY:
- case LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
+ case EVT_LEFTSHIFTKEY:
break;
#if 0
default:
@@ -577,7 +577,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
}
if (draw) {
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
// if (swallow) {
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 96fa9f87398..a0339b35c57 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -27,14 +27,14 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "DNA_text_types.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_text_types.h"
#include "BKE_context.h"
+#include "BKE_screen.h"
#include "BKE_text.h"
#include "BKE_text_suggestions.h"
-#include "BKE_screen.h"
#include "ED_text.h"
@@ -45,8 +45,8 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "text_intern.h"
#include "text_format.h"
+#include "text_intern.h"
/******************** text font drawing ******************/
@@ -187,9 +187,9 @@ static void format_draw_color(const TextDrawContext *tdc, char formatchar)
* \encode
*/
-int wrap_width(const SpaceText *st, ARegion *ar)
+int wrap_width(const SpaceText *st, ARegion *region)
{
- int winx = ar->winx - TXT_SCROLL_WIDTH;
+ int winx = region->winx - TXT_SCROLL_WIDTH;
int x, max;
x = TXT_BODY_LEFT(st);
@@ -199,7 +199,7 @@ int wrap_width(const SpaceText *st, ARegion *ar)
/* Sets (offl, offc) for transforming (line, curs) to its wrapped position */
void wrap_offset(
- const SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
+ const SpaceText *st, ARegion *region, TextLine *linein, int cursin, int *offl, int *offc)
{
Text *text;
TextLine *linep;
@@ -221,7 +221,7 @@ void wrap_offset(
linep = text->lines.first;
i = st->top;
while (i > 0 && linep) {
- int lines = text_get_visible_lines(st, ar, linep->line);
+ int lines = text_get_visible_lines(st, region, linep->line);
/* Line before top */
if (linep == linein) {
@@ -241,7 +241,7 @@ void wrap_offset(
}
}
- max = wrap_width(st, ar);
+ max = wrap_width(st, region);
cursin = BLI_str_utf8_offset_to_column(linein->line, cursin);
while (linep) {
@@ -305,7 +305,7 @@ void wrap_offset(
/* cursin - mem, offc - view */
void wrap_offset_in_line(
- const SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
+ const SpaceText *st, ARegion *region, TextLine *linein, int cursin, int *offl, int *offc)
{
int i, j, start, end, chars, max, chop;
char ch;
@@ -319,7 +319,7 @@ void wrap_offset_in_line(
return;
}
- max = wrap_width(st, ar);
+ max = wrap_width(st, region);
start = 0;
end = max;
@@ -598,7 +598,7 @@ static void text_drawcache_init(SpaceText *st)
st->runtime.drawcache = drawcache;
}
-static void text_update_drawcache(SpaceText *st, ARegion *ar)
+static void text_update_drawcache(SpaceText *st, ARegion *region)
{
DrawCache *drawcache;
int full_update = 0, nlines = 0;
@@ -616,7 +616,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
/* check if full cache update is needed */
/* area was resized */
- full_update |= drawcache->winx != ar->winx;
+ full_update |= drawcache->winx != region->winx;
/* word-wrapping option was toggled */
full_update |= drawcache->wordwrap != st->wordwrap;
/* word-wrapping option was toggled */
@@ -673,7 +673,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
lines_count = fp[lineno];
}
else {
- lines_count = text_get_visible_lines(st, ar, line->line);
+ lines_count = text_get_visible_lines(st, region, line->line);
}
fp[lineno] = lines_count;
@@ -706,7 +706,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
drawcache->nlines = nlines;
/* store settings */
- drawcache->winx = ar->winx;
+ drawcache->winx = region->winx;
drawcache->wordwrap = st->wordwrap;
drawcache->lheight = st->runtime.lheight_px;
drawcache->cwidth_px = st->runtime.cwidth_px;
@@ -793,12 +793,12 @@ static int text_get_visible_lines_no(const SpaceText *st, int lineno)
return drawcache->line_height[lineno];
}
-int text_get_visible_lines(const SpaceText *st, ARegion *ar, const char *str)
+int text_get_visible_lines(const SpaceText *st, ARegion *region, const char *str)
{
int i, j, start, end, max, lines, chars;
char ch;
- max = wrap_width(st, ar);
+ max = wrap_width(st, region);
lines = 1;
start = 0;
end = max;
@@ -832,7 +832,7 @@ int text_get_visible_lines(const SpaceText *st, ARegion *ar, const char *str)
return lines;
}
-int text_get_span_wrap(const SpaceText *st, ARegion *ar, TextLine *from, TextLine *to)
+int text_get_span_wrap(const SpaceText *st, ARegion *region, TextLine *from, TextLine *to)
{
if (st->wordwrap) {
int ret = 0;
@@ -843,7 +843,7 @@ int text_get_span_wrap(const SpaceText *st, ARegion *ar, TextLine *from, TextLin
if (tmp == to) {
return ret;
}
- ret += text_get_visible_lines(st, ar, tmp->line);
+ ret += text_get_visible_lines(st, region, tmp->line);
tmp = tmp->next;
}
@@ -854,11 +854,11 @@ int text_get_span_wrap(const SpaceText *st, ARegion *ar, TextLine *from, TextLin
}
}
-int text_get_total_lines(SpaceText *st, ARegion *ar)
+int text_get_total_lines(SpaceText *st, ARegion *region)
{
DrawCache *drawcache;
- text_update_drawcache(st, ar);
+ text_update_drawcache(st, region);
drawcache = st->runtime.drawcache;
return drawcache->total_lines;
@@ -866,7 +866,7 @@ int text_get_total_lines(SpaceText *st, ARegion *ar)
/************************ draw scrollbar *****************************/
-static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
+static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *back)
{
int lhlstart, lhlend, ltexth, sell_off, curl_off;
short barheight, barstart, hlstart, hlend, blank_lines;
@@ -874,17 +874,17 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
pix_top_margin = (0.4 * U.widget_unit);
pix_bottom_margin = (0.4 * U.widget_unit);
- pix_available = ar->winy - pix_top_margin - pix_bottom_margin;
- ltexth = text_get_total_lines(st, ar);
+ pix_available = region->winy - pix_top_margin - pix_bottom_margin;
+ ltexth = text_get_total_lines(st, region);
blank_lines = st->runtime.viewlines / 2;
/* nicer code: use scroll rect for entire bar */
- back->xmin = ar->winx - (0.6 * U.widget_unit);
- back->xmax = ar->winx;
+ back->xmin = region->winx - (0.6 * U.widget_unit);
+ back->xmax = region->winx;
back->ymin = 0;
- back->ymax = ar->winy;
+ back->ymax = region->winy;
- scroll->xmax = ar->winx - (0.2 * U.widget_unit);
+ scroll->xmax = region->winx - (0.2 * U.widget_unit);
scroll->xmin = scroll->xmax - (0.4 * U.widget_unit);
scroll->ymin = pix_top_margin;
scroll->ymax = pix_available;
@@ -909,16 +909,16 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
st->runtime.scroll_region_handle.ymax -= barstart;
st->runtime.scroll_region_handle.ymin = st->runtime.scroll_region_handle.ymax - barheight;
- CLAMP(st->runtime.scroll_region_handle.ymin, pix_bottom_margin, ar->winy - pix_top_margin);
- CLAMP(st->runtime.scroll_region_handle.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
+ CLAMP(st->runtime.scroll_region_handle.ymin, pix_bottom_margin, region->winy - pix_top_margin);
+ CLAMP(st->runtime.scroll_region_handle.ymax, pix_bottom_margin, region->winy - pix_top_margin);
st->runtime.scroll_px_per_line = (pix_available > 0) ? (float)ltexth / pix_available : 0;
if (st->runtime.scroll_px_per_line < 0.1f) {
st->runtime.scroll_px_per_line = 0.1f;
}
- curl_off = text_get_span_wrap(st, ar, st->text->lines.first, st->text->curl);
- sell_off = text_get_span_wrap(st, ar, st->text->lines.first, st->text->sell);
+ curl_off = text_get_span_wrap(st, region, st->text->lines.first, st->text->curl);
+ sell_off = text_get_span_wrap(st, region, st->text->lines.first, st->text->sell);
lhlstart = MIN2(curl_off, sell_off);
lhlend = MAX2(curl_off, sell_off);
@@ -981,11 +981,11 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
}
st->runtime.scroll_region_select = *scroll;
- st->runtime.scroll_region_select.ymax = ar->winy - pix_top_margin - hlstart;
- st->runtime.scroll_region_select.ymin = ar->winy - pix_top_margin - hlend;
+ st->runtime.scroll_region_select.ymax = region->winy - pix_top_margin - hlstart;
+ st->runtime.scroll_region_select.ymin = region->winy - pix_top_margin - hlend;
- CLAMP(st->runtime.scroll_region_select.ymin, pix_bottom_margin, ar->winy - pix_top_margin);
- CLAMP(st->runtime.scroll_region_select.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
+ CLAMP(st->runtime.scroll_region_select.ymin, pix_bottom_margin, region->winy - pix_top_margin);
+ CLAMP(st->runtime.scroll_region_select.ymax, pix_bottom_margin, region->winy - pix_top_margin);
}
static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
@@ -1025,7 +1025,7 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
/*********************** draw documentation *******************************/
#if 0
-static void draw_documentation(const SpaceText *st, ARegion *ar)
+static void draw_documentation(const SpaceText *st, ARegion *region)
{
TextDrawContext tdc = {0};
TextLine *tmp;
@@ -1062,7 +1062,7 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
x += SUGG_LIST_WIDTH * st->runtime.cwidth_px + 50;
}
- /* top = */ /* UNUSED */ y = ar->winy - st->runtime.lheight_px * l - 2;
+ /* top = */ /* UNUSED */ y = region->winy - st->runtime.lheight_px * l - 2;
boxw = DOC_WIDTH * st->runtime.cwidth_px + 20;
boxh = (DOC_HEIGHT + 1) * TXT_LINE_HEIGHT(st);
@@ -1136,7 +1136,7 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
/*********************** draw suggestion list *******************************/
-static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc, ARegion *ar)
+static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc, ARegion *region)
{
SuggItem *item, *first, *last, *sel;
char str[SUGG_LIST_WIDTH * BLI_UTF8_MAX + 1];
@@ -1163,12 +1163,12 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
sel = texttool_suggest_selected();
top = texttool_suggest_top();
- wrap_offset(st, ar, st->text->curl, st->text->curc, &offl, &offc);
+ wrap_offset(st, region, st->text->curl, st->text->curc, &offl, &offc);
vcurl = txt_get_span(st->text->lines.first, st->text->curl) - st->top + offl;
vcurc = text_get_char_pos(st, st->text->curl->line, st->text->curc) - st->left + offc;
x = TXT_BODY_LEFT(st) + (vcurc * st->runtime.cwidth_px);
- y = ar->winy - (vcurl + 1) * lheight - 2;
+ y = region->winy - (vcurl + 1) * lheight - 2;
/* offset back so the start of the text lines up with the suggestions,
* not essential but makes suggestions easier to follow */
@@ -1178,8 +1178,8 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
boxw = SUGG_LIST_WIDTH * st->runtime.cwidth_px + 20;
boxh = SUGG_LIST_SIZE * lheight + 8;
- if (x + boxw > ar->winx) {
- x = MAX2(0, ar->winx - boxw);
+ if (x + boxw > region->winx) {
+ x = MAX2(0, region->winx - boxw);
}
/* not needed but stands out nicer */
@@ -1232,7 +1232,7 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
/*********************** draw cursor ************************/
-static void draw_text_decoration(SpaceText *st, ARegion *ar)
+static void draw_text_decoration(SpaceText *st, ARegion *region)
{
Text *text = st->text;
int vcurl, vcurc, vsell, vselc, hidden = 0;
@@ -1241,7 +1241,7 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
const int lheight = TXT_LINE_HEIGHT(st);
/* Convert to view space character coordinates to determine if cursor is hidden */
- wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+ wrap_offset(st, region, text->sell, text->selc, &offl, &offc);
vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
@@ -1262,7 +1262,7 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
/* Draw the selection */
if (text->curl != text->sell || text->curc != text->selc) {
/* Convert all to view space character coordinates */
- wrap_offset(st, ar, text->curl, text->curc, &offl, &offc);
+ wrap_offset(st, region, text->curl, text->curc, &offl, &offc);
vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl;
vcurc = text_get_char_pos(st, text->curl->line, text->curc) - st->left + offc;
@@ -1273,7 +1273,7 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
immUniformThemeColor(TH_SHADE2);
x = TXT_BODY_LEFT(st);
- y = ar->winy;
+ y = region->winy;
if (st->flags & ST_SCROLL_SELECT) {
y += st->runtime.scroll_ofs_px[1];
}
@@ -1314,11 +1314,11 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
y -= froml * lheight;
- immRecti(pos, x + fromc * st->runtime.cwidth_px - U.pixelsize, y, ar->winx, y - lheight);
+ immRecti(pos, x + fromc * st->runtime.cwidth_px - U.pixelsize, y, region->winx, y - lheight);
y -= lheight;
for (i = froml + 1; i < tol; i++) {
- immRecti(pos, x - U.pixelsize, y, ar->winx, y - lheight);
+ immRecti(pos, x - U.pixelsize, y, region->winx, y - lheight);
y -= lheight;
}
@@ -1333,19 +1333,25 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
int y1, y2;
if (st->wordwrap) {
- int visible_lines = text_get_visible_lines(st, ar, text->sell->line);
+ int visible_lines = text_get_visible_lines(st, region, text->sell->line);
- wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
+ wrap_offset_in_line(st, region, text->sell, text->selc, &offl, &offc);
- y1 = ar->winy - (vsell - offl) * lheight;
+ y1 = region->winy - (vsell - offl) * lheight;
+ if (st->flags & ST_SCROLL_SELECT) {
+ y1 += st->runtime.scroll_ofs_px[1];
+ }
y2 = y1 - (lheight * visible_lines);
}
else {
- y1 = ar->winy - vsell * lheight;
+ y1 = region->winy - vsell * lheight;
+ if (st->flags & ST_SCROLL_SELECT) {
+ y1 += st->runtime.scroll_ofs_px[1];
+ }
y2 = y1 - (lheight);
}
- if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */
+ if (!(y1 < 0 || y2 > region->winy)) { /* check we need to draw */
float highlight_color[4];
UI_GetThemeColor4fv(TH_TEXT, highlight_color);
highlight_color[3] = 0.1f;
@@ -1353,7 +1359,7 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_blend(true);
- immRecti(pos, 0, y1, ar->winx, y2);
+ immRecti(pos, 0, y1, region->winx, y2);
GPU_blend(false);
}
}
@@ -1361,7 +1367,7 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
if (!hidden) {
/* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */
x = TXT_BODY_LEFT(st) + (vselc * st->runtime.cwidth_px);
- y = ar->winy - vsell * lheight;
+ y = region->winy - vsell * lheight;
if (st->flags & ST_SCROLL_SELECT) {
y += st->runtime.scroll_ofs_px[1];
}
@@ -1390,7 +1396,7 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
/******************* draw matching brackets *********************/
-static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegion *ar)
+static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegion *region)
{
TextLine *startl, *endl, *linep;
Text *text = st->text;
@@ -1515,14 +1521,14 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi
UI_FontThemeColor(tdc->font_id, TH_HILITE);
x = TXT_BODY_LEFT(st);
- y = ar->winy - st->runtime.lheight_px;
+ y = region->winy - st->runtime.lheight_px;
if (st->flags & ST_SCROLL_SELECT) {
y += st->runtime.scroll_ofs_px[1];
}
/* draw opening bracket */
ch = startl->line[startc];
- wrap_offset(st, ar, startl, startc, &offl, &offc);
+ wrap_offset(st, region, startl, startc, &offl, &offc);
viewc = text_get_char_pos(st, startl->line, startc) - st->left + offc;
if (viewc >= 0) {
@@ -1536,7 +1542,7 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi
/* draw closing bracket */
ch = endl->line[endc];
- wrap_offset(st, ar, endl, endc, &offl, &offc);
+ wrap_offset(st, region, endl, endc, &offl, &offc);
viewc = text_get_char_pos(st, endl->line, endc) - st->left + offc;
if (viewc >= 0) {
@@ -1551,7 +1557,7 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi
/*********************** main region drawing *************************/
-void draw_text_main(SpaceText *st, ARegion *ar)
+void draw_text_main(SpaceText *st, ARegion *region)
{
TextDrawContext tdc = {0};
Text *text = st->text;
@@ -1575,12 +1581,12 @@ void draw_text_main(SpaceText *st, ARegion *ar)
const int clip_min_y = -(int)(st->runtime.lheight_px - 1);
st->runtime.viewlines = (st->runtime.lheight_px) ?
- (int)(ar->winy - clip_min_y) / TXT_LINE_HEIGHT(st) :
+ (int)(region->winy - clip_min_y) / TXT_LINE_HEIGHT(st) :
0;
text_draw_context_init(st, &tdc);
- text_update_drawcache(st, ar);
+ text_update_drawcache(st, region);
/* make sure all the positional pointers exist */
if (!text->curl || !text->sell || !text->lines.first || !text->lines.last) {
@@ -1588,7 +1594,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
}
/* update rects for scroll */
- calc_text_rcts(st, ar, &scroll, &back); /* scroll will hold the entire bar size */
+ calc_text_rcts(st, region, &scroll, &back); /* scroll will hold the entire bar size */
/* update syntax formatting if needed */
tft = ED_text_format_get(text);
@@ -1631,7 +1637,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_GRID);
- immRecti(pos, 0, 0, TXT_NUMCOL_WIDTH(st), ar->winy);
+ immRecti(pos, 0, 0, TXT_NUMCOL_WIDTH(st), region->winy);
immUnbindProgram();
}
else {
@@ -1639,17 +1645,17 @@ void draw_text_main(SpaceText *st, ARegion *ar)
}
x = TXT_BODY_LEFT(st);
- y = ar->winy - st->runtime.lheight_px;
+ y = region->winy - st->runtime.lheight_px;
int viewlines = st->runtime.viewlines;
if (st->flags & ST_SCROLL_SELECT) {
y += st->runtime.scroll_ofs_px[1];
viewlines += 1;
}
- winx = ar->winx - TXT_SCROLL_WIDTH;
+ winx = region->winx - TXT_SCROLL_WIDTH;
/* draw cursor, margin, selection and highlight */
- draw_text_decoration(st, ar);
+ draw_text_decoration(st, region);
/* draw the text */
UI_FontThemeColor(tdc.font_id, TH_TEXT);
@@ -1689,7 +1695,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
else {
/* draw unwrapped text */
text_draw(
- st, &tdc, tmp->line, st->left, ar->winx / st->runtime.cwidth_px, x, y, tmp->format);
+ st, &tdc, tmp->line, st->left, region->winx / st->runtime.cwidth_px, x, y, tmp->format);
y -= TXT_LINE_HEIGHT(st);
}
@@ -1707,17 +1713,17 @@ void draw_text_main(SpaceText *st, ARegion *ar)
margin_color[3] = 0.2f;
immUniformColor4fv(margin_color);
GPU_blend(true);
- immRecti(pos, margin_column_x, 0, margin_column_x + U.pixelsize, ar->winy);
+ immRecti(pos, margin_column_x, 0, margin_column_x + U.pixelsize, region->winy);
GPU_blend(false);
immUnbindProgram();
}
}
/* draw other stuff */
- draw_brackets(st, &tdc, ar);
+ draw_brackets(st, &tdc, region);
draw_textscroll(st, &scroll, &back);
- /* draw_documentation(st, ar); - No longer supported */
- draw_suggestion_list(st, &tdc, ar);
+ /* draw_documentation(st, region); - No longer supported */
+ draw_suggestion_list(st, &tdc, region);
text_font_end(&tdc);
}
@@ -1738,10 +1744,10 @@ void text_update_character_width(SpaceText *st)
/* Moves the view to the cursor location,
* also used to make sure the view isn't outside the file */
-void text_scroll_to_cursor(SpaceText *st, ARegion *ar, const bool center)
+void text_scroll_to_cursor(SpaceText *st, ARegion *region, const bool center)
{
Text *text;
- int i, x, winx = ar->winx;
+ int i, x, winx = region->winx;
if (ELEM(NULL, st, st->text, st->text->curl)) {
return;
@@ -1754,7 +1760,7 @@ void text_scroll_to_cursor(SpaceText *st, ARegion *ar, const bool center)
i = txt_get_span(text->lines.first, text->sell);
if (st->wordwrap) {
int offl, offc;
- wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+ wrap_offset(st, region, text->sell, text->selc, &offl, &offc);
i += offl;
}
@@ -1806,34 +1812,34 @@ void text_scroll_to_cursor(SpaceText *st, ARegion *ar, const bool center)
}
/* takes an area instead of a region, use for listeners */
-void text_scroll_to_cursor__area(SpaceText *st, ScrArea *sa, const bool center)
+void text_scroll_to_cursor__area(SpaceText *st, ScrArea *area, const bool center)
{
- ARegion *ar;
+ ARegion *region;
if (ELEM(NULL, st, st->text, st->text->curl)) {
return;
}
- ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
- if (ar) {
- text_scroll_to_cursor(st, ar, center);
+ if (region) {
+ text_scroll_to_cursor(st, region, center);
}
}
void text_update_cursor_moved(bContext *C)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
SpaceText *st = CTX_wm_space_text(C);
- text_scroll_to_cursor__area(st, sa, true);
+ text_scroll_to_cursor__area(st, area, true);
}
/**
* Takes a cursor (row, character) and returns x,y pixel coords.
*/
bool ED_text_region_location_from_cursor(SpaceText *st,
- ARegion *ar,
+ ARegion *region,
const int cursor_co[2],
int r_pixel_co[2])
{
@@ -1853,10 +1859,10 @@ bool ED_text_region_location_from_cursor(SpaceText *st,
/* handle tabs as well! */
int char_pos = text_get_char_pos(st, line->line, cursor_co[1]);
- wrap_offset(st, ar, line, cursor_co[1], &offl, &offc);
+ wrap_offset(st, region, line, cursor_co[1], &offl, &offc);
r_pixel_co[0] = (char_pos + offc - st->left) * st->runtime.cwidth_px + linenr_offset;
r_pixel_co[1] = (cursor_co[0] + offl - st->top) * TXT_LINE_HEIGHT(st);
- r_pixel_co[1] = (ar->winy - (r_pixel_co[1] + (TXT_BODY_LPAD * st->runtime.cwidth_px))) -
+ r_pixel_co[1] = (region->winy - (r_pixel_co[1] + (TXT_BODY_LPAD * st->runtime.cwidth_px))) -
st->runtime.lheight_px;
}
return true;
diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c
index 48ee30e450f..bdbf55d9198 100644
--- a/source/blender/editors/space_text/text_format.c
+++ b/source/blender/editors/space_text/text_format.c
@@ -27,8 +27,8 @@
#include "BLI_blenlib.h"
#include "BLI_string_utils.h"
-#include "DNA_text_types.h"
#include "DNA_space_types.h"
+#include "DNA_text_types.h"
#include "ED_text.h"
@@ -121,7 +121,7 @@ int flatten_string_strlen(FlattenString *fs, const char *str)
/* Ensures the format string for the given line is long enough, reallocating
* as needed. Allocation is done here, alone, to ensure consistency. */
-int text_check_format_len(TextLine *line, unsigned int len)
+int text_check_format_len(TextLine *line, uint len)
{
if (line->format) {
if (strlen(line->format) < len) {
diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c
index 6bbb0d529ab..42a52ce0f58 100644
--- a/source/blender/editors/space_text/text_format_lua.c
+++ b/source/blender/editors/space_text/text_format_lua.c
@@ -21,8 +21,8 @@
#include "BLI_blenlib.h"
-#include "DNA_text_types.h"
#include "DNA_space_types.h"
+#include "DNA_text_types.h"
#include "BKE_text.h"
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index 0275a293e7a..53e38cfe870 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -21,8 +21,8 @@
#include "BLI_blenlib.h"
-#include "DNA_text_types.h"
#include "DNA_space_types.h"
+#include "DNA_text_types.h"
#include "BKE_text.h"
diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c
index 13830aa7c4d..52aaad034bf 100644
--- a/source/blender/editors/space_text/text_format_pov.c
+++ b/source/blender/editors/space_text/text_format_pov.c
@@ -21,8 +21,8 @@
#include "BLI_blenlib.h"
-#include "DNA_text_types.h"
#include "DNA_space_types.h"
+#include "DNA_text_types.h"
#include "BKE_text.h"
diff --git a/source/blender/editors/space_text/text_format_pov_ini.c b/source/blender/editors/space_text/text_format_pov_ini.c
index 08f6d10ac6d..df4f1e6b38c 100644
--- a/source/blender/editors/space_text/text_format_pov_ini.c
+++ b/source/blender/editors/space_text/text_format_pov_ini.c
@@ -21,8 +21,8 @@
#include "BLI_blenlib.h"
-#include "DNA_text_types.h"
#include "DNA_space_types.h"
+#include "DNA_text_types.h"
#include "BKE_text.h"
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 48c522c5e1b..3858f7225ef 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -21,8 +21,8 @@
#include "BLI_blenlib.h"
-#include "DNA_text_types.h"
#include "DNA_space_types.h"
+#include "DNA_text_types.h"
#include "BKE_text.h"
@@ -291,7 +291,7 @@ static int txtfmt_py_literal_numeral(const char *string, char prev_fmt)
}
/* Previous was a number; if immediately followed by '.' it's a floating point decimal number.
* Note: keep the decimal point, it's needed to allow leading zeros. */
- if ((prev_fmt == FMT_TYPE_NUMERAL) && (first == '.')) {
+ if (first == '.') {
return txtfmt_py_find_numeral_inner(string);
}
/* "Imaginary" part of a complex number ends with 'j' */
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index e2d2bb5ed64..c4052fcef84 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -34,32 +34,34 @@
#include "WM_types.h"
+#include "UI_interface.h"
+
#include "text_intern.h"
/* ************************ header area region *********************** */
/************************** properties ******************************/
-static ARegion *text_has_properties_region(ScrArea *sa)
+static ARegion *text_has_properties_region(ScrArea *area)
{
- ARegion *ar, *arnew;
+ ARegion *region, *arnew;
- ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
- if (ar) {
- return ar;
+ region = BKE_area_find_region_type(area, RGN_TYPE_UI);
+ if (region) {
+ return region;
}
/* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ region = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
/* is error! */
- if (ar == NULL) {
+ if (region == NULL) {
return NULL;
}
arnew = MEM_callocN(sizeof(ARegion), "properties region");
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ BLI_insertlinkafter(&area->regionbase, region, arnew);
arnew->regiontype = RGN_TYPE_UI;
arnew->alignment = RGN_ALIGN_LEFT;
@@ -75,20 +77,22 @@ static bool text_properties_poll(bContext *C)
static int text_text_search_exec(bContext *C, wmOperator *UNUSED(op))
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = text_has_properties_region(sa);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = text_has_properties_region(area);
SpaceText *st = CTX_wm_space_text(C);
- if (ar) {
- if (ar->flag & RGN_FLAG_HIDDEN) {
- ED_region_toggle_hidden(C, ar);
+ if (region) {
+ if (region->flag & RGN_FLAG_HIDDEN) {
+ ED_region_toggle_hidden(C, region);
}
+ UI_panel_category_active_set(region, "Text");
+
/* cannot send a button activate yet for case when region wasn't visible yet */
/* flag gets checked and cleared in main draw callback */
st->flags |= ST_FIND_ACTIVATE;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index 1a36b21952b..d6588dda797 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -35,26 +35,26 @@ struct bContext;
struct wmOperatorType;
/* text_draw.c */
-void draw_text_main(struct SpaceText *st, struct ARegion *ar);
+void draw_text_main(struct SpaceText *st, struct ARegion *region);
void text_update_line_edited(struct TextLine *line);
void text_update_edited(struct Text *text);
void text_update_character_width(struct SpaceText *st);
-void text_scroll_to_cursor(struct SpaceText *st, struct ARegion *ar, const bool center);
-void text_scroll_to_cursor__area(struct SpaceText *st, struct ScrArea *sa, const bool center);
+void text_scroll_to_cursor(struct SpaceText *st, struct ARegion *region, const bool center);
+void text_scroll_to_cursor__area(struct SpaceText *st, struct ScrArea *area, const bool center);
void text_update_cursor_moved(struct bContext *C);
/* Padding around line numbers in character widths. */
#define TXT_NUMCOL_PAD 1.0f
/* Total width of the optional line numbers column. */
#define TXT_NUMCOL_WIDTH(st) \
- (st->runtime.cwidth_px * (st->runtime.line_number_display_digits + (2 * TXT_NUMCOL_PAD)))
+ ((st)->runtime.cwidth_px * ((st)->runtime.line_number_display_digits + (2 * TXT_NUMCOL_PAD)))
/* Padding on left of body text in character units. */
#define TXT_BODY_LPAD 1.0f
/* Left position of body text. */
#define TXT_BODY_LEFT(st) \
- (st->showlinenrs ? TXT_NUMCOL_WIDTH(st) : 0) + (TXT_BODY_LPAD * st->runtime.cwidth_px)
+ ((st)->showlinenrs ? TXT_NUMCOL_WIDTH(st) : 0) + (TXT_BODY_LPAD * (st)->runtime.cwidth_px)
#define TXT_SCROLL_WIDTH U.widget_unit
#define TXT_SCROLL_SPACE ((int)(0.1f * U.widget_unit))
@@ -74,15 +74,15 @@ void text_update_cursor_moved(struct bContext *C);
#define TOOL_SUGG_LIST 0x01
#define TOOL_DOCUMENT 0x02
-int wrap_width(const struct SpaceText *st, struct ARegion *ar);
+int wrap_width(const struct SpaceText *st, struct ARegion *region);
void wrap_offset(const struct SpaceText *st,
- struct ARegion *ar,
+ struct ARegion *region,
struct TextLine *linein,
int cursin,
int *offl,
int *offc);
void wrap_offset_in_line(const struct SpaceText *st,
- struct ARegion *ar,
+ struct ARegion *region,
struct TextLine *linep,
int cursin,
int *offl,
@@ -92,15 +92,15 @@ int text_get_char_pos(const struct SpaceText *st, const char *line, int cur);
void text_drawcache_tag_update(struct SpaceText *st, int full);
void text_free_caches(struct SpaceText *st);
-int text_do_suggest_select(struct SpaceText *st, struct ARegion *ar);
+int text_do_suggest_select(struct SpaceText *st, struct ARegion *region);
void text_pop_suggest_list(void);
-int text_get_visible_lines(const struct SpaceText *st, struct ARegion *ar, const char *str);
+int text_get_visible_lines(const struct SpaceText *st, struct ARegion *region, const char *str);
int text_get_span_wrap(const struct SpaceText *st,
- struct ARegion *ar,
+ struct ARegion *region,
struct TextLine *from,
struct TextLine *to);
-int text_get_total_lines(struct SpaceText *st, struct ARegion *ar);
+int text_get_total_lines(struct SpaceText *st, struct ARegion *region);
/* text_ops.c */
enum {
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index eea3e4d7958..fa378954a30 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -21,21 +21,22 @@
* \ingroup sptext
*/
-#include <string.h>
#include <errno.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_text_types.h"
#include "BLI_blenlib.h"
+#include "BLI_math_base.h"
#include "BLT_translation.h"
#include "PIL_time.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_text.h"
@@ -43,9 +44,9 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_text.h"
#include "ED_curve.h"
#include "ED_screen.h"
+#include "ED_text.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -56,10 +57,10 @@
# include "BPY_extern.h"
#endif
-#include "text_intern.h"
#include "text_format.h"
+#include "text_intern.h"
-static void txt_screen_clamp(SpaceText *st, ARegion *ar);
+static void txt_screen_clamp(SpaceText *st, ARegion *region);
/* -------------------------------------------------------------------- */
/** \name Util
@@ -194,13 +195,13 @@ static bool text_region_edit_poll(bContext *C)
{
SpaceText *st = CTX_wm_space_text(C);
Text *text = CTX_data_edit_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
if (!st || !text) {
return 0;
}
- if (!ar || ar->regiontype != RGN_TYPE_WINDOW) {
+ if (!region || region->regiontype != RGN_TYPE_WINDOW) {
return 0;
}
@@ -420,7 +421,7 @@ static int text_reload_exec(bContext *C, wmOperator *op)
{
SpaceText *st = CTX_wm_space_text(C);
Text *text = CTX_data_edit_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* store view & cursor state */
const int orig_top = st->top;
@@ -447,7 +448,7 @@ static int text_reload_exec(bContext *C, wmOperator *op)
/* return to scroll position */
st->top = orig_top;
- txt_screen_clamp(st, ar);
+ txt_screen_clamp(st, region);
/* return cursor */
txt_move_to(text, orig_curl, orig_curc, false);
@@ -819,13 +820,14 @@ static int text_refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUS
{
#ifdef WITH_PYTHON
# if 0
+ Main *bmain = CTX_data_main(C);
Text *text = CTX_data_edit_text(C);
Object *ob;
bConstraint *con;
short update;
/* check all pyconstraints */
- for (ob = CTX_data_main(C)->objects.first; ob; ob = ob->id.next) {
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
update = 0;
if (ob->type == OB_ARMATURE && ob->pose) {
bPoseChannel *pchan;
@@ -1631,12 +1633,13 @@ static const EnumPropertyItem move_type_items[] = {
};
/* get cursor position in line by relative wrapped line and column positions */
-static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int rell, int relc)
+static int text_get_cursor_rel(
+ SpaceText *st, ARegion *region, TextLine *linein, int rell, int relc)
{
int i, j, start, end, max, chop, curs, loop, endj, found, selc;
char ch;
- max = wrap_width(st, ar);
+ max = wrap_width(st, region);
selc = start = endj = curs = found = 0;
end = max;
@@ -1724,17 +1727,17 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int
}
static int cursor_skip_find_line(
- SpaceText *st, ARegion *ar, int lines, TextLine **linep, int *charp, int *rell, int *relc)
+ SpaceText *st, ARegion *region, int lines, TextLine **linep, int *charp, int *rell, int *relc)
{
int offl, offc, visible_lines;
- wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc);
+ wrap_offset_in_line(st, region, *linep, *charp, &offl, &offc);
*relc = text_get_char_pos(st, (*linep)->line, *charp) + offc;
*rell = lines;
/* handle current line */
if (lines > 0) {
- visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
+ visible_lines = text_get_visible_lines(st, region, (*linep)->line);
if (*rell - visible_lines + offl >= 0) {
if (!(*linep)->next) {
@@ -1778,7 +1781,7 @@ static int cursor_skip_find_line(
/* skip lines and find destination line and offsets */
while (*linep) {
- visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
+ visible_lines = text_get_visible_lines(st, region, (*linep)->line);
if (lines < 0) { /* moving top */
if (*rell + visible_lines >= 0) {
@@ -1812,7 +1815,7 @@ static int cursor_skip_find_line(
return 1;
}
-static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, const bool sel)
+static void txt_wrap_move_bol(SpaceText *st, ARegion *region, const bool sel)
{
Text *text = st->text;
TextLine **linep;
@@ -1833,7 +1836,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, const bool sel)
oldc = *charp;
- max = wrap_width(st, ar);
+ max = wrap_width(st, region);
start = endj = 0;
end = max;
@@ -1896,7 +1899,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, const bool sel)
}
}
-static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, const bool sel)
+static void txt_wrap_move_eol(SpaceText *st, ARegion *region, const bool sel)
{
Text *text = st->text;
TextLine **linep;
@@ -1917,7 +1920,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, const bool sel)
oldc = *charp;
- max = wrap_width(st, ar);
+ max = wrap_width(st, region);
start = endj = 0;
end = max;
@@ -1980,7 +1983,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, const bool sel)
}
}
-static void txt_wrap_move_up(SpaceText *st, ARegion *ar, const bool sel)
+static void txt_wrap_move_up(SpaceText *st, ARegion *region, const bool sel)
{
Text *text = st->text;
TextLine **linep;
@@ -1998,18 +2001,18 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, const bool sel)
charp = &text->curc;
}
- wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc);
+ wrap_offset_in_line(st, region, *linep, *charp, &offl, &offc);
col = text_get_char_pos(st, (*linep)->line, *charp) + offc;
if (offl) {
- *charp = text_get_cursor_rel(st, ar, *linep, offl - 1, col);
+ *charp = text_get_cursor_rel(st, region, *linep, offl - 1, col);
}
else {
if ((*linep)->prev) {
int visible_lines;
*linep = (*linep)->prev;
- visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
- *charp = text_get_cursor_rel(st, ar, *linep, visible_lines - 1, col);
+ visible_lines = text_get_visible_lines(st, region, (*linep)->line);
+ *charp = text_get_cursor_rel(st, region, *linep, visible_lines - 1, col);
}
else {
*charp = 0;
@@ -2021,7 +2024,7 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, const bool sel)
}
}
-static void txt_wrap_move_down(SpaceText *st, ARegion *ar, const bool sel)
+static void txt_wrap_move_down(SpaceText *st, ARegion *region, const bool sel)
{
Text *text = st->text;
TextLine **linep;
@@ -2039,16 +2042,16 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, const bool sel)
charp = &text->curc;
}
- wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc);
+ wrap_offset_in_line(st, region, *linep, *charp, &offl, &offc);
col = text_get_char_pos(st, (*linep)->line, *charp) + offc;
- visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
+ visible_lines = text_get_visible_lines(st, region, (*linep)->line);
if (offl < visible_lines - 1) {
- *charp = text_get_cursor_rel(st, ar, *linep, offl + 1, col);
+ *charp = text_get_cursor_rel(st, region, *linep, offl + 1, col);
}
else {
if ((*linep)->next) {
*linep = (*linep)->next;
- *charp = text_get_cursor_rel(st, ar, *linep, 0, col);
+ *charp = text_get_cursor_rel(st, region, *linep, 0, col);
}
else {
*charp = (*linep)->len;
@@ -2066,7 +2069,7 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, const bool sel)
*
* This is to replace screen_skip for PageUp/Down operations.
*/
-static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, const bool sel)
+static void cursor_skip(SpaceText *st, ARegion *region, Text *text, int lines, const bool sel)
{
TextLine **linep;
int *charp;
@@ -2080,12 +2083,12 @@ static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, const
charp = &text->curc;
}
- if (st && ar && st->wordwrap) {
+ if (st && region && st->wordwrap) {
int rell, relc;
/* find line and offsets inside it needed to set cursor position */
- if (cursor_skip_find_line(st, ar, lines, linep, charp, &rell, &relc)) {
- *charp = text_get_cursor_rel(st, ar, *linep, rell, relc);
+ if (cursor_skip_find_line(st, region, lines, linep, charp, &rell, &relc)) {
+ *charp = text_get_cursor_rel(st, region, *linep, rell, relc);
}
}
else {
@@ -2112,11 +2115,11 @@ static int text_move_cursor(bContext *C, int type, bool select)
{
SpaceText *st = CTX_wm_space_text(C);
Text *text = CTX_data_edit_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* ensure we have the right region, it's optional */
- if (ar && ar->regiontype != RGN_TYPE_WINDOW) {
- ar = NULL;
+ if (region && region->regiontype != RGN_TYPE_WINDOW) {
+ region = NULL;
}
switch (type) {
@@ -2124,8 +2127,8 @@ static int text_move_cursor(bContext *C, int type, bool select)
if (!select) {
txt_sel_clear(text);
}
- if (st && st->wordwrap && ar) {
- txt_wrap_move_bol(st, ar, select);
+ if (st && st->wordwrap && region) {
+ txt_wrap_move_bol(st, region, select);
}
else {
txt_move_bol(text, select);
@@ -2136,8 +2139,8 @@ static int text_move_cursor(bContext *C, int type, bool select)
if (!select) {
txt_sel_clear(text);
}
- if (st && st->wordwrap && ar) {
- txt_wrap_move_eol(st, ar, select);
+ if (st && st->wordwrap && region) {
+ txt_wrap_move_eol(st, region, select);
}
else {
txt_move_eol(text, select);
@@ -2187,8 +2190,8 @@ static int text_move_cursor(bContext *C, int type, bool select)
break;
case PREV_LINE:
- if (st && st->wordwrap && ar) {
- txt_wrap_move_up(st, ar, select);
+ if (st && st->wordwrap && region) {
+ txt_wrap_move_up(st, region, select);
}
else {
txt_move_up(text, select);
@@ -2196,8 +2199,8 @@ static int text_move_cursor(bContext *C, int type, bool select)
break;
case NEXT_LINE:
- if (st && st->wordwrap && ar) {
- txt_wrap_move_down(st, ar, select);
+ if (st && st->wordwrap && region) {
+ txt_wrap_move_down(st, region, select);
}
else {
txt_move_down(text, select);
@@ -2206,7 +2209,7 @@ static int text_move_cursor(bContext *C, int type, bool select)
case PREV_PAGE:
if (st) {
- cursor_skip(st, ar, st->text, -st->runtime.viewlines, select);
+ cursor_skip(st, region, st->text, -st->runtime.viewlines, select);
}
else {
cursor_skip(NULL, NULL, text, -10, select);
@@ -2215,7 +2218,7 @@ static int text_move_cursor(bContext *C, int type, bool select)
case NEXT_PAGE:
if (st) {
- cursor_skip(st, ar, st->text, st->runtime.viewlines, select);
+ cursor_skip(st, region, st->text, st->runtime.viewlines, select);
}
else {
cursor_skip(NULL, NULL, text, 10, select);
@@ -2314,7 +2317,7 @@ static int text_jump_exec(bContext *C, wmOperator *op)
static int text_jump_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return WM_operator_props_dialog_popup(C, op, 200, 100);
+ return WM_operator_props_dialog_popup(C, op, 200);
}
void TEXT_OT_jump(wmOperatorType *ot)
@@ -2489,14 +2492,14 @@ void TEXT_OT_overwrite_toggle(wmOperatorType *ot)
/** \name Scroll Operator
* \{ */
-static void txt_screen_clamp(SpaceText *st, ARegion *ar)
+static void txt_screen_clamp(SpaceText *st, ARegion *region)
{
if (st->top <= 0) {
st->top = 0;
}
else {
int last;
- last = text_get_total_lines(st, ar);
+ last = text_get_total_lines(st, region);
last = last - (st->runtime.viewlines / 2);
if (last > 0 && st->top > last) {
st->top = last;
@@ -2505,10 +2508,10 @@ static void txt_screen_clamp(SpaceText *st, ARegion *ar)
}
/* Moves the view vertically by the specified number of lines */
-static void txt_screen_skip(SpaceText *st, ARegion *ar, int lines)
+static void txt_screen_skip(SpaceText *st, ARegion *region, int lines)
{
st->top += lines;
- txt_screen_clamp(st, ar);
+ txt_screen_clamp(st, region);
}
/* quick enum for tsc->zone (scroller handles) */
@@ -2538,13 +2541,14 @@ typedef struct TextScroll {
int ofs_delta_px[2];
} TextScroll;
-static void text_scroll_state_init(TextScroll *tsc, SpaceText *st, ARegion *ar)
+static void text_scroll_state_init(TextScroll *tsc, SpaceText *st, ARegion *region)
{
tsc->state.ofs_init[0] = st->left;
tsc->state.ofs_init[1] = st->top;
tsc->state.ofs_max[0] = INT_MAX;
- tsc->state.ofs_max[1] = text_get_total_lines(st, ar) - (st->runtime.viewlines / 2);
+ tsc->state.ofs_max[1] = max_ii(0,
+ text_get_total_lines(st, region) - (st->runtime.viewlines / 2));
tsc->state.size_px[0] = st->runtime.cwidth_px;
tsc->state.size_px[1] = TXT_LINE_HEIGHT(st);
@@ -2560,7 +2564,7 @@ static bool text_scroll_poll(bContext *C)
static int text_scroll_exec(bContext *C, wmOperator *op)
{
SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
int lines = RNA_int_get(op->ptr, "lines");
@@ -2568,7 +2572,7 @@ static int text_scroll_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- txt_screen_skip(st, ar, lines * U.wheellinescroll);
+ txt_screen_skip(st, region, lines * U.wheellinescroll);
ED_area_tag_redraw(CTX_wm_area(C));
@@ -2687,7 +2691,7 @@ static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
TextScroll *tsc = op->customdata;
SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
switch (event->type) {
case MOUSEMOVE:
@@ -2700,8 +2704,10 @@ static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MIDDLEMOUSE:
if (event->val == KM_RELEASE) {
if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) {
- txt_screen_skip(
- st, ar, st->runtime.viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1));
+ txt_screen_skip(st,
+ region,
+ st->runtime.viewlines *
+ (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1));
ED_area_tag_redraw(CTX_wm_area(C));
}
@@ -2721,7 +2727,7 @@ static void text_scroll_cancel(bContext *C, wmOperator *op)
static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
TextScroll *tsc;
@@ -2733,7 +2739,7 @@ static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
tsc->is_first = true;
tsc->zone = SCROLLHANDLE_BAR;
- text_scroll_state_init(tsc, st, ar);
+ text_scroll_state_init(tsc, st, region);
op->customdata = tsc;
@@ -2794,13 +2800,13 @@ static bool text_region_scroll_poll(bContext *C)
/* same as text_region_edit_poll except it works on libdata too */
SpaceText *st = CTX_wm_space_text(C);
Text *text = CTX_data_edit_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
if (!st || !text) {
return 0;
}
- if (!ar || ar->regiontype != RGN_TYPE_WINDOW) {
+ if (!region || region->regiontype != RGN_TYPE_WINDOW) {
return 0;
}
@@ -2810,7 +2816,7 @@ static bool text_region_scroll_poll(bContext *C)
static int text_scroll_bar_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
TextScroll *tsc;
const int *mval = event->mval;
enum eScrollZone zone = SCROLLHANDLE_INVALID_OUTSIDE;
@@ -2827,7 +2833,7 @@ static int text_scroll_bar_invoke(bContext *C, wmOperator *op, const wmEvent *ev
/* mouse inside scroll handle */
zone = SCROLLHANDLE_BAR;
}
- else if (mval[1] > TXT_SCROLL_SPACE && mval[1] < ar->winy - TXT_SCROLL_SPACE) {
+ else if (mval[1] > TXT_SCROLL_SPACE && mval[1] < region->winy - TXT_SCROLL_SPACE) {
if (mval[1] < st->runtime.scroll_region_handle.ymin) {
zone = SCROLLHANDLE_MIN_OUTSIDE;
}
@@ -2849,12 +2855,12 @@ static int text_scroll_bar_invoke(bContext *C, wmOperator *op, const wmEvent *ev
op->customdata = tsc;
st->flags |= ST_SCROLL_SELECT;
- text_scroll_state_init(tsc, st, ar);
+ text_scroll_state_init(tsc, st, region);
/* jump scroll, works in v2d but needs to be added here too :S */
if (event->type == MIDDLEMOUSE) {
- tsc->mval_prev[0] = ar->winrct.xmin + BLI_rcti_cent_x(&st->runtime.scroll_region_handle);
- tsc->mval_prev[1] = ar->winrct.ymin + BLI_rcti_cent_y(&st->runtime.scroll_region_handle);
+ tsc->mval_prev[0] = region->winrct.xmin + BLI_rcti_cent_x(&st->runtime.scroll_region_handle);
+ tsc->mval_prev[1] = region->winrct.ymin + BLI_rcti_cent_y(&st->runtime.scroll_region_handle);
tsc->is_first = false;
tsc->zone = SCROLLHANDLE_BAR;
@@ -2896,7 +2902,6 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot)
* \{ */
typedef struct SetSelection {
- int selecting;
int selc, sell;
short mval_prev[2];
wmTimer *timer; /* needed for scrolling when mouse at region bounds */
@@ -2941,7 +2946,7 @@ static int flatten_column_to_offset(SpaceText *st, const char *str, int index)
return j;
}
-static TextLine *get_line_pos_wrapped(SpaceText *st, ARegion *ar, int *y)
+static TextLine *get_line_pos_wrapped(SpaceText *st, ARegion *region, int *y)
{
TextLine *linep = st->text->lines.first;
int i, lines;
@@ -2951,7 +2956,7 @@ static TextLine *get_line_pos_wrapped(SpaceText *st, ARegion *ar, int *y)
}
for (i = -st->top; i <= *y && linep; linep = linep->next, i += lines) {
- lines = text_get_visible_lines(st, ar, linep->line);
+ lines = text_get_visible_lines(st, region, linep->line);
if (i + lines > *y) {
/* We found the line matching given vertical 'coordinate',
@@ -2964,15 +2969,15 @@ static TextLine *get_line_pos_wrapped(SpaceText *st, ARegion *ar, int *y)
}
static void text_cursor_set_to_pos_wrapped(
- SpaceText *st, ARegion *ar, int x, int y, const bool sel)
+ SpaceText *st, ARegion *region, int x, int y, const bool sel)
{
Text *text = st->text;
- int max = wrap_width(st, ar); /* column */
- int charp = -1; /* mem */
- bool found = false; /* flags */
+ int max = wrap_width(st, region); /* column */
+ int charp = -1; /* mem */
+ bool found = false; /* flags */
/* Point to line matching given y position, if any. */
- TextLine *linep = get_line_pos_wrapped(st, ar, &y);
+ TextLine *linep = get_line_pos_wrapped(st, region, &y);
if (linep) {
int i = 0, start = 0, end = max; /* column */
@@ -3088,11 +3093,11 @@ static void text_cursor_set_to_pos_wrapped(
}
}
-static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, const bool sel)
+static void text_cursor_set_to_pos(SpaceText *st, ARegion *region, int x, int y, const bool sel)
{
Text *text = st->text;
text_update_character_width(st);
- y = (ar->winy - 2 - y) / TXT_LINE_HEIGHT(st);
+ y = (region->winy - 2 - y) / TXT_LINE_HEIGHT(st);
x -= TXT_BODY_LEFT(st);
if (x < 0) {
@@ -3101,7 +3106,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, con
x = text_pixel_x_to_column(st, x) + st->left;
if (st->wordwrap) {
- text_cursor_set_to_pos_wrapped(st, ar, x, y, sel);
+ text_cursor_set_to_pos_wrapped(st, region, x, y, sel);
}
else {
TextLine **linep;
@@ -3171,24 +3176,25 @@ static void text_cursor_timer_remove(bContext *C, SetSelection *ssel)
static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SetSelection *ssel = op->customdata;
- if (event->mval[1] < 0 || event->mval[1] > ar->winy) {
+ if (event->mval[1] < 0 || event->mval[1] > region->winy) {
text_cursor_timer_ensure(C, ssel);
if (event->type == TIMER) {
- text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
- text_scroll_to_cursor(st, ar, false);
+ text_cursor_set_to_pos(st, region, event->mval[0], event->mval[1], 1);
+ text_scroll_to_cursor(st, region, false);
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
}
}
- else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > ar->winx)) {
+ else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > region->winx)) {
text_cursor_timer_ensure(C, ssel);
if (event->type == TIMER) {
- text_cursor_set_to_pos(st, ar, CLAMPIS(event->mval[0], 0, ar->winx), event->mval[1], 1);
- text_scroll_to_cursor(st, ar, false);
+ text_cursor_set_to_pos(
+ st, region, CLAMPIS(event->mval[0], 0, region->winx), event->mval[1], 1);
+ text_scroll_to_cursor(st, region, false);
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
}
}
@@ -3196,8 +3202,8 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *ev
text_cursor_timer_remove(C, ssel);
if (event->type != TIMER) {
- text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
- text_scroll_to_cursor(st, ar, false);
+ text_cursor_set_to_pos(st, region, event->mval[0], event->mval[1], 1);
+ text_scroll_to_cursor(st, region, false);
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
ssel->mval_prev[0] = event->mval[0];
@@ -3296,11 +3302,11 @@ void TEXT_OT_selection_set(wmOperatorType *ot)
static int text_cursor_set_exec(bContext *C, wmOperator *op)
{
SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
int x = RNA_int_get(op->ptr, "x");
int y = RNA_int_get(op->ptr, "y");
- text_cursor_set_to_pos(st, ar, x, y, 0);
+ text_cursor_set_to_pos(st, region, x, y, 0);
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
@@ -3349,7 +3355,7 @@ static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), const wm
{
SpaceText *st = CTX_wm_space_text(C);
Text *text = CTX_data_edit_text(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
const int *mval = event->mval;
double time;
static int jump_to = 0;
@@ -3363,7 +3369,7 @@ static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), const wm
if (!(mval[0] > 2 &&
mval[0] < (TXT_NUMCOL_WIDTH(st) + (TXT_BODY_LPAD * st->runtime.cwidth_px)) &&
- mval[1] > 2 && mval[1] < ar->winy - 2)) {
+ mval[1] > 2 && mval[1] < region->winy - 2)) {
return OPERATOR_PASS_THROUGH;
}
@@ -3413,7 +3419,7 @@ static int text_insert_exec(bContext *C, wmOperator *op)
char *str;
bool done = false;
size_t i = 0;
- unsigned int code;
+ uint code;
text_drawcache_tag_update(st, 0);
diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c
index 4a628cf70e4..4126f36e44a 100644
--- a/source/blender/editors/space_text/text_undo.c
+++ b/source/blender/editors/space_text/text_undo.c
@@ -18,8 +18,8 @@
* \ingroup sptext
*/
-#include <string.h>
#include <errno.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -33,17 +33,17 @@
#include "PIL_time.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#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"
-#include "ED_text.h"
#include "ED_curve.h"
#include "ED_screen.h"
+#include "ED_text.h"
#include "ED_undo.h"
#include "UI_interface.h"
@@ -52,8 +52,8 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "text_intern.h"
#include "text_format.h"
+#include "text_intern.h"
/* -------------------------------------------------------------------- */
/** \name Implements ED Undo System
diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c
index d62fcf45d68..d06c567988d 100644
--- a/source/blender/editors/space_topbar/space_topbar.c
+++ b/source/blender/editors/space_topbar/space_topbar.c
@@ -21,8 +21,8 @@
* \ingroup sptopbar
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -47,33 +47,33 @@
#include "RNA_access.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
/* ******************** default callbacks for topbar space ***************** */
static SpaceLink *topbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceTopBar *stopbar;
stopbar = MEM_callocN(sizeof(*stopbar), "init topbar");
stopbar->spacetype = SPACE_TOPBAR;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "left aligned header for topbar");
- BLI_addtail(&stopbar->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_TOP;
- ar = MEM_callocN(sizeof(ARegion), "right aligned header for topbar");
- BLI_addtail(&stopbar->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_RIGHT | RGN_SPLIT_PREV;
+ region = MEM_callocN(sizeof(ARegion), "left aligned header for topbar");
+ BLI_addtail(&stopbar->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = RGN_ALIGN_TOP;
+ region = MEM_callocN(sizeof(ARegion), "right aligned header for topbar");
+ BLI_addtail(&stopbar->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = RGN_ALIGN_RIGHT | RGN_SPLIT_PREV;
/* main regions */
- ar = MEM_callocN(sizeof(ARegion), "main region of topbar");
- BLI_addtail(&stopbar->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ region = MEM_callocN(sizeof(ARegion), "main region of topbar");
+ BLI_addtail(&stopbar->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
return (SpaceLink *)stopbar;
}
@@ -84,7 +84,7 @@ static void topbar_free(SpaceLink *UNUSED(sl))
}
/* spacetype; init callback */
-static void topbar_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void topbar_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -121,17 +121,17 @@ static void topbar_keymap(struct wmKeyConfig *UNUSED(keyconf))
}
/* add handlers, stuff you only do once or on area/region changes */
-static void topbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void topbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- if (RGN_ALIGN_ENUM_FROM_MASK(ar->alignment) == RGN_ALIGN_RIGHT) {
- ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+ if (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_RIGHT) {
+ region->flag |= RGN_FLAG_DYNAMIC_SIZE;
}
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
static void topbar_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -139,30 +139,30 @@ static void topbar_main_region_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_WM:
if (wmn->data == ND_HISTORY) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
if (wmn->data == ND_MODE) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_VIEW3D) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_GPENCIL:
if (wmn->data == ND_DATA) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
}
static void topbar_header_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -170,22 +170,22 @@ static void topbar_header_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_WM:
if (wmn->data == ND_JOB) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_INFO) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCREEN:
if (wmn->data == ND_LAYER) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
if (wmn->data == ND_SCENEBROWSE) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -195,13 +195,13 @@ static void topbar_header_region_message_subscribe(const struct bContext *UNUSED
struct WorkSpace *workspace,
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
- struct ScrArea *UNUSED(sa),
- struct ARegion *ar,
+ struct ScrArea *UNUSED(area),
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 731c8a3028e..9eae722d5c8 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -21,8 +21,8 @@
* \ingroup spuserpref
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -47,45 +47,45 @@
static SpaceLink *userpref_new(const ScrArea *area, const Scene *UNUSED(scene))
{
- ARegion *ar;
+ ARegion *region;
SpaceUserPref *spref;
spref = MEM_callocN(sizeof(SpaceUserPref), "inituserpref");
spref->spacetype = SPACE_USERPREF;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for userpref");
+ region = MEM_callocN(sizeof(ARegion), "header for userpref");
- BLI_addtail(&spref->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
+ BLI_addtail(&spref->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
/* Ignore user preference "USER_HEADER_BOTTOM" here (always show bottom for new types). */
- ar->alignment = RGN_ALIGN_BOTTOM;
+ region->alignment = RGN_ALIGN_BOTTOM;
/* navigation region */
- ar = MEM_callocN(sizeof(ARegion), "navigation region for userpref");
+ region = MEM_callocN(sizeof(ARegion), "navigation region for userpref");
- BLI_addtail(&spref->regionbase, ar);
- ar->regiontype = RGN_TYPE_NAV_BAR;
- ar->alignment = RGN_ALIGN_LEFT;
+ BLI_addtail(&spref->regionbase, region);
+ region->regiontype = RGN_TYPE_NAV_BAR;
+ region->alignment = RGN_ALIGN_LEFT;
/* Use smaller size when opened in area like properties editor. */
if (area->winx && area->winx < 3.0f * UI_NAVIGATION_REGION_WIDTH * UI_DPI_FAC) {
- ar->sizex = UI_NARROW_NAVIGATION_REGION_WIDTH;
+ region->sizex = UI_NARROW_NAVIGATION_REGION_WIDTH;
}
/* execution region */
- ar = MEM_callocN(sizeof(ARegion), "execution region for userpref");
+ region = MEM_callocN(sizeof(ARegion), "execution region for userpref");
- BLI_addtail(&spref->regionbase, ar);
- ar->regiontype = RGN_TYPE_EXECUTE;
- ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
- ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+ BLI_addtail(&spref->regionbase, region);
+ region->regiontype = RGN_TYPE_EXECUTE;
+ region->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
+ region->flag |= RGN_FLAG_DYNAMIC_SIZE;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for userpref");
+ region = MEM_callocN(sizeof(ARegion), "main region for userpref");
- BLI_addtail(&spref->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&spref->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
return (SpaceLink *)spref;
}
@@ -97,7 +97,7 @@ static void userpref_free(SpaceLink *UNUSED(sl))
}
/* spacetype; init callback */
-static void userpref_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void userpref_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -111,18 +111,18 @@ static SpaceLink *userpref_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void userpref_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void userpref_main_region_init(wmWindowManager *wm, ARegion *region)
{
/* do not use here, the properties changed in userprefs do a system-wide refresh,
* then scroller jumps back */
- /* ar->v2d.flag &= ~V2D_IS_INITIALISED; */
+ /* region->v2d.flag &= ~V2D_IS_INITIALISED; */
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
}
-static void userpref_main_region_layout(const bContext *C, ARegion *ar)
+static void userpref_main_region_layout(const bContext *C, ARegion *region)
{
char id_lower[64];
const char *contexts[2] = {id_lower, NULL};
@@ -142,7 +142,7 @@ static void userpref_main_region_layout(const bContext *C, ARegion *ar)
}
ED_region_panels_layout_ex(
- C, ar, &ar->type->paneltypes, contexts, U.space_data.section_active, true, NULL);
+ C, region, &region->type->paneltypes, contexts, U.space_data.section_active, true, NULL);
}
static void userpref_operatortypes(void)
@@ -154,39 +154,39 @@ static void userpref_keymap(struct wmKeyConfig *UNUSED(keyconf))
}
/* add handlers, stuff you only do once or on area/region changes */
-static void userpref_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void userpref_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void userpref_header_region_draw(const bContext *C, ARegion *ar)
+static void userpref_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void userpref_navigation_region_init(wmWindowManager *wm, ARegion *ar)
+static void userpref_navigation_region_init(wmWindowManager *wm, ARegion *region)
{
- ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+ region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
}
-static void userpref_navigation_region_draw(const bContext *C, ARegion *ar)
+static void userpref_navigation_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels(C, ar);
+ ED_region_panels(C, region);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void userpref_execute_region_init(wmWindowManager *wm, ARegion *ar)
+static void userpref_execute_region_init(wmWindowManager *wm, ARegion *region)
{
- ED_region_panels_init(wm, ar);
- ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
+ ED_region_panels_init(wm, region);
+ region->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
}
static void userpref_main_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *UNUSED(ar),
+ ScrArea *UNUSED(area),
+ ARegion *UNUSED(region),
wmNotifier *UNUSED(wmn),
const Scene *UNUSED(scene))
{
@@ -194,8 +194,8 @@ static void userpref_main_region_listener(wmWindow *UNUSED(win),
}
static void userpref_header_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *UNUSED(ar),
+ ScrArea *UNUSED(area),
+ ARegion *UNUSED(region),
wmNotifier *UNUSED(wmn),
const Scene *UNUSED(scene))
{
@@ -209,8 +209,8 @@ static void userpref_header_listener(wmWindow *UNUSED(win),
}
static void userpref_navigation_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *UNUSED(ar),
+ ScrArea *UNUSED(area),
+ ARegion *UNUSED(region),
wmNotifier *UNUSED(wmn),
const Scene *UNUSED(scene))
{
@@ -218,8 +218,8 @@ static void userpref_navigation_region_listener(wmWindow *UNUSED(win),
}
static void userpref_execute_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *UNUSED(ar),
+ ScrArea *UNUSED(area),
+ ARegion *UNUSED(region),
wmNotifier *UNUSED(wmn),
const Scene *UNUSED(scene))
{
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 193be7567bc..0ab8f285de9 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -48,7 +48,6 @@ set(SRC
view3d_buttons.c
view3d_camera_control.c
view3d_draw.c
- view3d_draw_legacy.c
view3d_edit.c
view3d_fly.c
view3d_gizmo_armature.c
@@ -99,8 +98,8 @@ if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
-if(WITH_MOD_FLUID)
- add_definitions(-DWITH_FLUID)
+if(WITH_XR_OPENXR)
+ add_definitions(-DWITH_XR_OPENXR)
endif()
blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 2cdfd8039c1..5959052b0ab 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -22,22 +22,22 @@
*/
#include "DNA_mesh_types.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_math.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_global.h"
-
#include "BKE_editmesh.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "GPU_shader.h"
-#include "GPU_immediate.h"
#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_shader.h"
#include "GPU_state.h"
#include "ED_mesh.h"
@@ -87,7 +87,7 @@ static void circball_array_fill(float verts[CIRCLE_RESOL][3],
}
}
-void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos)
+void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], uint pos)
{
float verts[CIRCLE_RESOL][3];
@@ -120,8 +120,9 @@ void ED_draw_object_facemap(Depsgraph *depsgraph,
Mesh *me = ob->data;
{
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- if (ob_eval->runtime.mesh_eval) {
- me = ob_eval->runtime.mesh_eval;
+ Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
+ if (me_eval != NULL) {
+ me = me_eval;
}
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index e2d32181bb3..7fcd881d481 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -21,15 +21,15 @@
* \ingroup spview3d
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
+#include "DNA_defaults.h"
+#include "DNA_gpencil_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_defaults.h"
#include "MEM_guardedalloc.h"
@@ -39,6 +39,7 @@
#include "BKE_context.h"
#include "BKE_curve.h"
+#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_lattice.h"
@@ -50,8 +51,8 @@
#include "BKE_screen.h"
#include "BKE_workspace.h"
-#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "ED_transform.h"
#include "GPU_matrix.h"
@@ -59,9 +60,9 @@
#include "DRW_engine.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -87,11 +88,11 @@ RegionView3D *ED_view3d_context_rv3d(bContext *C)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d == NULL) {
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = BKE_area_find_region_active_win(sa);
- if (ar) {
- rv3d = ar->regiondata;
+ ScrArea *area = CTX_wm_area(C);
+ if (area && area->spacetype == SPACE_VIEW3D) {
+ ARegion *region = BKE_area_find_region_active_win(area);
+ if (region) {
+ rv3d = region->regiondata;
}
}
}
@@ -99,59 +100,77 @@ RegionView3D *ED_view3d_context_rv3d(bContext *C)
}
/* ideally would return an rv3d but in some cases the region is needed too
- * so return that, the caller can then access the ar->regiondata */
-bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
+ * so return that, the caller can then access the region->regiondata */
+bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_region)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
*r_v3d = NULL;
- *r_ar = NULL;
+ *r_region = NULL;
- if (sa && sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = CTX_wm_region(C);
- View3D *v3d = (View3D *)sa->spacedata.first;
+ if (area && area->spacetype == SPACE_VIEW3D) {
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = (View3D *)area->spacedata.first;
- if (ar) {
+ if (region) {
RegionView3D *rv3d;
- if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) &&
- (rv3d->viewlock & RV3D_LOCKED) == 0) {
+ if ((region->regiontype == RGN_TYPE_WINDOW) && (rv3d = region->regiondata) &&
+ (rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) {
*r_v3d = v3d;
- *r_ar = ar;
+ *r_region = region;
return true;
}
else {
- ARegion *ar_unlock_user = NULL;
- ARegion *ar_unlock = NULL;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- /* find the first unlocked rv3d */
- if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) {
- rv3d = ar->regiondata;
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
- ar_unlock = ar;
- if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) {
- ar_unlock_user = ar;
- break;
- }
- }
- }
- }
-
- /* camera/perspective view get priority when the active region is locked */
- if (ar_unlock_user) {
+ if (ED_view3d_area_user_region(area, v3d, r_region)) {
*r_v3d = v3d;
- *r_ar = ar_unlock_user;
return true;
}
+ }
+ }
+ }
- if (ar_unlock) {
- *r_v3d = v3d;
- *r_ar = ar_unlock;
- return true;
+ return false;
+}
+
+/**
+ * Similar to #ED_view3d_context_user_region() but does not use context. Always performs a lookup.
+ * Also works if \a v3d is not the active space.
+ */
+bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion **r_region)
+{
+ RegionView3D *rv3d = NULL;
+ ARegion *region_unlock_user = NULL;
+ ARegion *region_unlock = NULL;
+ const ListBase *region_list = (v3d == area->spacedata.first) ? &area->regionbase :
+ &v3d->regionbase;
+
+ BLI_assert(v3d->spacetype == SPACE_VIEW3D);
+
+ LISTBASE_FOREACH (ARegion *, region, region_list) {
+ /* find the first unlocked rv3d */
+ if (region->regiondata && region->regiontype == RGN_TYPE_WINDOW) {
+ rv3d = region->regiondata;
+ if ((rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) {
+ region_unlock = region;
+ if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) {
+ region_unlock_user = region;
+ break;
}
}
}
}
+ /* camera/perspective view get priority when the active region is locked */
+ if (region_unlock_user) {
+ *r_region = region_unlock_user;
+ return true;
+ }
+
+ if (region_unlock) {
+ *r_region = region_unlock;
+ return true;
+ }
+
return false;
}
@@ -201,16 +220,16 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
}
#endif
-void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
+void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *region)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (rv3d->render_engine) {
#ifdef WITH_PYTHON
BPy_BEGIN_ALLOW_THREADS;
#endif
- WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
+ WM_jobs_kill_type(wm, region, WM_JOB_TYPE_RENDER_PREVIEW);
#ifdef WITH_PYTHON
BPy_END_ALLOW_THREADS;
@@ -219,18 +238,21 @@ void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
RE_engine_free(rv3d->render_engine);
rv3d->render_engine = NULL;
}
+
+ /* A bit overkill but this make sure the viewport is reset completely. (fclem) */
+ WM_draw_region_free(region, false);
}
-void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
+void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *area)
{
wmWindowManager *wm = bmain->wm.first;
if (v3d->shading.type != OB_RENDER) {
- ARegion *ar;
+ ARegion *region;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if ((ar->regiontype == RGN_TYPE_WINDOW) && ar->regiondata) {
- ED_view3d_stop_render_preview(wm, ar);
+ for (region = area->regionbase.first; region; region = region->next) {
+ if ((region->regiontype == RGN_TYPE_WINDOW) && region->regiondata) {
+ ED_view3d_stop_render_preview(wm, region);
break;
}
}
@@ -239,9 +261,9 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
/* ******************** default callbacks for view3d space ***************** */
-static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
+static SpaceLink *view3d_new(const ScrArea *UNUSED(area), const Scene *scene)
{
- ARegion *ar;
+ ARegion *region;
View3D *v3d;
RegionView3D *rv3d;
@@ -252,44 +274,44 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
}
/* tool header */
- ar = MEM_callocN(sizeof(ARegion), "tool header for view3d");
+ region = MEM_callocN(sizeof(ARegion), "tool header for view3d");
- BLI_addtail(&v3d->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOL_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- ar->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
+ BLI_addtail(&v3d->regionbase, region);
+ region->regiontype = RGN_TYPE_TOOL_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ region->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
/* header */
- ar = MEM_callocN(sizeof(ARegion), "header for view3d");
+ region = MEM_callocN(sizeof(ARegion), "header for view3d");
- BLI_addtail(&v3d->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addtail(&v3d->regionbase, region);
+ region->regiontype = RGN_TYPE_HEADER;
+ region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* tool shelf */
- ar = MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
+ region = MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
- BLI_addtail(&v3d->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOLS;
- ar->alignment = RGN_ALIGN_LEFT;
- ar->flag = RGN_FLAG_HIDDEN;
+ BLI_addtail(&v3d->regionbase, region);
+ region->regiontype = RGN_TYPE_TOOLS;
+ region->alignment = RGN_ALIGN_LEFT;
+ region->flag = RGN_FLAG_HIDDEN;
/* buttons/list view */
- ar = MEM_callocN(sizeof(ARegion), "buttons for view3d");
+ region = MEM_callocN(sizeof(ARegion), "buttons for view3d");
- BLI_addtail(&v3d->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_RIGHT;
- ar->flag = RGN_FLAG_HIDDEN;
+ BLI_addtail(&v3d->regionbase, region);
+ region->regiontype = RGN_TYPE_UI;
+ region->alignment = RGN_ALIGN_RIGHT;
+ region->flag = RGN_FLAG_HIDDEN;
/* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for view3d");
+ region = MEM_callocN(sizeof(ARegion), "main region for view3d");
- BLI_addtail(&v3d->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
+ BLI_addtail(&v3d->regionbase, region);
+ region->regiontype = RGN_TYPE_WINDOW;
- ar->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d");
- rv3d = ar->regiondata;
+ region->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d");
+ rv3d = region->regiondata;
rv3d->viewquat[0] = 1.0f;
rv3d->persp = RV3D_PERSP;
rv3d->view = RV3D_VIEW_USER;
@@ -318,7 +340,7 @@ static void view3d_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -333,9 +355,11 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
v3dn->localvd = NULL;
v3dn->runtime.properties_storage = NULL;
}
+ /* Only one View3D is allowed to have this flag! */
+ v3dn->runtime.flag &= ~V3D_RUNTIME_XR_SESSION_ROOT;
v3dn->local_collections_uuid = 0;
- v3dn->flag &= ~V3D_LOCAL_COLLECTIONS;
+ v3dn->flag &= ~(V3D_LOCAL_COLLECTIONS | V3D_XR_SESSION_MIRROR);
if (v3dn->shading.type == OB_RENDER) {
v3dn->shading.type = OB_SOLID;
@@ -353,7 +377,7 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
+static void view3d_main_region_init(wmWindowManager *wm, ARegion *region)
{
ListBase *lb;
wmKeyMap *keymap;
@@ -361,115 +385,125 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
/* object ops. */
/* important to be before Pose keymap since they can both be enabled at once */
- keymap = WM_keymap_ensure(wm->defaultconf, "Face Mask", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Paint Face Mask (Weight, Vertex, Texture)", 0, 0);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
+
+ /* Before 'Pose' so weight paint menus aren't overridden by pose menus. */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint", 0, 0);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
+
+ keymap = WM_keymap_ensure(wm->defaultconf, "Vertex Paint", 0, 0);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
/* pose is not modal, operator poll checks for this */
keymap = WM_keymap_ensure(wm->defaultconf, "Pose", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Object Mode", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
-
- keymap = WM_keymap_ensure(wm->defaultconf, "Vertex Paint", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
-
- keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Sculpt", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Mesh", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
-
- keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Armature", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
-
- keymap = WM_keymap_ensure(wm->defaultconf, "Pose", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Metaball", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Lattice", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Particle", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
/* editfont keymap swallows all... */
keymap = WM_keymap_ensure(wm->defaultconf, "Font", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Object Non-modal", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
/* own keymap, last so modes can override it */
keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "3D View", SPACE_VIEW3D, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
/* add drop boxes */
lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
- WM_event_add_dropbox_handler(&ar->handlers, lb);
+ WM_event_add_dropbox_handler(&region->handlers, lb);
}
-static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
+static void view3d_main_region_exit(wmWindowManager *wm, ARegion *region)
{
- ED_view3d_stop_render_preview(wm, ar);
+ ED_view3d_stop_render_preview(wm, region);
+}
+
+static bool view3d_drop_id_in_main_region_poll(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event,
+ ID_Type id_type)
+{
+ ScrArea *area = CTX_wm_area(C);
+ if (ED_region_overlap_isect_any_xy(area, &event->x)) {
+ return false;
+ }
+ return WM_drag_ID(drag, id_type) != NULL;
}
-static bool view3d_ob_drop_poll(bContext *UNUSED(C),
+static bool view3d_ob_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const wmEvent *event,
+ const char **UNUSED(r_tooltip))
{
- return WM_drag_ID(drag, ID_OB) != NULL;
+ return view3d_drop_id_in_main_region_poll(C, drag, event, ID_OB);
}
-static bool view3d_collection_drop_poll(bContext *UNUSED(C),
+static bool view3d_collection_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const wmEvent *event,
+ const char **UNUSED(r_tooltip))
{
- return WM_drag_ID(drag, ID_GR) != NULL;
+ return view3d_drop_id_in_main_region_poll(C, drag, event, ID_GR);
}
-static bool view3d_mat_drop_poll(bContext *UNUSED(C),
+static bool view3d_mat_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const wmEvent *event,
+ const char **UNUSED(r_tooltip))
{
- return WM_drag_ID(drag, ID_MA) != NULL;
+ return view3d_drop_id_in_main_region_poll(C, drag, event, ID_MA);
}
-static bool view3d_ima_drop_poll(bContext *UNUSED(C),
+static bool view3d_ima_drop_poll(bContext *C,
wmDrag *drag,
- const wmEvent *UNUSED(event),
- const char **UNUSED(tooltip))
+ const wmEvent *event,
+ const char **UNUSED(r_tooltip))
{
+ if (ED_region_overlap_isect_any_xy(CTX_wm_area(C), &event->x)) {
+ return false;
+ }
if (drag->type == WM_DRAG_PATH) {
/* rule might not work? */
return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE));
@@ -494,9 +528,9 @@ static bool view3d_ima_bg_is_camera_view(bContext *C)
static bool view3d_ima_bg_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **tooltip)
+ const char **r_tooltip)
{
- if (!view3d_ima_drop_poll(C, drag, event, tooltip)) {
+ if (!view3d_ima_drop_poll(C, drag, event, r_tooltip)) {
return false;
}
@@ -510,9 +544,9 @@ static bool view3d_ima_bg_drop_poll(bContext *C,
static bool view3d_ima_empty_drop_poll(bContext *C,
wmDrag *drag,
const wmEvent *event,
- const char **tooltip)
+ const char **r_tooltip)
{
- if (!view3d_ima_drop_poll(C, drag, event, tooltip)) {
+ if (!view3d_ima_drop_poll(C, drag, event, r_tooltip)) {
return false;
}
@@ -529,6 +563,14 @@ static bool view3d_ima_empty_drop_poll(bContext *C,
return false;
}
+static bool view3d_volume_drop_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event),
+ const char **UNUSED(r_tooltip))
+{
+ return (drag->type == WM_DRAG_PATH) && (drag->icon == ICON_FILE_VOLUME);
+}
+
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_ID(drag, ID_OB);
@@ -596,6 +638,7 @@ static void view3d_dropboxes(void)
lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(
lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_volume_import", view3d_volume_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb,
"OBJECT_OT_collection_instance_add",
view3d_collection_drop_poll,
@@ -637,9 +680,9 @@ static void view3d_widgets(void)
}
/* type callback, not region itself */
-static void view3d_main_region_free(ARegion *ar)
+static void view3d_main_region_free(ARegion *region)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (rv3d) {
if (rv3d->localvd) {
@@ -664,7 +707,7 @@ static void view3d_main_region_free(ARegion *ar)
}
MEM_freeN(rv3d);
- ar->regiondata = NULL;
+ region->regiondata = NULL;
}
}
@@ -693,11 +736,11 @@ static void *view3d_main_region_duplicate(void *poin)
}
static void view3d_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, wmNotifier *wmn, const Scene *scene)
+ wmWindow *UNUSED(win), ScrArea *area, ARegion *region, wmNotifier *wmn, const Scene *scene)
{
- View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->regiondata;
- wmGizmoMap *gzmap = ar->gizmo_map;
+ View3D *v3d = area->spacedata.first;
+ RegionView3D *rv3d = region->regiondata;
+ wmGizmoMap *gzmap = region->gizmo_map;
/* context changes */
switch (wmn->category) {
@@ -705,22 +748,29 @@ static void view3d_main_region_listener(
if (ELEM(wmn->data, ND_UNDO)) {
WM_gizmomap_tag_refresh(gzmap);
}
+ else if (ELEM(wmn->data, ND_XR_DATA_CHANGED)) {
+ /* Only cause a redraw if this a VR session mirror. Should more features be added that
+ * require redraws, we could pass something to wmn->reference, e.g. the flag value. */
+ if (v3d->flag & V3D_XR_SESSION_MIRROR) {
+ ED_region_tag_redraw(region);
+ }
+ }
break;
case NC_ANIMATION:
switch (wmn->data) {
case ND_KEYFRAME_PROP:
case ND_NLA_ACTCHANGE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_NLA:
case ND_KEYFRAME:
if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case ND_ANIMCHAN:
if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -729,14 +779,14 @@ static void view3d_main_region_listener(
switch (wmn->data) {
case ND_SCENEBROWSE:
case ND_LAYER_CONTENT:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_gizmomap_tag_refresh(gzmap);
break;
case ND_LAYER:
if (wmn->reference) {
BKE_screen_view3d_sync(v3d, wmn->reference);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_gizmomap_tag_refresh(gzmap);
break;
case ND_OB_ACTIVE:
@@ -748,7 +798,7 @@ static void view3d_main_region_listener(
case ND_RENDER_OPTIONS:
case ND_MARKERS:
case ND_MODE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_gizmomap_tag_refresh(gzmap);
break;
case ND_WORLD:
@@ -757,14 +807,14 @@ static void view3d_main_region_listener(
case ND_DRAW_RENDER_VIEWPORT: {
if (v3d->camera && (scene == wmn->reference)) {
if (rv3d->persp == RV3D_CAMOB) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
break;
}
}
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_OBJECT:
@@ -780,13 +830,13 @@ static void view3d_main_region_listener(
case ND_PARTICLE:
case ND_POINTCACHE:
case ND_LOD:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_gizmomap_tag_refresh(gzmap);
break;
}
switch (wmn->action) {
case NA_ADDED:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -797,16 +847,16 @@ static void view3d_main_region_listener(
ATTR_FALLTHROUGH;
}
case ND_DATA:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_gizmomap_tag_refresh(gzmap);
break;
case ND_VERTEX_GROUP:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
switch (wmn->action) {
case NA_EDITED:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -815,7 +865,7 @@ static void view3d_main_region_listener(
case ND_DRAW_RENDER_VIEWPORT: {
if (v3d->camera && (v3d->camera->data == wmn->reference)) {
if (rv3d->persp == RV3D_CAMOB) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
break;
@@ -824,17 +874,17 @@ static void view3d_main_region_listener(
break;
case NC_GROUP:
/* all group ops for now */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_BRUSH:
switch (wmn->action) {
case NA_EDITED:
- ED_region_tag_redraw_overlay(ar);
+ ED_region_tag_redraw_cursor(region);
break;
case NA_SELECTED:
/* used on brush changes - needed because 3d cursor
* has to be drawn if clone brush is selected */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -847,11 +897,11 @@ static void view3d_main_region_listener(
*
* How to solve?
*/
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_SHADING_DRAW:
case ND_SHADING_LINKS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -862,7 +912,7 @@ static void view3d_main_region_listener(
break;
case ND_WORLD:
/* Needed for updating world materials */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -872,29 +922,29 @@ static void view3d_main_region_listener(
/* TODO(sergey): This is a bit too much, but needed to
* handle updates from new depsgraph.
*/
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_LIGHTING_DRAW:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
WM_gizmomap_tag_refresh(gzmap);
break;
}
break;
case NC_LIGHTPROBE:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case NC_IMAGE:
/* this could be more fine grained checks if we had
* more context than just the region */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_TEXTURE:
/* same as above */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_MOVIECLIP:
if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
@@ -902,36 +952,41 @@ static void view3d_main_region_listener(
if (wmn->subtype == NS_VIEW3D_GPU) {
rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
}
- ED_region_tag_redraw(ar);
+#ifdef WITH_XR_OPENXR
+ else if (wmn->subtype == NS_VIEW3D_SHADING) {
+ ED_view3d_xr_shading_update(G_MAIN->wm.first, v3d, scene);
+ }
+#endif
+ ED_region_tag_redraw(region);
WM_gizmomap_tag_refresh(gzmap);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCREEN:
switch (wmn->data) {
case ND_ANIMPLAY:
case ND_SKETCH:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_LAYOUTBROWSE:
case ND_LAYOUTDELETE:
case ND_LAYOUTSET:
WM_gizmomap_tag_refresh(gzmap);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_LAYER:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_GPENCIL:
if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -941,8 +996,8 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
- struct ScrArea *sa,
- struct ARegion *ar,
+ struct ScrArea *area,
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
/* Developer note: there are many properties that impact 3D view drawing,
@@ -973,8 +1028,8 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
};
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -984,7 +1039,7 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
}
/* Subscribe to a handful of other properties. */
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw);
WM_msg_subscribe_rna_anon_prop(
@@ -1023,8 +1078,8 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
{
wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
- .owner = ar,
- .user_data = sa,
+ .owner = region,
+ .user_data = area,
.notify = WM_toolsystem_do_msg_notify_tag_refresh,
};
WM_msg_subscribe_rna_anon_prop(mbus, Object, mode, &msg_sub_value_region_tag_refresh);
@@ -1032,31 +1087,31 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
}
}
-static void view3d_main_region_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
+static void view3d_main_region_cursor(wmWindow *win, ScrArea *area, ARegion *region)
{
- if (!WM_cursor_set_from_tool(win, sa, ar)) {
+ if (!WM_cursor_set_from_tool(win, area, region)) {
WM_cursor_set(win, WM_CURSOR_DEFAULT);
}
}
/* add handlers, stuff you only do once or on area/region changes */
-static void view3d_header_region_init(wmWindowManager *wm, ARegion *ar)
+static void view3d_header_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
- ED_region_header_init(ar);
+ ED_region_header_init(region);
}
-static void view3d_header_region_draw(const bContext *C, ARegion *ar)
+static void view3d_header_region_draw(const bContext *C, ARegion *region)
{
- ED_region_header(C, ar);
+ ED_region_header(C, region);
}
static void view3d_header_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -1073,25 +1128,25 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win),
case ND_TOOLSETTINGS:
case ND_LAYER_CONTENT:
case ND_RENDER_OPTIONS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_VIEW3D) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_GPENCIL:
if (wmn->data & ND_GPENCIL_EDITMODE) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
else if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_BRUSH:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
@@ -1102,22 +1157,22 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win),
switch (wmn->category) {
case NC_WM:
if (wmn->data == ND_HISTORY) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SCENE:
if (wmn->data == ND_MODE) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_VIEW3D) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_GPENCIL:
if (wmn->data == ND_DATA) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -1128,8 +1183,8 @@ static void view3d_header_region_message_subscribe(const struct bContext *UNUSED
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
- struct ScrArea *UNUSED(sa),
- struct ARegion *ar,
+ struct ScrArea *UNUSED(area),
+ struct ARegion *region,
struct wmMsgBus *mbus)
{
wmMsgParams_RNA msg_key_params = {{0}};
@@ -1140,8 +1195,8 @@ static void view3d_header_region_message_subscribe(const struct bContext *UNUSED
};
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
- .owner = ar,
- .user_data = ar,
+ .owner = region,
+ .user_data = region,
.notify = ED_region_do_msg_notify_tag_redraw,
};
@@ -1152,18 +1207,18 @@ static void view3d_header_region_message_subscribe(const struct bContext *UNUSED
}
/* add handlers, stuff you only do once or on area/region changes */
-static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
+static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
void ED_view3d_buttons_region_layout_ex(const bContext *C,
- ARegion *ar,
+ ARegion *region,
const char *category_override)
{
const enum eContextObjectMode mode = CTX_data_mode_enum(C);
@@ -1225,6 +1280,9 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C,
case CTX_MODE_WEIGHT_GPENCIL:
ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
break;
+ case CTX_MODE_VERTEX_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_vertex");
+ break;
default:
break;
}
@@ -1242,11 +1300,14 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C,
case CTX_MODE_EDIT_GPENCIL:
ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
break;
+ case CTX_MODE_VERTEX_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_vertex");
+ break;
default:
break;
}
- ListBase *paneltypes = &ar->type->paneltypes;
+ ListBase *paneltypes = &region->type->paneltypes;
/* Allow drawing 3D view toolbar from non 3D view space type. */
if (category_override != NULL) {
@@ -1256,17 +1317,18 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C,
}
const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, paneltypes, contexts_base, -1, vertical, category_override);
+ ED_region_panels_layout_ex(
+ C, region, paneltypes, contexts_base, -1, vertical, category_override);
}
-static void view3d_buttons_region_layout(const bContext *C, ARegion *ar)
+static void view3d_buttons_region_layout(const bContext *C, ARegion *region)
{
- ED_view3d_buttons_region_layout_ex(C, ar, NULL);
+ ED_view3d_buttons_region_layout_ex(C, region, NULL);
}
static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
- ARegion *ar,
+ ScrArea *UNUSED(area),
+ ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
{
@@ -1276,12 +1338,12 @@ static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_KEYFRAME_PROP:
case ND_NLA_ACTCHANGE:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case ND_NLA:
case ND_KEYFRAME:
if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
}
@@ -1296,12 +1358,12 @@ static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
case ND_LAYER:
case ND_LAYER_CONTENT:
case ND_TOOLSETTINGS:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
switch (wmn->action) {
case NA_EDITED:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -1314,7 +1376,7 @@ static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
case ND_DRAW:
case ND_KEYS:
case ND_MODIFIER:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
break;
@@ -1323,71 +1385,76 @@ static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
case ND_DATA:
case ND_VERTEX_GROUP:
case ND_SELECT:
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
}
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_TEXTURE:
case NC_MATERIAL:
/* for brush textures */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
break;
case NC_BRUSH:
/* NA_SELECTED is used on brush changes */
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_VIEW3D) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_GPENCIL:
if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED)) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
break;
case NC_IMAGE:
/* Update for the image layers in texture paint. */
if (wmn->action == NA_EDITED) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
+ }
+ break;
+ case NC_WM:
+ if (wmn->data == ND_XR_DATA_CHANGED) {
+ ED_region_tag_redraw(region);
}
break;
}
}
/* add handlers, stuff you only do once or on area/region changes */
-static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
+static void view3d_tools_region_init(wmWindowManager *wm, ARegion *region)
{
wmKeyMap *keymap;
- ED_region_panels_init(wm, ar);
+ ED_region_panels_init(wm, region);
keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
}
-static void view3d_tools_region_draw(const bContext *C, ARegion *ar)
+static void view3d_tools_region_draw(const bContext *C, ARegion *region)
{
- ED_region_panels_ex(C, ar, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true);
+ ED_region_panels_ex(C, region, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true);
}
/* area (not region) level listener */
static void space_view3d_listener(wmWindow *UNUSED(win),
- ScrArea *sa,
+ ScrArea *area,
struct wmNotifier *wmn,
Scene *UNUSED(scene))
{
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
/* context changes */
switch (wmn->category) {
@@ -1395,7 +1462,7 @@ static void space_view3d_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_WORLD:
if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
- ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
+ ED_area_tag_redraw_regiontype(area, RGN_TYPE_WINDOW);
}
break;
}
@@ -1405,7 +1472,7 @@ static void space_view3d_listener(wmWindow *UNUSED(win),
case ND_WORLD_DRAW:
case ND_WORLD:
if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) {
- ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
+ ED_area_tag_redraw_regiontype(area, RGN_TYPE_WINDOW);
}
break;
}
@@ -1414,7 +1481,7 @@ static void space_view3d_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_NODES:
if (v3d->shading.type == OB_TEXTURE) {
- ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
+ ED_area_tag_redraw_regiontype(area, RGN_TYPE_WINDOW);
}
break;
}
@@ -1422,10 +1489,10 @@ static void space_view3d_listener(wmWindow *UNUSED(win),
}
}
-static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(sa))
+static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(area))
{
Scene *scene = CTX_data_scene(C);
- LightCache *lcache = scene->eevee.light_cache;
+ LightCache *lcache = scene->eevee.light_cache_data;
if (lcache && (lcache->flag & LIGHTCACHE_UPDATE_AUTO) != 0) {
lcache->flag &= ~LIGHTCACHE_UPDATE_AUTO;
@@ -1480,10 +1547,10 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
return -1; /* found but not available */
}
-static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_id)
+static void view3d_id_remap(ScrArea *area, SpaceLink *slink, ID *old_id, ID *new_id)
{
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
bool is_local = false;
if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) {
@@ -1495,12 +1562,12 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i
v3d->camera = (Object *)new_id;
if (!new_id) {
/* 3D view might be inactive, in that case needs to use slink->regionbase */
- ListBase *regionbase = (slink == sa->spacedata.first) ? &sa->regionbase :
- &slink->regionbase;
- for (ar = regionbase->first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = is_local ? ((RegionView3D *)ar->regiondata)->localvd :
- ar->regiondata;
+ ListBase *regionbase = (slink == area->spacedata.first) ? &area->regionbase :
+ &slink->regionbase;
+ for (region = regionbase->first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = is_local ? ((RegionView3D *)region->regiondata)->localvd :
+ region->regiondata;
if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
rv3d->persp = RV3D_PERSP;
}
@@ -1511,12 +1578,12 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i
/* Values in local-view aren't used, see: T52663 */
if (is_local == false) {
- if ((ID *)v3d->ob_centre == old_id) {
- v3d->ob_centre = (Object *)new_id;
+ if ((ID *)v3d->ob_center == old_id) {
+ v3d->ob_center = (Object *)new_id;
/* Otherwise, bonename may remain valid...
* We could be smart and check this, too? */
if (new_id == NULL) {
- v3d->ob_centre_bone[0] = '\0';
+ v3d->ob_center_bone[0] = '\0';
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 9ab56dba72d..18425b88047 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -21,17 +21,17 @@
* \ingroup spview3d
*/
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
-#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -39,20 +39,20 @@
#include "BLT_translation.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_customdata.h"
-#include "BKE_screen.h"
-#include "BKE_editmesh.h"
#include "BKE_deform.h"
+#include "BKE_editmesh.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "DEG_depsgraph.h"
@@ -62,8 +62,8 @@
#include "RNA_access.h"
#include "ED_armature.h"
-#include "ED_object.h"
#include "ED_mesh.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -1005,7 +1005,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
}
BKE_nurb_test_2d(nu);
- BKE_nurb_handles_test(nu, true); /* test for bezier too */
+ BKE_nurb_handles_test(nu, true, false); /* test for bezier too */
nu = nu->next;
}
@@ -1140,9 +1140,9 @@ static bool view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt))
return false;
}
-static void view3d_panel_vgroup(const bContext *C, Panel *pa)
+static void view3d_panel_vgroup(const bContext *C, Panel *panel)
{
- uiBlock *block = uiLayoutAbsoluteBlock(pa->layout);
+ uiBlock *block = uiLayoutAbsoluteBlock(panel->layout);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = view_layer->basact->object;
@@ -1171,7 +1171,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
UI_block_func_handle_set(block, do_view3d_vgroup_buttons, NULL);
- bcol = uiLayoutColumn(pa->layout, true);
+ bcol = uiLayoutColumn(panel->layout, true);
row = uiLayoutRow(bcol, true); /* The filter button row */
RNA_pointer_create(NULL, &RNA_ToolSettings, ts, &tools_ptr);
@@ -1184,7 +1184,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) {
bool locked = (dg->flag & DG_LOCK_WEIGHT) != 0;
if (vgroup_validmap[i]) {
- MDeformWeight *dw = defvert_find_index(dv, i);
+ MDeformWeight *dw = BKE_defvert_find_index(dv, i);
if (dw) {
int x, xco = 0;
int icon;
@@ -1269,7 +1269,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
yco -= 2;
- col = uiLayoutColumn(pa->layout, true);
+ col = uiLayoutColumn(panel->layout, true);
row = uiLayoutRow(col, true);
ot = WM_operatortype_find("OBJECT_OT_vertex_weight_normalize_active_vertex", 1);
@@ -1555,7 +1555,7 @@ static bool view3d_panel_transform_poll(const bContext *C, PanelType *UNUSED(pt)
return (view_layer->basact != NULL);
}
-static void view3d_panel_transform(const bContext *C, Panel *pa)
+static void view3d_panel_transform(const bContext *C, Panel *panel)
{
uiBlock *block;
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1563,10 +1563,10 @@ static void view3d_panel_transform(const bContext *C, Panel *pa)
Object *obedit = OBEDIT_FROM_OBACT(ob);
uiLayout *col;
- block = uiLayoutGetBlock(pa->layout);
+ block = uiLayoutGetBlock(panel->layout);
UI_block_func_handle_set(block, do_view3d_region_buttons, NULL);
- col = uiLayoutColumn(pa->layout, false);
+ col = uiLayoutColumn(panel->layout, false);
if (ob == obedit) {
if (ob->type == OB_ARMATURE) {
@@ -1591,8 +1591,8 @@ static void view3d_panel_transform(const bContext *C, Panel *pa)
RNA_id_pointer_create(&ob->id, &obptr);
v3d_transform_butsR(col, &obptr);
- /* dimensions and editmode just happen to be the same checks */
- if (OB_TYPE_SUPPORT_EDITMODE(ob->type)) {
+ /* Dimensions and editmode are mostly the same check. */
+ if (OB_TYPE_SUPPORT_EDITMODE(ob->type) || ELEM(ob->type, OB_VOLUME, OB_HAIR, OB_POINTCLOUD)) {
View3D *v3d = CTX_wm_view3d(C);
v3d_object_dimension_buts(NULL, col, v3d, ob);
}
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index 260546738f4..daa3f641404 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -37,9 +37,9 @@
* - updating can optionally keyframe the camera object.
*/
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_camera_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
@@ -89,7 +89,7 @@ typedef struct View3DCameraControl {
/* backup the views quat in case the user cancels flying in non camera mode. */
float rot_backup[4];
- /* remember if were ortho or not, only used for restoring the view if it was a ortho view */
+ /* remember if we're ortho or not, only used for restoring the view if it was a ortho view */
char persp_backup;
/* are we flying an ortho camera in perspective view,
@@ -101,7 +101,7 @@ typedef struct View3DCameraControl {
void *obtfm;
} View3DCameraControl;
-BLI_INLINE Object *view3d_cameracontrol_object(View3DCameraControl *vctrl)
+BLI_INLINE Object *view3d_cameracontrol_object(const View3DCameraControl *vctrl)
{
return vctrl->root_parent ? vctrl->root_parent : vctrl->ctx_v3d->camera;
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index bb605c6cbae..fac378ae104 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -23,22 +23,25 @@
#include <math.h>
+#include "BLI_jitter_2d.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_threads.h"
-#include "BLI_jitter_2d.h"
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
-#include "BKE_scene.h"
#include "BKE_object.h"
#include "BKE_paint.h"
+#include "BKE_scene.h"
#include "BKE_studiolight.h"
#include "BKE_unit.h"
@@ -56,25 +59,29 @@
#include "DNA_windowmanager_types.h"
#include "DRW_engine.h"
+#include "DRW_select_buffer.h"
#include "ED_armature.h"
-#include "ED_keyframing.h"
#include "ED_gpencil.h"
+#include "ED_info.h"
+#include "ED_keyframing.h"
#include "ED_screen.h"
+#include "ED_screen_types.h"
#include "ED_transform.h"
+#include "ED_view3d_offscreen.h"
#include "DEG_depsgraph_query.h"
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
#include "GPU_draw.h"
-#include "GPU_matrix.h"
+#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_material.h"
-#include "GPU_viewport.h"
+#include "GPU_matrix.h"
#include "GPU_state.h"
-#include "GPU_framebuffer.h"
+#include "GPU_viewport.h"
#include "MEM_guardedalloc.h"
@@ -93,6 +100,10 @@
#include "view3d_intern.h" /* own include */
+#define M_GOLDEN_RATIO_CONJUGATE 0.618033988749895f
+
+#define VIEW3D_OVERLAY_LINEHEIGHT (0.9f * U.widget_unit)
+
/* -------------------------------------------------------------------- */
/** \name General Functions
* \{ */
@@ -101,22 +112,22 @@
* \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
*/
void ED_view3d_update_viewmat(Depsgraph *depsgraph,
- Scene *scene,
+ const Scene *scene,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
float viewmat[4][4],
float winmat[4][4],
const rcti *rect,
bool offscreen)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
/* setup window matrices */
if (winmat) {
copy_m4_m4(rv3d->winmat, winmat);
}
else {
- view3d_winmatrix_set(depsgraph, ar, v3d, rect);
+ view3d_winmatrix_set(depsgraph, region, v3d, rect);
}
/* setup view matrix */
@@ -126,8 +137,8 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
else {
float rect_scale[2];
if (rect) {
- rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)ar->winx;
- rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)ar->winy;
+ rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)region->winx;
+ rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)region->winy;
}
/* note: calls BKE_object_where_is_calc for camera... */
view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : NULL);
@@ -142,12 +153,12 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
/* store window coordinates scaling/offset */
if (!offscreen && rv3d->persp == RV3D_CAMOB && v3d->camera) {
rctf cameraborder;
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &cameraborder, false);
- rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
- rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &cameraborder, false);
+ rv3d->viewcamtexcofac[0] = (float)region->winx / BLI_rctf_size_x(&cameraborder);
+ rv3d->viewcamtexcofac[1] = (float)region->winy / BLI_rctf_size_y(&cameraborder);
- rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
- rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
+ rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)region->winx;
+ rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)region->winy;
}
else {
rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
@@ -175,7 +186,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
len_sc = (float)max_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
}
else {
- len_sc = (float)MAX2(ar->winx, ar->winy);
+ len_sc = (float)MAX2(region->winx, region->winy);
}
rv3d->pixsize = len_px / len_sc;
@@ -185,14 +196,14 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
static void view3d_main_region_setup_view(Depsgraph *depsgraph,
Scene *scene,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
float viewmat[4][4],
float winmat[4][4],
const rcti *rect)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect, false);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, region, viewmat, winmat, rect, false);
/* set for opengl */
GPU_matrix_projection_set(rv3d->winmat);
@@ -200,21 +211,24 @@ static void view3d_main_region_setup_view(Depsgraph *depsgraph,
}
static void view3d_main_region_setup_offscreen(Depsgraph *depsgraph,
- Scene *scene,
+ const Scene *scene,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
float viewmat[4][4],
float winmat[4][4])
{
- RegionView3D *rv3d = ar->regiondata;
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, NULL, true);
+ RegionView3D *rv3d = region->regiondata;
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, region, viewmat, winmat, NULL, true);
/* set for opengl */
GPU_matrix_projection_set(rv3d->winmat);
GPU_matrix_set(rv3d->viewmat);
}
-static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
+static bool view3d_stereo3d_active(wmWindow *win,
+ const Scene *scene,
+ View3D *v3d,
+ RegionView3D *rv3d)
{
if ((scene->r.scemode & R_MULTIVIEW) == 0) {
return false;
@@ -256,7 +270,7 @@ static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, Reg
* view3d)main_region_setup_view() code to account for that.
*/
static void view3d_stereo3d_setup(
- Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect)
+ Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *region, const rcti *rect)
{
bool is_left;
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
@@ -285,7 +299,7 @@ static void view3d_stereo3d_setup(
data_eval->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, region, viewmat, NULL, rect);
data_eval->shiftx = shiftx;
BLI_thread_unlock(LOCK_VIEW3D);
@@ -299,34 +313,69 @@ static void view3d_stereo3d_setup(
v3d->camera = camera;
BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, region, viewmat, NULL, rect);
v3d->camera = view_ob;
BLI_thread_unlock(LOCK_VIEW3D);
}
}
+#ifdef WITH_XR_OPENXR
+static void view3d_xr_mirror_setup(const wmWindowManager *wm,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ ARegion *region,
+ const rcti *rect)
+{
+ RegionView3D *rv3d = region->regiondata;
+ float viewmat[4][4];
+ const float lens_old = v3d->lens;
+
+ if (!WM_xr_session_state_viewer_pose_matrix_info_get(&wm->xr, viewmat, &v3d->lens)) {
+ /* Can't get info from XR session, use fallback values. */
+ copy_m4_m4(viewmat, rv3d->viewmat);
+ v3d->lens = lens_old;
+ }
+ view3d_main_region_setup_view(depsgraph, scene, v3d, region, viewmat, NULL, rect);
+
+ /* Reset overridden View3D data */
+ v3d->lens = lens_old;
+}
+#endif /* WITH_XR_OPENXR */
+
/**
* Set the correct matrices
*/
-void ED_view3d_draw_setup_view(wmWindow *win,
+void ED_view3d_draw_setup_view(const wmWindowManager *wm,
+ wmWindow *win,
Depsgraph *depsgraph,
Scene *scene,
- ARegion *ar,
+ ARegion *region,
View3D *v3d,
float viewmat[4][4],
float winmat[4][4],
const rcti *rect)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
+#ifdef WITH_XR_OPENXR
/* Setup the view matrix. */
- if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
- view3d_stereo3d_setup(depsgraph, scene, v3d, ar, rect);
+ if (ED_view3d_is_region_xr_mirror_active(wm, v3d, region)) {
+ view3d_xr_mirror_setup(wm, depsgraph, scene, v3d, region, rect);
+ }
+ else
+#endif
+ if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
+ view3d_stereo3d_setup(depsgraph, scene, v3d, region, rect);
}
else {
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, rect);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, region, viewmat, winmat, rect);
}
+
+#ifndef WITH_XR_OPENXR
+ UNUSED_VARS(wm);
+#endif
}
/** \} */
@@ -337,7 +386,7 @@ void ED_view3d_draw_setup_view(wmWindow *win,
static void view3d_camera_border(const Scene *scene,
struct Depsgraph *depsgraph,
- const ARegion *ar,
+ const ARegion *region,
const View3D *v3d,
const RegionView3D *rv3d,
rctf *r_viewborder,
@@ -354,7 +403,7 @@ static void view3d_camera_border(const Scene *scene,
if (no_zoom) {
params.zoom = 1.0f;
}
- BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
+ BKE_camera_params_compute_viewplane(&params, region->winx, region->winy, 1.0f, 1.0f);
rect_view = params.viewplane;
/* get camera viewplane */
@@ -373,38 +422,38 @@ static void view3d_camera_border(const Scene *scene,
/* get camera border within viewport */
r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) *
- ar->winx;
+ region->winx;
r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) *
- ar->winx;
+ region->winx;
r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) *
- ar->winy;
+ region->winy;
r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) *
- ar->winy;
+ region->winy;
}
void ED_view3d_calc_camera_border_size(const Scene *scene,
Depsgraph *depsgraph,
- const ARegion *ar,
+ const ARegion *region,
const View3D *v3d,
const RegionView3D *rv3d,
float r_size[2])
{
rctf viewborder;
- view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, true, true);
+ view3d_camera_border(scene, depsgraph, region, v3d, rv3d, &viewborder, true, true);
r_size[0] = BLI_rctf_size_x(&viewborder);
r_size[1] = BLI_rctf_size_y(&viewborder);
}
void ED_view3d_calc_camera_border(const Scene *scene,
Depsgraph *depsgraph,
- const ARegion *ar,
+ const ARegion *region,
const View3D *v3d,
const RegionView3D *rv3d,
rctf *r_viewborder,
const bool no_shift)
{
- view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, r_viewborder, no_shift, false);
+ view3d_camera_border(scene, depsgraph, region, v3d, rv3d, r_viewborder, no_shift, false);
}
static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, float y2, float fac)
@@ -445,7 +494,7 @@ static void drawviewborder_triangle(
if (w > h) {
if (golden) {
- ofs = w * (1.0f - (1.0f / 1.61803399f));
+ ofs = w * (1.0f - M_GOLDEN_RATIO_CONJUGATE);
}
else {
ofs = h * (h / w);
@@ -465,7 +514,7 @@ static void drawviewborder_triangle(
}
else {
if (golden) {
- ofs = h * (1.0f - (1.0f / 1.61803399f));
+ ofs = h * (1.0f - M_GOLDEN_RATIO_CONJUGATE);
}
else {
ofs = w * (w / h);
@@ -487,14 +536,14 @@ static void drawviewborder_triangle(
immEnd();
}
-static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
+static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, View3D *v3d)
{
float x1, x2, y1, y2;
float x1i, x2i, y1i, y2i;
rctf viewborder;
Camera *ca = NULL;
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (v3d->camera == NULL) {
return;
@@ -503,7 +552,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
ca = v3d->camera->data;
}
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &viewborder, false);
/* the offsets */
x1 = viewborder.xmin;
y1 = viewborder.ymin;
@@ -533,8 +582,8 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
/* passepartout, specified in camera edit buttons */
if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) {
- const float winx = (ar->winx + 1);
- const float winy = (ar->winy + 1);
+ const float winx = (region->winx + 1);
+ const float winy = (region->winy + 1);
float alpha = 1.0f;
@@ -563,7 +612,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
GPU_blend(false);
}
- immUniformThemeColor(TH_BACK);
+ immUniformThemeColor3(TH_BACK);
imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
#ifdef VIEW3D_CAMERA_BORDER_HACK
@@ -600,7 +649,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
imm_draw_box_wire_2d(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1);
}
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor3(TH_VIEW_OVERLAY);
imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
}
@@ -655,7 +704,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
}
if (ca->dtx & CAM_DTX_GOLDEN) {
- drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
+ drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - M_GOLDEN_RATIO_CONJUGATE);
}
if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
@@ -745,7 +794,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View
}
}
-static void drawrenderborder(ARegion *ar, View3D *v3d)
+static void drawrenderborder(ARegion *region, View3D *v3d)
{
/* use the same program for everything */
uint shdr_pos = GPU_vertformat_attr_add(
@@ -765,19 +814,19 @@ static void drawrenderborder(ARegion *ar, View3D *v3d)
immUniform1f("dash_factor", 0.5f);
imm_draw_box_wire_2d(shdr_pos,
- v3d->render_border.xmin * ar->winx,
- v3d->render_border.ymin * ar->winy,
- v3d->render_border.xmax * ar->winx,
- v3d->render_border.ymax * ar->winy);
+ v3d->render_border.xmin * region->winx,
+ v3d->render_border.ymin * region->winy,
+ v3d->render_border.xmax * region->winx,
+ v3d->render_border.ymax * region->winy);
immUnbindProgram();
}
-void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool alphaoverride)
+void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bool alphaoverride)
{
struct bThemeState theme_state;
Scene *scene = DEG_get_evaluated_scene(depsgraph);
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
short flag = v3d->flag;
float glalphaclip = U.glalphaclip;
@@ -792,7 +841,8 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool a
UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
- ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL);
+ ED_view3d_draw_setup_view(
+ G_MAIN->wm.first, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL);
GPU_clear(GPU_DEPTH_BIT);
@@ -805,17 +855,17 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool a
GPU_depth_test(true);
/* Needed in cases the view-port isn't already setup. */
- WM_draw_region_viewport_ensure(ar, SPACE_VIEW3D);
- WM_draw_region_viewport_bind(ar);
+ WM_draw_region_viewport_ensure(region, SPACE_VIEW3D);
+ WM_draw_region_viewport_bind(region);
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
/* 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, false);
+ DRW_draw_depth_loop(depsgraph, region, v3d, viewport, false);
}
- WM_draw_region_viewport_unbind(ar);
+ WM_draw_region_viewport_unbind(region);
if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
ED_view3d_clipping_disable();
@@ -834,7 +884,7 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool a
/* ******************** other elements ***************** */
/** could move this elsewhere, but tied into #ED_view3d_grid_scale */
-float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
+float ED_scene_grid_scale(const Scene *scene, const char **r_grid_unit)
{
/* apply units */
if (scene->unit.system) {
@@ -845,8 +895,8 @@ float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
if (usys) {
int i = bUnit_GetBaseUnit(usys);
- if (grid_unit) {
- *grid_unit = bUnit_GetNameDisplay(usys, i);
+ if (r_grid_unit) {
+ *r_grid_unit = bUnit_GetNameDisplay(usys, i);
}
return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
}
@@ -855,13 +905,13 @@ float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
return 1.0f;
}
-float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
+float ED_view3d_grid_scale(const Scene *scene, View3D *v3d, const char **r_grid_unit)
{
- return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
+ return v3d->grid * ED_scene_grid_scale(scene, r_grid_unit);
}
#define STEPS_LEN 8
-void ED_view3d_grid_steps(Scene *scene,
+void ED_view3d_grid_steps(const Scene *scene,
View3D *v3d,
RegionView3D *rv3d,
float r_grid_steps[STEPS_LEN])
@@ -870,6 +920,7 @@ void ED_view3d_grid_steps(Scene *scene,
int i, len;
bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
float grid_scale = v3d->grid;
+ BLI_assert(STEPS_LEN >= len);
if (usys) {
if (rv3d->view == RV3D_VIEW_USER) {
@@ -903,7 +954,6 @@ void ED_view3d_grid_steps(Scene *scene,
}
}
}
-#undef STEPS_LEN
/* Simulates the grid scale that is actually viewed.
* The actual code is seen in `object_grid_frag.glsl` (see `grid_res`).
@@ -911,7 +961,7 @@ void ED_view3d_grid_steps(Scene *scene,
float ED_view3d_grid_view_scale(Scene *scene,
View3D *v3d,
RegionView3D *rv3d,
- const char **grid_unit)
+ const char **r_grid_unit)
{
float grid_scale;
if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
@@ -919,33 +969,36 @@ float ED_view3d_grid_view_scale(Scene *scene,
/* `0.38` was a value visually obtained in order to get a snap distance
* that matches previous versions Blender.*/
float min_dist = 0.38f * (rv3d->dist / v3d->lens);
- float grid_steps[8];
+ float grid_steps[STEPS_LEN];
ED_view3d_grid_steps(scene, v3d, rv3d, grid_steps);
+ /* Skip last item, in case the 'mid_dist' is greater than the largest unit. */
int i;
- for (i = 0; i < ARRAY_SIZE(grid_steps); i++) {
+ for (i = 0; i < ARRAY_SIZE(grid_steps) - 1; i++) {
grid_scale = grid_steps[i];
if (grid_scale > min_dist) {
break;
}
}
- if (grid_unit) {
+ if (r_grid_unit) {
const void *usys;
int len;
bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
if (usys) {
- *grid_unit = bUnit_GetNameDisplay(usys, len - i - 1);
+ *r_grid_unit = bUnit_GetNameDisplay(usys, len - i - 1);
}
}
}
else {
- grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+ grid_scale = ED_view3d_grid_scale(scene, v3d, r_grid_unit);
}
return grid_scale;
}
+#undef STEPS_LEN
+
static void draw_view_axis(RegionView3D *rv3d, const rcti *rect)
{
const float k = U.rvisize * U.pixelsize; /* axis size */
@@ -1129,18 +1182,18 @@ static void draw_rotation_guide(const RegionView3D *rv3d)
/**
* Render and camera border
*/
-static void view3d_draw_border(const bContext *C, ARegion *ar)
+static void view3d_draw_border(const bContext *C, ARegion *region)
{
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
View3D *v3d = CTX_wm_view3d(C);
if (rv3d->persp == RV3D_CAMOB) {
- drawviewborder(scene, depsgraph, ar, v3d);
+ drawviewborder(scene, depsgraph, region, v3d);
}
else if (v3d->flag2 & V3D_RENDER_BORDER) {
- drawrenderborder(ar, v3d);
+ drawrenderborder(region, v3d);
}
}
@@ -1244,37 +1297,56 @@ static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
return name;
}
-static void draw_viewport_name(ARegion *ar, View3D *v3d, int xoffset, int *yoffset)
+static void draw_viewport_name(ARegion *region, View3D *v3d, int xoffset, int *yoffset)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
const char *name = view3d_get_name(v3d, rv3d);
+ const char *name_array[3] = {name, NULL, NULL};
+ int name_array_len = 1;
const int font_id = BLF_default();
+ /* 6 is the maximum size of the axis roll text. */
/* increase size for unicode languages (Chinese in utf-8...) */
#ifdef WITH_INTERNATIONAL
- char tmpstr[96];
+ char tmpstr[96 + 6];
#else
- char tmpstr[32];
+ char tmpstr[32 + 6];
#endif
BLF_enable(font_id, BLF_SHADOW);
BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
BLF_shadow_offset(font_id, 1, -1);
+ if (RV3D_VIEW_IS_AXIS(rv3d->view) && (rv3d->view_axis_roll != RV3D_VIEW_AXIS_ROLL_0)) {
+ const char *axis_roll;
+ switch (rv3d->view_axis_roll) {
+ case RV3D_VIEW_AXIS_ROLL_90:
+ axis_roll = " 90\xC2\xB0";
+ break;
+ case RV3D_VIEW_AXIS_ROLL_180:
+ axis_roll = " 180\xC2\xB0";
+ break;
+ default:
+ axis_roll = " -90\xC2\xB0";
+ break;
+ }
+ name_array[name_array_len++] = axis_roll;
+ }
+
if (v3d->localvd) {
- BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
+ name_array[name_array_len++] = IFACE_(" (Local)");
+ }
+
+ if (name_array_len > 1) {
+ BLI_string_join_array(tmpstr, sizeof(tmpstr), name_array, name_array_len);
name = tmpstr;
}
UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
- *yoffset -= U.widget_unit;
+ *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT;
-#ifdef WITH_INTERNATIONAL
BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr));
-#else
- BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr));
-#endif
BLF_disable(font_id, BLF_SHADOW);
}
@@ -1404,7 +1476,7 @@ static void draw_selected_name(
BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
BLF_shadow_offset(font_id, 1, -1);
- *yoffset -= U.widget_unit;
+ *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT;
BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info));
BLF_disable(font_id, BLF_SHADOW);
@@ -1425,7 +1497,7 @@ static void draw_grid_unit_name(
BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
}
- *yoffset -= U.widget_unit;
+ *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT;
BLF_enable(font_id, BLF_SHADOW);
BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
BLF_shadow_offset(font_id, 1, -1);
@@ -1440,15 +1512,17 @@ static void draw_grid_unit_name(
/**
* Information drawn on top of the solid plates and composed data
*/
-void view3d_draw_region_info(const bContext *C, ARegion *ar)
+void view3d_draw_region_info(const bContext *C, ARegion *region)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
#ifdef WITH_INPUT_NDOF
- if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) &&
+ if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) &&
(rv3d->persp != RV3D_CAMOB)) {
/* TODO: draw something else (but not this) during fly mode */
draw_rotation_guide(rv3d);
@@ -1456,12 +1530,12 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar)
#endif
/* correct projection matrix */
- ED_region_pixelspace(ar);
+ ED_region_pixelspace(region);
/* local coordinate visible rect inside region, to accommodate overlapping ui */
- const rcti *rect = ED_region_visible_rect(ar);
+ const rcti *rect = ED_region_visible_rect(region);
- view3d_draw_border(C, ar);
+ view3d_draw_border(C, region);
view3d_draw_grease_pencil(C);
BLF_batch_draw_begin();
@@ -1481,19 +1555,18 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar)
}
}
- int xoffset = rect->xmin + U.widget_unit;
- int yoffset = rect->ymax;
+ int xoffset = rect->xmin + (0.5f * U.widget_unit);
+ int yoffset = rect->ymax - (0.1f * U.widget_unit);
if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) {
if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
ED_scene_draw_fps(scene, xoffset, &yoffset);
}
else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
- draw_viewport_name(ar, v3d, xoffset, &yoffset);
+ draw_viewport_name(region, v3d, xoffset, &yoffset);
}
if (U.uiflag & USER_DRAWVIEWINFO) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
draw_selected_name(scene, view_layer, ob, xoffset, &yoffset);
}
@@ -1502,10 +1575,12 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar)
/* draw below the viewport name */
draw_grid_unit_name(scene, rv3d, v3d, xoffset, &yoffset);
}
+
+ DRW_draw_region_engine_info(xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT);
}
- if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) {
- DRW_draw_region_engine_info(xoffset, yoffset);
+ if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_STATS)) {
+ ED_info_draw_stats(bmain, scene, view_layer, xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT);
}
BLF_batch_draw_end();
@@ -1517,12 +1592,13 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar)
/** \name Draw Viewport Contents
* \{ */
-static void view3d_draw_view(const bContext *C, ARegion *ar)
+static void view3d_draw_view(const bContext *C, ARegion *region)
{
- ED_view3d_draw_setup_view(CTX_wm_window(C),
+ ED_view3d_draw_setup_view(CTX_wm_manager(C),
+ CTX_wm_window(C),
CTX_data_expect_evaluated_depsgraph(C),
CTX_data_scene(C),
- ar,
+ region,
CTX_wm_view3d(C),
NULL,
NULL,
@@ -1532,7 +1608,7 @@ static void view3d_draw_view(const bContext *C, ARegion *ar)
DRW_draw_view(C);
}
-RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype)
+RenderEngineType *ED_view3d_engine_type(const Scene *scene, int drawtype)
{
/*
* Temporary viewport draw modes until we have a proper system.
@@ -1548,12 +1624,12 @@ RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype)
}
}
-void view3d_main_region_draw(const bContext *C, ARegion *ar)
+void view3d_main_region_draw(const bContext *C, ARegion *region)
{
Main *bmain = CTX_data_main(C);
View3D *v3d = CTX_wm_view3d(C);
- view3d_draw_view(C, ar);
+ view3d_draw_view(C, region);
DRW_cache_free_old_batches(bmain);
GPU_free_images_old(bmain);
@@ -1576,9 +1652,9 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
* \{ */
static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph,
- Scene *scene,
+ const Scene *scene,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
float winmat[4][4],
const char *viewname)
{
@@ -1588,26 +1664,27 @@ static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph,
const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat);
+ view3d_main_region_setup_offscreen(depsgraph, scene, v3d, region, viewmat, winmat);
}
else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
float viewmat[4][4];
Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat);
+ view3d_main_region_setup_offscreen(depsgraph, scene, v3d, region, viewmat, winmat);
}
}
void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
- Scene *scene,
- int drawtype,
+ const Scene *scene,
+ eDrawType drawtype,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
int winx,
int winy,
float viewmat[4][4],
float winmat[4][4],
+ bool is_image_render,
bool do_sky,
bool UNUSED(is_persp),
const char *viewname,
@@ -1615,20 +1692,20 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
GPUOffScreen *ofs,
GPUViewport *viewport)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
RenderEngineType *engine_type = ED_view3d_engine_type(scene, drawtype);
/* set temporary new size */
- int bwinx = ar->winx;
- int bwiny = ar->winy;
- rcti brect = ar->winrct;
+ int bwinx = region->winx;
+ int bwiny = region->winy;
+ rcti brect = region->winrct;
- ar->winx = winx;
- ar->winy = winy;
- ar->winrct.xmin = 0;
- ar->winrct.ymin = 0;
- ar->winrct.xmax = winx;
- ar->winrct.ymax = winy;
+ region->winx = winx;
+ region->winy = winy;
+ region->winrct.xmin = 0;
+ region->winrct.ymin = 0;
+ region->winrct.xmax = winx;
+ region->winrct.ymax = winy;
struct bThemeState theme_state;
UI_Theme_Store(&theme_state);
@@ -1650,20 +1727,27 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) &&
rv3d->persp == RV3D_CAMOB && v3d->camera) {
- view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname);
+ view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, region, winmat, viewname);
}
else {
- view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat);
+ view3d_main_region_setup_offscreen(depsgraph, scene, v3d, region, viewmat, winmat);
}
/* main drawing call */
- DRW_draw_render_loop_offscreen(
- depsgraph, engine_type, ar, v3d, do_sky, do_color_management, ofs, viewport);
+ DRW_draw_render_loop_offscreen(depsgraph,
+ engine_type,
+ region,
+ v3d,
+ is_image_render,
+ do_sky,
+ do_color_management,
+ ofs,
+ viewport);
/* restore size */
- ar->winx = bwinx;
- ar->winy = bwiny;
- ar->winrct = brect;
+ region->winx = bwinx;
+ region->winy = bwiny;
+ region->winrct = brect;
GPU_matrix_pop_projection();
GPU_matrix_pop();
@@ -1674,6 +1758,94 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
}
/**
+ * Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen). Similar too
+ * #ED_view_draw_offscreen_imbuf_simple, but takes view/projection matrices as arguments.
+ */
+void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
+ Scene *scene,
+ View3DShading *shading_override,
+ int drawtype,
+ int winx,
+ int winy,
+ uint draw_flags,
+ float viewmat[4][4],
+ float winmat[4][4],
+ float clip_start,
+ float clip_end,
+ bool is_image_render,
+ bool do_sky,
+ bool is_persp,
+ const char *viewname,
+ const bool do_color_management,
+ GPUOffScreen *ofs,
+ GPUViewport *viewport)
+{
+ View3D v3d = {NULL};
+ ARegion ar = {NULL};
+ RegionView3D rv3d = {{{0}}};
+
+ v3d.regionbase.first = v3d.regionbase.last = &ar;
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+
+ View3DShading *source_shading_settings = &scene->display.shading;
+ if (draw_flags & V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS && shading_override != NULL) {
+ source_shading_settings = shading_override;
+ }
+ memcpy(&v3d.shading, source_shading_settings, sizeof(View3DShading));
+ v3d.shading.type = drawtype;
+
+ if (shading_override) {
+ /* Pass. */
+ }
+ else if (drawtype == OB_MATERIAL) {
+ v3d.shading.flag = V3D_SHADING_SCENE_WORLD | V3D_SHADING_SCENE_LIGHTS;
+ }
+
+ if (draw_flags & V3D_OFSDRAW_SHOW_ANNOTATION) {
+ v3d.flag2 |= V3D_SHOW_ANNOTATION;
+ }
+ if (draw_flags & V3D_OFSDRAW_SHOW_GRIDFLOOR) {
+ v3d.gridflag |= V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y;
+ v3d.grid = 1.0f;
+ v3d.gridlines = 16;
+ v3d.gridsubdiv = 10;
+
+ /* Show grid, disable other overlays (set all available _HIDE_ flags). */
+ v3d.overlay.flag |= V3D_OVERLAY_HIDE_CURSOR | V3D_OVERLAY_HIDE_TEXT |
+ V3D_OVERLAY_HIDE_MOTION_PATHS | V3D_OVERLAY_HIDE_BONES |
+ V3D_OVERLAY_HIDE_OBJECT_XTRAS | V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
+ v3d.flag |= V3D_HIDE_HELPLINES;
+ }
+ else {
+ v3d.flag2 = V3D_HIDE_OVERLAYS;
+ }
+
+ rv3d.persp = RV3D_PERSP;
+ v3d.clip_start = clip_start;
+ v3d.clip_end = clip_end;
+ /* Actually not used since we pass in the projection matrix. */
+ v3d.lens = 0;
+
+ ED_view3d_draw_offscreen(depsgraph,
+ scene,
+ drawtype,
+ &v3d,
+ &ar,
+ winx,
+ winy,
+ viewmat,
+ winmat,
+ is_image_render,
+ do_sky,
+ is_persp,
+ viewname,
+ do_color_management,
+ ofs,
+ viewport);
+}
+
+/**
* Utility func for ED_view3d_draw_offscreen
*
* \param ofs: Optional off-screen buffer, can be NULL.
@@ -1681,19 +1853,19 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
*/
ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
Scene *scene,
- int drawtype,
+ eDrawType drawtype,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
int sizex,
int sizey,
- uint flag,
+ eImBufFlags imbuf_flag,
int alpha_mode,
const char *viewname,
/* output vars */
GPUOffScreen *ofs,
char err_out[256])
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
const bool draw_sky = (alpha_mode == R_ADDSKY);
/* view state */
@@ -1726,7 +1898,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
GPU_offscreen_bind(ofs, true);
/* read in pixels & stamp */
- ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
+ ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, imbuf_flag);
/* render 3d view */
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
@@ -1777,11 +1949,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
scene,
drawtype,
v3d,
- ar,
+ region,
sizex,
sizey,
NULL,
winmat,
+ true,
draw_sky,
!is_ortho,
viewname,
@@ -1827,25 +2000,25 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
Scene *scene,
View3DShading *shading_override,
- int drawtype,
+ eDrawType drawtype,
Object *camera,
int width,
int height,
- uint flag,
- uint draw_flags,
+ eImBufFlags imbuf_flag,
+ eV3DOffscreenDrawFlag draw_flags,
int alpha_mode,
const char *viewname,
GPUOffScreen *ofs,
char err_out[256])
{
View3D v3d = {NULL};
- ARegion ar = {NULL};
+ ARegion region = {NULL};
RegionView3D rv3d = {{{0}}};
/* connect data */
- v3d.regionbase.first = v3d.regionbase.last = &ar;
- ar.regiondata = &rv3d;
- ar.regiontype = RGN_TYPE_WINDOW;
+ v3d.regionbase.first = v3d.regionbase.last = &region;
+ region.regiondata = &rv3d;
+ region.regiontype = RGN_TYPE_WINDOW;
v3d.camera = camera;
View3DShading *source_shading_settings = &scene->display.shading;
@@ -1869,6 +2042,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
if (draw_flags & V3D_OFSDRAW_SHOW_ANNOTATION) {
v3d.flag2 |= V3D_SHOW_ANNOTATION;
}
+ if (draw_flags & V3D_OFSDRAW_SHOW_GRIDFLOOR) {
+ v3d.gridflag |= V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y;
+ }
v3d.shading.background_type = V3D_SHADING_BACKGROUND_WORLD;
@@ -1902,10 +2078,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
scene,
drawtype,
&v3d,
- &ar,
+ &region,
width,
height,
- flag,
+ imbuf_flag,
alpha_mode,
viewname,
ofs,
@@ -1933,11 +2109,457 @@ static bool view3d_clipping_test(const float co[3], const float clip[6][4])
return true;
}
-/* for 'local' ED_view3d_clipping_local must run first
- * then all comparisons can be done in localspace */
+/* For 'local' ED_view3d_clipping_local must run first
+ * then all comparisons can be done in localspace. */
bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local)
{
return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
}
+void ED_view3d_clipping_set(RegionView3D *UNUSED(rv3d))
+{
+ for (uint a = 0; a < 6; a++) {
+ glEnable(GL_CLIP_DISTANCE0 + a);
+ }
+}
+
+/* Use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set. */
+void ED_view3d_clipping_disable(void)
+{
+ for (uint a = 0; a < 6; a++) {
+ glDisable(GL_CLIP_DISTANCE0 + a);
+ }
+}
+void ED_view3d_clipping_enable(void)
+{
+ for (uint a = 0; a < 6; a++) {
+ glEnable(GL_CLIP_DISTANCE0 + a);
+ }
+}
+
+/* *********************** backdraw for selection *************** */
+
+/**
+ * \note Only use in object mode.
+ */
+static void validate_object_select_id(struct Depsgraph *depsgraph,
+ ViewLayer *view_layer,
+ ARegion *region,
+ View3D *v3d,
+ Object *obact)
+{
+ Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
+
+ BLI_assert(region->regiontype == RGN_TYPE_WINDOW);
+ UNUSED_VARS_NDEBUG(region);
+
+ if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
+ BKE_paint_select_face_test(obact_eval))) {
+ /* do nothing */
+ }
+ /* texture paint mode sampling */
+ else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) &&
+ (v3d->shading.type > OB_WIRE)) {
+ /* do nothing */
+ }
+ else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) {
+ /* do nothing */
+ }
+ else {
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+ return;
+ }
+
+ if (!(v3d->flag & V3D_INVALID_BACKBUF)) {
+ return;
+ }
+
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
+ Base *base = BKE_view_layer_base_find(view_layer, obact);
+ DRW_select_buffer_context_create(&base, 1, -1);
+ }
+
+ /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
+ * made on the backbuffer in this case. */
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+}
+
+/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow.
+ * Calling this function should be avoided during interactive drawing. */
+static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data)
+{
+ DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport);
+
+ GPUFrameBuffer *tmp_fb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0);
+ GPU_framebuffer_bind(tmp_fb);
+
+ glReadPixels(rect->xmin,
+ rect->ymin,
+ BLI_rcti_size_x(rect),
+ BLI_rcti_size_y(rect),
+ GL_DEPTH_COMPONENT,
+ GL_FLOAT,
+ data);
+
+ GPU_framebuffer_restore();
+ GPU_framebuffer_free(tmp_fb);
+}
+
+void ED_view3d_select_id_validate(ViewContext *vc)
+{
+ /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
+ * made on the backbuffer in this case. */
+ if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
+ validate_object_select_id(vc->depsgraph, vc->view_layer, vc->region, vc->v3d, vc->obact);
+ }
+}
+
+void ED_view3d_backbuf_depth_validate(ViewContext *vc)
+{
+ if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
+ ARegion *region = vc->region;
+ Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
+
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
+ DRW_draw_depth_object(vc->scene, vc->region, vc->v3d, viewport, obact_eval);
+ }
+
+ vc->v3d->flag &= ~V3D_INVALID_BACKBUF;
+ }
+}
+
+/**
+ * allow for small values [0.5 - 2.5],
+ * and large values, FLT_MAX by clamping by the area size
+ */
+int ED_view3d_backbuf_sample_size_clamp(ARegion *region, const float dist)
+{
+ return (int)min_ff(ceilf(dist), (float)max_ii(region->winx, region->winx));
+}
+
+/* *********************** */
+
+void view3d_update_depths_rect(ARegion *region, ViewDepths *d, rcti *rect)
+{
+ /* clamp rect by region */
+ rcti r = {
+ .xmin = 0,
+ .xmax = region->winx - 1,
+ .ymin = 0,
+ .ymax = region->winy - 1,
+ };
+
+ /* Constrain rect to depth bounds */
+ BLI_rcti_isect(&r, rect, rect);
+
+ /* assign values to compare with the ViewDepths */
+ int x = rect->xmin;
+ int y = rect->ymin;
+
+ int w = BLI_rcti_size_x(rect);
+ int h = BLI_rcti_size_y(rect);
+
+ if (w <= 0 || h <= 0) {
+ if (d->depths) {
+ MEM_freeN(d->depths);
+ }
+ d->depths = NULL;
+
+ d->damaged = false;
+ }
+ else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) {
+ d->x = x;
+ d->y = y;
+ d->w = w;
+ d->h = h;
+
+ if (d->depths) {
+ MEM_freeN(d->depths);
+ }
+
+ d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
+
+ d->damaged = true;
+ }
+
+ if (d->damaged) {
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
+ view3d_opengl_read_Z_pixels(viewport, rect, d->depths);
+ glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
+ d->damaged = false;
+ }
+}
+
+/* Note, with nouveau drivers the glReadPixels() is very slow. [#24339]. */
+void ED_view3d_depth_update(ARegion *region)
+{
+ RegionView3D *rv3d = region->regiondata;
+
+ /* Create storage for, and, if necessary, copy depth buffer. */
+ if (!rv3d->depths) {
+ rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
+ }
+ if (rv3d->depths) {
+ ViewDepths *d = rv3d->depths;
+ if (d->w != region->winx || d->h != region->winy || !d->depths) {
+ d->w = region->winx;
+ d->h = region->winy;
+ if (d->depths) {
+ MEM_freeN(d->depths);
+ }
+ d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
+ d->damaged = true;
+ }
+
+ if (d->damaged) {
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
+ rcti r = {
+ .xmin = 0,
+ .xmax = d->w,
+ .ymin = 0,
+ .ymax = d->h,
+ };
+ view3d_opengl_read_Z_pixels(viewport, &r, d->depths);
+ glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
+ d->damaged = false;
+ }
+ }
+}
+
+/* Utility function to find the closest Z value, use for autodepth. */
+float view3d_depth_near(ViewDepths *d)
+{
+ /* Convert to float for comparisons. */
+ const float near = (float)d->depth_range[0];
+ const float far_real = (float)d->depth_range[1];
+ float far = far_real;
+
+ const float *depths = d->depths;
+ float depth = FLT_MAX;
+ int i = (int)d->w * (int)d->h; /* Cast to avoid short overflow. */
+
+ /* Far is both the starting 'far' value
+ * and the closest value found. */
+ while (i--) {
+ depth = *depths++;
+ if ((depth < far) && (depth > near)) {
+ far = depth;
+ }
+ }
+
+ return far == far_real ? FLT_MAX : far;
+}
+
+void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *region, View3D *v3d)
+{
+ /* Setup view matrix. */
+ ED_view3d_draw_setup_view(NULL, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL);
+
+ GPU_clear(GPU_DEPTH_BIT);
+
+ GPU_depth_test(true);
+
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
+ DRW_draw_depth_loop_gpencil(depsgraph, region, v3d, viewport);
+
+ GPU_depth_test(false);
+}
+
+/* *********************** customdata **************** */
+
+void ED_view3d_datamask(const bContext *C,
+ const Scene *UNUSED(scene),
+ const View3D *v3d,
+ CustomData_MeshMasks *r_cddata_masks)
+{
+ if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) {
+ r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
+ r_cddata_masks->vmask |= CD_MASK_ORCO;
+ }
+ else if (v3d->shading.type == OB_SOLID) {
+ if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) {
+ r_cddata_masks->lmask |= CD_MASK_MLOOPUV;
+ }
+ if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) {
+ r_cddata_masks->lmask |= CD_MASK_MLOOPCOL;
+ }
+ }
+
+ if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) &&
+ (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) {
+ r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
+ }
+}
+
+/* Goes over all modes and view3d settings. */
+void ED_view3d_screen_datamask(const bContext *C,
+ const Scene *scene,
+ const bScreen *screen,
+ CustomData_MeshMasks *r_cddata_masks)
+{
+ CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH);
+
+ /* Check if we need tfaces & mcols due to view mode. */
+ LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) {
+ if (area->spacetype == SPACE_VIEW3D) {
+ ED_view3d_datamask(C, scene, area->spacedata.first, r_cddata_masks);
+ }
+ }
+}
+
+/**
+ * Store values from #RegionView3D, set when drawing.
+ * This is needed when we draw with to a viewport using a different matrix
+ * (offscreen drawing for example).
+ *
+ * Values set by #ED_view3d_update_viewmat should be handled here.
+ */
+struct RV3DMatrixStore {
+ float winmat[4][4];
+ float viewmat[4][4];
+ float viewinv[4][4];
+ float persmat[4][4];
+ float persinv[4][4];
+ float viewcamtexcofac[4];
+ float pixsize;
+};
+
+struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
+{
+ struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
+ copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
+ copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat);
+ copy_m4_m4(rv3dmat->persmat, rv3d->persmat);
+ copy_m4_m4(rv3dmat->persinv, rv3d->persinv);
+ copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv);
+ copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac);
+ rv3dmat->pixsize = rv3d->pixsize;
+ return (void *)rv3dmat;
+}
+
+void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt)
+{
+ struct RV3DMatrixStore *rv3dmat = rv3dmat_pt;
+ copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
+ copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat);
+ copy_m4_m4(rv3d->persmat, rv3dmat->persmat);
+ copy_m4_m4(rv3d->persinv, rv3dmat->persinv);
+ copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv);
+ copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac);
+ rv3d->pixsize = rv3dmat->pixsize;
+}
+
+/**
+ * \note The info that this uses is updated in #ED_refresh_viewport_fps,
+ * which currently gets called during #SCREEN_OT_animation_step.
+ */
+void ED_scene_draw_fps(const Scene *scene, int xoffset, int *yoffset)
+{
+ ScreenFrameRateInfo *fpsi = scene->fps_info;
+ char printable[16];
+
+ if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) {
+ return;
+ }
+
+ printable[0] = '\0';
+
+ /* Doing an average for a more robust calculation. */
+ fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 /
+ (fpsi->lredrawtime - fpsi->redrawtime));
+
+ float fps = 0.0f;
+ int tot = 0;
+ for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) {
+ if (fpsi->redrawtimes_fps[i]) {
+ fps += fpsi->redrawtimes_fps[i];
+ tot++;
+ }
+ }
+ if (tot) {
+ fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
+ fps = fps / tot;
+ }
+
+ const int font_id = BLF_default();
+
+ /* Is this more than half a frame behind? */
+ if (fps + 0.5f < (float)(FPS)) {
+ UI_FontThemeColor(font_id, TH_REDALERT);
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
+ }
+ else {
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
+ }
+
+ BLF_enable(font_id, BLF_SHADOW);
+ BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
+ BLF_shadow_offset(font_id, 1, -1);
+
+ *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT;
+
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
+#else
+ BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
+#endif
+
+ BLF_disable(font_id, BLF_SHADOW);
+}
+
+static bool view3d_main_region_do_render_draw(const Scene *scene)
+{
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ return (type && type->view_update && type->view_draw);
+}
+
+bool ED_view3d_calc_render_border(
+ const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *region, rcti *rect)
+{
+ RegionView3D *rv3d = region->regiondata;
+ bool use_border;
+
+ /* Test if there is a 3d view rendering. */
+ if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) {
+ return false;
+ }
+
+ /* Test if there is a border render. */
+ if (rv3d->persp == RV3D_CAMOB) {
+ use_border = (scene->r.mode & R_BORDER) != 0;
+ }
+ else {
+ use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
+ }
+
+ if (!use_border) {
+ return false;
+ }
+
+ /* Compute border. */
+ if (rv3d->persp == RV3D_CAMOB) {
+ rctf viewborder;
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &viewborder, false);
+
+ rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
+ rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
+ rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
+ rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
+ }
+ else {
+ rect->xmin = v3d->render_border.xmin * region->winx;
+ rect->xmax = v3d->render_border.xmax * region->winx;
+ rect->ymin = v3d->render_border.ymin * region->winy;
+ rect->ymax = v3d->render_border.ymax * region->winy;
+ }
+
+ BLI_rcti_translate(rect, region->winrct.xmin, region->winrct.ymin);
+ BLI_rcti_isect(&region->winrct, rect, rect);
+
+ return true;
+}
+
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
deleted file mode 100644
index 38cb5ad8651..00000000000
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2008 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup spview3d
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-
-#include "DNA_armature_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_collection_types.h"
-#include "DNA_customdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_key_types.h"
-#include "DNA_light_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_world_types.h"
-#include "DNA_brush_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_endian_switch.h"
-#include "BLI_threads.h"
-
-#include "BKE_anim.h"
-#include "BKE_camera.h"
-#include "BKE_context.h"
-#include "BKE_customdata.h"
-#include "BKE_image.h"
-#include "BKE_key.h"
-#include "BKE_layer.h"
-#include "BKE_object.h"
-#include "BKE_global.h"
-#include "BKE_paint.h"
-#include "BKE_scene.h"
-#include "BKE_unit.h"
-#include "BKE_movieclip.h"
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
-
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-#include "IMB_colormanagement.h"
-
-#include "BIF_glutil.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "BLF_api.h"
-#include "BLT_translation.h"
-
-#include "ED_armature.h"
-#include "ED_keyframing.h"
-#include "ED_gpencil.h"
-#include "ED_mesh.h"
-#include "ED_screen.h"
-#include "ED_space_api.h"
-#include "ED_screen_types.h"
-#include "ED_transform.h"
-#include "ED_view3d.h"
-
-#include "UI_interface.h"
-#include "UI_interface_icons.h"
-#include "UI_resources.h"
-
-#include "GPU_framebuffer.h"
-#include "GPU_immediate.h"
-#include "GPU_state.h"
-#include "GPU_viewport.h"
-
-#include "RE_engine.h"
-
-#include "DRW_engine.h"
-#include "DRW_select_buffer.h"
-
-#include "view3d_intern.h" /* own include */
-
-/* ********* custom clipping *********** */
-
-/* Legacy 2.7x, now use shaders that use clip distance instead.
- * Remove once clipping is working properly. */
-#define USE_CLIP_PLANES
-
-void ED_view3d_clipping_set(RegionView3D *rv3d)
-{
-#ifdef USE_CLIP_PLANES
- double plane[4];
- const uint tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
-
- for (unsigned a = 0; a < tot; a++) {
- copy_v4db_v4fl(plane, rv3d->clip[a]);
- glClipPlane(GL_CLIP_PLANE0 + a, plane);
- glEnable(GL_CLIP_PLANE0 + a);
- glEnable(GL_CLIP_DISTANCE0 + a);
- }
-#else
- for (unsigned a = 0; a < 6; a++) {
- glEnable(GL_CLIP_DISTANCE0 + a);
- }
-#endif
-}
-
-/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */
-void ED_view3d_clipping_disable(void)
-{
- for (unsigned a = 0; a < 6; a++) {
-#ifdef USE_CLIP_PLANES
- glDisable(GL_CLIP_PLANE0 + a);
-#endif
- glDisable(GL_CLIP_DISTANCE0 + a);
- }
-}
-void ED_view3d_clipping_enable(void)
-{
- for (unsigned a = 0; a < 6; a++) {
-#ifdef USE_CLIP_PLANES
- glEnable(GL_CLIP_PLANE0 + a);
-#endif
- glEnable(GL_CLIP_DISTANCE0 + a);
- }
-}
-
-/* *********************** backdraw for selection *************** */
-
-/**
- * \note Only use in object mode.
- */
-static void validate_object_select_id(
- struct Depsgraph *depsgraph, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Object *obact)
-{
- Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
-
- BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
- UNUSED_VARS_NDEBUG(ar);
-
- if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
- BKE_paint_select_face_test(obact_eval))) {
- /* do nothing */
- }
- /* texture paint mode sampling */
- else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) &&
- (v3d->shading.type > OB_WIRE)) {
- /* do nothing */
- }
- else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) {
- /* do nothing */
- }
- else {
- v3d->flag &= ~V3D_INVALID_BACKBUF;
- return;
- }
-
- if (!(v3d->flag & V3D_INVALID_BACKBUF)) {
- return;
- }
-
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
- Base *base = BKE_view_layer_base_find(view_layer, obact);
- DRW_select_buffer_context_create(&base, 1, -1);
- }
-
- /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
- * made on the backbuffer in this case. */
- v3d->flag &= ~V3D_INVALID_BACKBUF;
-}
-
-/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow.
- * Calling this function should be avoided during interactive drawing. */
-static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data)
-{
- DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport);
-
- GPUFrameBuffer *tmp_fb = GPU_framebuffer_create();
- GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0);
- GPU_framebuffer_bind(tmp_fb);
-
- glReadPixels(rect->xmin,
- rect->ymin,
- BLI_rcti_size_x(rect),
- BLI_rcti_size_y(rect),
- GL_DEPTH_COMPONENT,
- GL_FLOAT,
- data);
-
- GPU_framebuffer_restore();
- GPU_framebuffer_free(tmp_fb);
-}
-
-void ED_view3d_select_id_validate(ViewContext *vc)
-{
- /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
- * made on the backbuffer in this case. */
- if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- validate_object_select_id(vc->depsgraph, vc->view_layer, vc->ar, vc->v3d, vc->obact);
- }
-}
-
-void ED_view3d_backbuf_depth_validate(ViewContext *vc)
-{
- if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- ARegion *ar = vc->ar;
- Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
-
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- DRW_draw_depth_object(vc->ar, vc->v3d, viewport, obact_eval);
- }
-
- vc->v3d->flag &= ~V3D_INVALID_BACKBUF;
- }
-}
-
-/**
- * allow for small values [0.5 - 2.5],
- * and large values, FLT_MAX by clamping by the area size
- */
-int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
-{
- return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
-}
-
-/* *********************** */
-
-void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
-{
- /* clamp rect by region */
- rcti r = {
- .xmin = 0,
- .xmax = ar->winx - 1,
- .ymin = 0,
- .ymax = ar->winy - 1,
- };
-
- /* Constrain rect to depth bounds */
- BLI_rcti_isect(&r, rect, rect);
-
- /* assign values to compare with the ViewDepths */
- int x = rect->xmin;
- int y = rect->ymin;
-
- int w = BLI_rcti_size_x(rect);
- int h = BLI_rcti_size_y(rect);
-
- if (w <= 0 || h <= 0) {
- if (d->depths) {
- MEM_freeN(d->depths);
- }
- d->depths = NULL;
-
- d->damaged = false;
- }
- else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) {
- d->x = x;
- d->y = y;
- d->w = w;
- d->h = h;
-
- if (d->depths) {
- MEM_freeN(d->depths);
- }
-
- d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
-
- d->damaged = true;
- }
-
- if (d->damaged) {
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- view3d_opengl_read_Z_pixels(viewport, rect, d->depths);
- glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
- d->damaged = false;
- }
-}
-
-/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */
-void ED_view3d_depth_update(ARegion *ar)
-{
- RegionView3D *rv3d = ar->regiondata;
-
- /* Create storage for, and, if necessary, copy depth buffer */
- if (!rv3d->depths) {
- rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
- }
- if (rv3d->depths) {
- ViewDepths *d = rv3d->depths;
- if (d->w != ar->winx || d->h != ar->winy || !d->depths) {
- d->w = ar->winx;
- d->h = ar->winy;
- if (d->depths) {
- MEM_freeN(d->depths);
- }
- d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
- d->damaged = true;
- }
-
- if (d->damaged) {
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- rcti r = {
- .xmin = 0,
- .xmax = d->w,
- .ymin = 0,
- .ymax = d->h,
- };
- view3d_opengl_read_Z_pixels(viewport, &r, d->depths);
- glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
- d->damaged = false;
- }
- }
-}
-
-/* utility function to find the closest Z value, use for autodepth */
-float view3d_depth_near(ViewDepths *d)
-{
- /* convert to float for comparisons */
- const float near = (float)d->depth_range[0];
- const float far_real = (float)d->depth_range[1];
- float far = far_real;
-
- const float *depths = d->depths;
- float depth = FLT_MAX;
- int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */
-
- /* far is both the starting 'far' value
- * and the closest value found. */
- while (i--) {
- depth = *depths++;
- if ((depth < far) && (depth > near)) {
- far = depth;
- }
- }
-
- return far == far_real ? FLT_MAX : far;
-}
-
-void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d)
-{
- /* Setup view matrix. */
- ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL);
-
- GPU_clear(GPU_DEPTH_BIT);
-
- GPU_depth_test(true);
-
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport);
-
- GPU_depth_test(false);
-}
-
-/* *********************** customdata **************** */
-
-void ED_view3d_datamask(const bContext *C,
- const Scene *UNUSED(scene),
- const View3D *v3d,
- CustomData_MeshMasks *r_cddata_masks)
-{
- if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) {
- r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
- r_cddata_masks->vmask |= CD_MASK_ORCO;
- }
- else if (v3d->shading.type == OB_SOLID) {
- if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) {
- r_cddata_masks->lmask |= CD_MASK_MLOOPUV;
- }
- if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) {
- r_cddata_masks->lmask |= CD_MASK_MLOOPCOL;
- }
- }
-
- if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) &&
- (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) {
- r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
- }
-}
-
-/* goes over all modes and view3d settings */
-void ED_view3d_screen_datamask(const bContext *C,
- const Scene *scene,
- const bScreen *screen,
- CustomData_MeshMasks *r_cddata_masks)
-{
- CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH);
-
- /* check if we need tfaces & mcols due to view mode */
- for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_VIEW3D) {
- ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks);
- }
- }
-}
-
-/**
- * Store values from #RegionView3D, set when drawing.
- * This is needed when we draw with to a viewport using a different matrix
- * (offscreen drawing for example).
- *
- * Values set by #ED_view3d_update_viewmat should be handled here.
- */
-struct RV3DMatrixStore {
- float winmat[4][4];
- float viewmat[4][4];
- float viewinv[4][4];
- float persmat[4][4];
- float persinv[4][4];
- float viewcamtexcofac[4];
- float pixsize;
-};
-
-struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
-{
- struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
- copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
- copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat);
- copy_m4_m4(rv3dmat->persmat, rv3d->persmat);
- copy_m4_m4(rv3dmat->persinv, rv3d->persinv);
- copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv);
- copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac);
- rv3dmat->pixsize = rv3d->pixsize;
- return (void *)rv3dmat;
-}
-
-void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt)
-{
- struct RV3DMatrixStore *rv3dmat = rv3dmat_pt;
- copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
- copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat);
- copy_m4_m4(rv3d->persmat, rv3dmat->persmat);
- copy_m4_m4(rv3d->persinv, rv3dmat->persinv);
- copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv);
- copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac);
- rv3d->pixsize = rv3dmat->pixsize;
-}
-
-/**
- * \note The info that this uses is updated in #ED_refresh_viewport_fps,
- * which currently gets called during #SCREEN_OT_animation_step.
- */
-void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset)
-{
- ScreenFrameRateInfo *fpsi = scene->fps_info;
- char printable[16];
-
- if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) {
- return;
- }
-
- printable[0] = '\0';
-
-#if 0
- /* this is too simple, better do an average */
- fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
-#else
- fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 /
- (fpsi->lredrawtime - fpsi->redrawtime));
-
- float fps = 0.0f;
- int tot = 0;
- for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) {
- if (fpsi->redrawtimes_fps[i]) {
- fps += fpsi->redrawtimes_fps[i];
- tot++;
- }
- }
- if (tot) {
- fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
-
- // fpsi->redrawtime_index++;
- // if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) {
- // fpsi->redrawtime = 0;
- //}
-
- fps = fps / tot;
- }
-#endif
-
- const int font_id = BLF_default();
-
- /* is this more than half a frame behind? */
- if (fps + 0.5f < (float)(FPS)) {
- UI_FontThemeColor(font_id, TH_REDALERT);
- BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
- }
- else {
- UI_FontThemeColor(font_id, TH_TEXT_HI);
- BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
- }
-
- BLF_enable(font_id, BLF_SHADOW);
- BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
- BLF_shadow_offset(font_id, 1, -1);
-
- *yoffset -= U.widget_unit;
-
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
-#else
- BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
-#endif
-
- BLF_disable(font_id, BLF_SHADOW);
-}
-
-static bool view3d_main_region_do_render_draw(const Scene *scene)
-{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type && type->view_update && type->view_draw);
-}
-
-bool ED_view3d_calc_render_border(
- const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect)
-{
- RegionView3D *rv3d = ar->regiondata;
- bool use_border;
-
- /* test if there is a 3d view rendering */
- if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) {
- return false;
- }
-
- /* test if there is a border render */
- if (rv3d->persp == RV3D_CAMOB) {
- use_border = (scene->r.mode & R_BORDER) != 0;
- }
- else {
- use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
- }
-
- if (!use_border) {
- return false;
- }
-
- /* compute border */
- if (rv3d->persp == RV3D_CAMOB) {
- rctf viewborder;
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false);
-
- rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
- rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
- rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
- rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
- }
- else {
- rect->xmin = v3d->render_border.xmin * ar->winx;
- rect->xmax = v3d->render_border.xmax * ar->winx;
- rect->ymin = v3d->render_border.ymin * ar->winy;
- rect->ymax = v3d->render_border.ymax * ar->winy;
- }
-
- BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin);
- BLI_rcti_isect(&ar->winrct, rect, rect);
-
- return true;
-}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 83fb87264e3..5cdf6ce28cb 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -23,17 +23,17 @@
* 3D view manipulation/operators.
*/
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_gpencil_types.h"
#include "MEM_guardedalloc.h"
@@ -46,9 +46,9 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_font.h"
-#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -60,19 +60,19 @@
#include "DEG_depsgraph_query.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "ED_armature.h"
+#include "ED_mesh.h"
#include "ED_particle.h"
#include "ED_screen.h"
#include "ED_transform.h"
-#include "ED_mesh.h"
-#include "ED_view3d.h"
#include "ED_transform_snap_object_context.h"
+#include "ED_view3d.h"
#include "UI_resources.h"
@@ -85,6 +85,52 @@ enum {
HAS_ROTATE = (1 << 0),
};
+/* test for unlocked camera view in quad view */
+static bool view3d_camera_user_poll(bContext *C)
+{
+ View3D *v3d;
+ ARegion *region;
+
+ if (ED_view3d_context_user_region(C, &v3d, &region)) {
+ RegionView3D *rv3d = region->regiondata;
+ if ((rv3d->persp == RV3D_CAMOB) && !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static bool view3d_lock_poll(bContext *C)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d) {
+ return ED_view3d_offset_lock_check(v3d, rv3d);
+ }
+ }
+ return false;
+}
+
+static bool view3d_pan_poll(bContext *C)
+{
+ if (ED_operator_region_view3d_active(C)) {
+ const RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ return !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_LOCATION);
+ }
+ return false;
+}
+
+static bool view3d_zoom_or_dolly_poll(bContext *C)
+{
+ if (ED_operator_region_view3d_active(C)) {
+ const RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ return !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ZOOM_AND_DOLLY);
+ }
+ return false;
+}
+
/* -------------------------------------------------------------------- */
/** \name Generic View Operator Properties
* \{ */
@@ -129,8 +175,8 @@ typedef struct ViewOpsData {
/** Context pointers (assigned by #viewops_data_alloc). */
Main *bmain;
Scene *scene;
- ScrArea *sa;
- ARegion *ar;
+ ScrArea *area;
+ ARegion *region;
View3D *v3d;
RegionView3D *rv3d;
Depsgraph *depsgraph;
@@ -190,7 +236,7 @@ typedef struct ViewOpsData {
} ViewOpsData;
/**
- * Size of the sphere being dragged for trackball rotation withing the view bounds.
+ * Size of the sphere being dragged for trackball rotation within the view bounds.
* also affects speed (smaller is faster).
*/
#define TRACKBALLSIZE (1.1f)
@@ -211,11 +257,11 @@ static void calctrackballvec(const rcti *rect, const int event_xy[2], float r_di
const float d = len_v2(r_dir);
if (d < t) {
/* Inside sphere. */
- r_dir[2] = sqrtf(SQUARE(radius) - SQUARE(d));
+ r_dir[2] = sqrtf(square_f(radius) - square_f(d));
}
else {
/* On hyperbola. */
- r_dir[2] = SQUARE(t) / d;
+ r_dir[2] = square_f(t) / d;
}
}
@@ -231,10 +277,10 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
vod->bmain = CTX_data_main(C);
vod->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
vod->scene = CTX_data_scene(C);
- vod->sa = CTX_wm_area(C);
- vod->ar = CTX_wm_region(C);
- vod->v3d = vod->sa->spacedata.first;
- vod->rv3d = vod->ar->regiondata;
+ vod->area = CTX_wm_area(C);
+ vod->region = CTX_wm_region(C);
+ vod->v3d = vod->area->spacedata.first;
+ vod->rv3d = vod->region->regiondata;
}
void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
@@ -401,17 +447,17 @@ static void viewops_data_create(bContext *C,
negate_v3_v3(fallback_depth_pt, rv3d->ofs);
vod->use_dyn_ofs = ED_view3d_autodist(
- depsgraph, vod->ar, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt);
+ depsgraph, vod->region, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt);
}
else {
vod->use_dyn_ofs = false;
}
if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
- if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) {
+ if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->region)) {
/* If we're switching from camera view to the perspective one,
* need to tag viewport update, so camera view and borders are properly updated. */
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
}
}
@@ -432,8 +478,8 @@ static void viewops_data_create(bContext *C,
}
else {
/* Simulate the event starting in the middle of the region. */
- vod->init.event_xy_offset[0] = BLI_rcti_cent_x(&vod->ar->winrct) - event->x;
- vod->init.event_xy_offset[1] = BLI_rcti_cent_y(&vod->ar->winrct) - event->y;
+ vod->init.event_xy_offset[0] = BLI_rcti_cent_x(&vod->region->winrct) - event->x;
+ vod->init.event_xy_offset[1] = BLI_rcti_cent_y(&vod->region->winrct) - event->y;
}
vod->init.event_type = event->type;
@@ -483,9 +529,10 @@ static void viewops_data_create(bContext *C,
negate_v3_v3(rv3d->ofs, dvec);
}
else {
- const float mval_ar_mid[2] = {(float)vod->ar->winx / 2.0f, (float)vod->ar->winy / 2.0f};
+ const float mval_region_mid[2] = {(float)vod->region->winx / 2.0f,
+ (float)vod->region->winy / 2.0f};
- ED_view3d_win_to_3d(vod->v3d, vod->ar, vod->dyn_ofs, mval_ar_mid, rv3d->ofs);
+ ED_view3d_win_to_3d(vod->v3d, vod->region, vod->dyn_ofs, mval_region_mid, rv3d->ofs);
negate_v3(rv3d->ofs);
}
negate_v3(vod->dyn_ofs);
@@ -494,7 +541,7 @@ static void viewops_data_create(bContext *C,
}
/* For dolly */
- ED_view3d_win_to_vector(vod->ar, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec);
+ ED_view3d_win_to_vector(vod->region, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec);
{
const int event_xy_offset[2] = {
@@ -502,7 +549,7 @@ static void viewops_data_create(bContext *C,
event->y + vod->init.event_xy_offset[1],
};
/* For rotation with trackball rotation. */
- calctrackballvec(&vod->ar->winrct, event_xy_offset, vod->init.trackvec);
+ calctrackballvec(&vod->region->winrct, event_xy_offset, vod->init.trackvec);
}
{
@@ -521,10 +568,10 @@ static void viewops_data_create(bContext *C,
static void viewops_data_free(bContext *C, wmOperator *op)
{
- ARegion *ar;
+ ARegion *region;
if (op->customdata) {
ViewOpsData *vod = op->customdata;
- ar = vod->ar;
+ region = vod->region;
vod->rv3d->rflag &= ~RV3D_NAVIGATING;
if (vod->timer) {
@@ -535,12 +582,12 @@ static void viewops_data_free(bContext *C, wmOperator *op)
op->customdata = NULL;
}
else {
- ar = CTX_wm_region(C);
+ region = CTX_wm_region(C);
}
/* Need to redraw because drawing code uses RV3D_NAVIGATING to draw
* faster while navigation operator runs. */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
/** \} */
@@ -580,14 +627,14 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Rotate Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Rotate Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Rotate Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Rotate Modal", modal_items);
/* disabled mode switching for now, can re-implement better, later on */
#if 0
@@ -700,9 +747,9 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
if (found) {
/* lock 'quat_best' to an axis view if we can */
- rv3d->view = ED_view3d_quat_to_axis_view(quat_best, 0.01f);
+ ED_view3d_quat_to_axis_view(quat_best, 0.01f, &rv3d->view, &rv3d->view_axis_roll);
if (rv3d->view != RV3D_VIEW_USER) {
- ED_view3d_quat_from_axis_view(rv3d->view, quat_best);
+ ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, quat_best);
}
}
else {
@@ -741,7 +788,7 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
event_xy[0] + vod->init.event_xy_offset[0],
event_xy[1] + vod->init.event_xy_offset[1],
};
- calctrackballvec(&vod->ar->winrct, event_xy_offset, newvec);
+ calctrackballvec(&vod->region->winrct, event_xy_offset, newvec);
}
sub_v3_v3v3(dvec, newvec, vod->init.trackvec);
@@ -858,7 +905,7 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
}
static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -934,12 +981,12 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
vod = op->customdata;
/* poll should check but in some cases fails, see poll func for details */
- if (vod->rv3d->viewlock & RV3D_LOCKED) {
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_ROTATION) {
viewops_data_free(C, op);
return OPERATOR_PASS_THROUGH;
}
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
viewops_data_create(C,
op,
@@ -982,34 +1029,6 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
}
-/* test for unlocked camera view in quad view */
-static bool view3d_camera_user_poll(bContext *C)
-{
- View3D *v3d;
- ARegion *ar;
-
- if (ED_view3d_context_user_region(C, &v3d, &ar)) {
- RegionView3D *rv3d = ar->regiondata;
- if (rv3d->persp == RV3D_CAMOB) {
- return 1;
- }
- }
-
- return 0;
-}
-
-static bool view3d_lock_poll(bContext *C)
-{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d) {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (rv3d) {
- return ED_view3d_offset_lock_check(v3d, rv3d);
- }
- }
- return false;
-}
-
static void viewrotate_cancel(bContext *C, wmOperator *op)
{
viewops_data_free(C, op);
@@ -1050,7 +1069,7 @@ static bool ndof_has_translate(const wmNDOFMotionData *ndof,
static bool ndof_has_rotate(const wmNDOFMotionData *ndof, const RegionView3D *rv3d)
{
- return !is_zero_v3(ndof->rvec) && ((rv3d->viewlock & RV3D_LOCKED) == 0);
+ return !is_zero_v3(ndof->rvec) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0);
}
/**
@@ -1101,12 +1120,12 @@ static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d)
* often `!rv3d->is_persp` since it doesn't make sense to dolly in ortho.
*/
static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
- ScrArea *sa,
- ARegion *ar,
+ ScrArea *area,
+ ARegion *region,
const bool has_translate,
const bool has_zoom)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
float view_inv[4];
float pan_vec[3];
@@ -1142,7 +1161,7 @@ static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
/* all callers must check */
if (has_translate) {
- BLI_assert(ED_view3d_offset_lock_check((View3D *)sa->spacedata.first, rv3d) == false);
+ BLI_assert(ED_view3d_offset_lock_check((View3D *)area->spacedata.first, rv3d) == false);
}
}
@@ -1158,26 +1177,26 @@ static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
/* move center of view opposite of hand motion (this is camera mode, not object mode) */
sub_v3_v3(rv3d->ofs, pan_vec);
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar);
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(area, region);
}
}
}
static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof,
- ScrArea *sa,
- ARegion *ar,
+ ScrArea *area,
+ ARegion *region,
ViewOpsData *vod,
const bool apply_dyn_ofs)
{
- View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = area->spacedata.first;
+ RegionView3D *rv3d = region->regiondata;
float view_inv[4];
- BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
+ BLI_assert((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0);
- ED_view3d_persp_ensure(vod->depsgraph, v3d, ar);
+ ED_view3d_persp_ensure(vod->depsgraph, v3d, region);
rv3d->view = RV3D_VIEW_USER;
@@ -1385,7 +1404,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
C, op, event, viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
vod = op->customdata;
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
v3d = vod->v3d;
rv3d = vod->rv3d;
@@ -1399,16 +1418,16 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool has_rotation = ndof_has_rotate(ndof, rv3d);
/* if we can't rotate, fallback to translate (locked axis views) */
const bool has_translate = ndof_has_translate(ndof, v3d, rv3d) &&
- (rv3d->viewlock & RV3D_LOCKED);
+ (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION);
const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom);
+ view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
xform_flag |= HAS_TRANSLATE;
}
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
+ view3d_ndof_orbit(ndof, vod->area, vod->region, vod, true);
xform_flag |= HAS_ROTATE;
}
}
@@ -1419,7 +1438,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
}
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
viewops_data_free(C, op);
@@ -1467,7 +1486,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
vod = op->customdata;
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
v3d = vod->v3d;
rv3d = vod->rv3d;
@@ -1486,7 +1505,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d);
if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, true);
+ view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, true);
xform_flag |= HAS_TRANSLATE;
}
}
@@ -1516,7 +1535,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
if (!is_orbit_around_pivot) {
ED_view3d_distance_set(rv3d, 0.0f);
}
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, is_orbit_around_pivot);
+ view3d_ndof_orbit(ndof, vod->area, vod->region, vod, is_orbit_around_pivot);
xform_flag |= HAS_ROTATE;
if (!is_orbit_around_pivot) {
ED_view3d_distance_set(rv3d, dist_backup);
@@ -1524,7 +1543,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
}
if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom);
+ view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
xform_flag |= HAS_TRANSLATE;
}
}
@@ -1535,7 +1554,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
}
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
viewops_data_free(C, op);
@@ -1588,11 +1607,11 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress != P_FINISHING) {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, sa, ar, has_translate, has_zoom);
+ view3d_ndof_pan_zoom(ndof, area, region, has_translate, has_zoom);
xform_flag |= HAS_TRANSLATE;
}
}
@@ -1683,18 +1702,18 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Move Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Move Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Move Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Move Modal", modal_items);
/* items for modal map */
WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, EVT_ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
/* disabled mode switching for now, can re-implement better, later on */
#if 0
@@ -1711,13 +1730,13 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
static void viewmove_apply(ViewOpsData *vod, int x, int y)
{
if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) {
- vod->rv3d->ofs_lock[0] -= ((vod->prev.event_xy[0] - x) * 2.0f) / (float)vod->ar->winx;
- vod->rv3d->ofs_lock[1] -= ((vod->prev.event_xy[1] - y) * 2.0f) / (float)vod->ar->winy;
+ vod->rv3d->ofs_lock[0] -= ((vod->prev.event_xy[0] - x) * 2.0f) / (float)vod->region->winx;
+ vod->rv3d->ofs_lock[1] -= ((vod->prev.event_xy[1] - y) * 2.0f) / (float)vod->region->winy;
}
else if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
const float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
- vod->rv3d->camdx += (vod->prev.event_xy[0] - x) / (vod->ar->winx * zoomfac);
- vod->rv3d->camdy += (vod->prev.event_xy[1] - y) / (vod->ar->winy * zoomfac);
+ vod->rv3d->camdx += (vod->prev.event_xy[0] - x) / (vod->region->winx * zoomfac);
+ vod->rv3d->camdy += (vod->prev.event_xy[1] - y) / (vod->region->winy * zoomfac);
CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
CLAMP(vod->rv3d->camdy, -1.0f, 1.0f);
}
@@ -1727,12 +1746,12 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
mval_f[0] = x - vod->prev.event_xy[0];
mval_f[1] = y - vod->prev.event_xy[1];
- ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->init.zfac);
+ ED_view3d_win_to_delta(vod->region, mval_f, dvec, vod->init.zfac);
add_v3_v3(vod->rv3d->ofs, dvec);
- if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->ar);
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->area, vod->region);
}
}
@@ -1741,7 +1760,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
}
static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -1806,14 +1825,19 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* makes op->customdata */
viewops_data_alloc(C, op);
+ vod = op->customdata;
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_LOCATION) {
+ viewops_data_free(C, op);
+ return OPERATOR_PASS_THROUGH;
+ }
+
viewops_data_create(C,
op,
event,
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
- vod = op->customdata;
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
if (event->type == MOUSEPAN) {
/* invert it, trackpad scroll follows same principle as 2d windows this way */
@@ -1877,14 +1901,14 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Zoom Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Zoom Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Zoom Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Zoom Modal", modal_items);
/* disabled mode switching for now, can re-implement better, later on */
#if 0
@@ -1901,10 +1925,14 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
* \param zoom_xy: Optionally zoom to window location
* (coords compatible w/ #wmEvent.x, y). Use when not NULL.
*/
-static void view_zoom_to_window_xy_camera(
- Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, float dfac, const int zoom_xy[2])
-{
- RegionView3D *rv3d = ar->regiondata;
+static void view_zoom_to_window_xy_camera(Scene *scene,
+ Depsgraph *depsgraph,
+ View3D *v3d,
+ ARegion *region,
+ float dfac,
+ const int zoom_xy[2])
+{
+ RegionView3D *rv3d = region->regiondata;
const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
const float zoomfac_new = clamp_f(
zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
@@ -1919,14 +1947,14 @@ static void view_zoom_to_window_xy_camera(
float pt_dst[2];
float delta_px[2];
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_old, false);
- BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin);
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &camera_frame_old, false);
+ BLI_rctf_translate(&camera_frame_old, region->winrct.xmin, region->winrct.ymin);
rv3d->camzoom = camzoom_new;
CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_new, false);
- BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin);
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &camera_frame_new, false);
+ BLI_rctf_translate(&camera_frame_new, region->winrct.xmin, region->winrct.ymin);
BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
sub_v2_v2v2(delta_px, pt_dst, pt_src);
@@ -1935,8 +1963,8 @@ static void view_zoom_to_window_xy_camera(
* mapped back to the camera (same logic as panning in camera view) */
zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f;
- rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px);
- rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px);
+ rv3d->camdx += delta_px[0] / (region->winx * zoomfac_px);
+ rv3d->camdy += delta_px[1] / (region->winy * zoomfac_px);
CLAMP(rv3d->camdx, -1.0f, 1.0f);
CLAMP(rv3d->camdy, -1.0f, 1.0f);
}
@@ -1950,9 +1978,9 @@ static void view_zoom_to_window_xy_camera(
* \param zoom_xy: Optionally zoom to window location
* (coords compatible w/ #wmEvent.x, y). Use when not NULL.
*/
-static void view_zoom_to_window_xy_3d(ARegion *ar, float dfac, const int zoom_xy[2])
+static void view_zoom_to_window_xy_3d(ARegion *region, float dfac, const int zoom_xy[2])
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
const float dist_new = rv3d->dist * dfac;
if (zoom_xy != NULL) {
@@ -1965,12 +1993,12 @@ static void view_zoom_to_window_xy_3d(ARegion *ar, float dfac, const int zoom_xy
negate_v3_v3(tpos, rv3d->ofs);
- mval_f[0] = (float)(((zoom_xy[0] - ar->winrct.xmin) * 2) - ar->winx) / 2.0f;
- mval_f[1] = (float)(((zoom_xy[1] - ar->winrct.ymin) * 2) - ar->winy) / 2.0f;
+ mval_f[0] = (float)(((zoom_xy[0] - region->winrct.xmin) * 2) - region->winx) / 2.0f;
+ mval_f[1] = (float)(((zoom_xy[1] - region->winrct.ymin) * 2) - region->winy) / 2.0f;
/* Project cursor position into 3D space */
zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL);
- ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
+ ED_view3d_win_to_delta(region, mval_f, dvec, zfac);
/* Calculate view target position for dolly */
add_v3_v3v3(tvec, tpos, dvec);
@@ -2102,7 +2130,7 @@ static void viewzoom_apply_camera(ViewOpsData *vod,
float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->init.camzoom) * 2.0f;
float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
- zfac = viewzoom_scale_value_offset(&vod->ar->winrct,
+ zfac = viewzoom_scale_value_offset(&vod->region->winrct,
viewzoom,
zoom_invert,
true,
@@ -2119,12 +2147,12 @@ static void viewzoom_apply_camera(ViewOpsData *vod,
view_zoom_to_window_xy_camera(vod->scene,
vod->depsgraph,
vod->v3d,
- vod->ar,
+ vod->region,
zfac,
zoom_to_pos ? vod->prev.event_xy : NULL);
}
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
}
static void viewzoom_apply_3d(ViewOpsData *vod,
@@ -2138,7 +2166,7 @@ static void viewzoom_apply_3d(ViewOpsData *vod,
ED_view3d_dist_range_get(vod->v3d, dist_range);
- zfac = viewzoom_scale_value_offset(&vod->ar->winrct,
+ zfac = viewzoom_scale_value_offset(&vod->region->winrct,
viewzoom,
zoom_invert,
false,
@@ -2154,19 +2182,19 @@ static void viewzoom_apply_3d(ViewOpsData *vod,
const float zfac_max = dist_range[1] / vod->rv3d->dist;
CLAMP(zfac, zfac_min, zfac_max);
- view_zoom_to_window_xy_3d(vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
+ view_zoom_to_window_xy_3d(vod->region, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
}
/* these limits were in old code too */
CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]);
- if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->ar);
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->area, vod->region);
}
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
}
static void viewzoom_apply(ViewOpsData *vod,
@@ -2252,8 +2280,8 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
View3D *v3d;
RegionView3D *rv3d;
- ScrArea *sa;
- ARegion *ar;
+ ScrArea *area;
+ ARegion *region;
bool use_cam_zoom;
float dist_range[2];
@@ -2263,16 +2291,16 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
if (op->customdata) {
ViewOpsData *vod = op->customdata;
- sa = vod->sa;
- ar = vod->ar;
+ area = vod->area;
+ region = vod->region;
}
else {
- sa = CTX_wm_area(C);
- ar = CTX_wm_region(C);
+ area = CTX_wm_area(C);
+ region = CTX_wm_region(C);
}
- v3d = sa->spacedata.first;
- rv3d = ar->regiondata;
+ v3d = area->spacedata.first;
+ rv3d = region->regiondata;
use_cam_zoom = (rv3d->persp == RV3D_CAMOB) &&
!(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
@@ -2281,9 +2309,9 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
const int *zoom_xy = NULL;
if (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") :
- ar->winx / 2;
+ region->winx / 2;
zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") :
- ar->winy / 2;
+ region->winy / 2;
zoom_xy = zoom_xy_buf;
}
@@ -2293,28 +2321,28 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
const float step = 1.2f;
/* this min and max is also in viewmove() */
if (use_cam_zoom) {
- view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
}
else {
if (rv3d->dist < dist_range[1]) {
- view_zoom_to_window_xy_3d(ar, step, zoom_xy);
+ view_zoom_to_window_xy_3d(region, step, zoom_xy);
}
}
}
else {
const float step = 1.0f / 1.2f;
if (use_cam_zoom) {
- view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
}
else {
if (rv3d->dist > dist_range[0]) {
- view_zoom_to_window_xy_3d(ar, step, zoom_xy);
+ view_zoom_to_window_xy_3d(region, step, zoom_xy);
}
}
}
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar);
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(area, region);
}
ED_view3d_depth_tag_update(rv3d);
@@ -2322,7 +2350,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
viewops_data_free(C, op);
@@ -2345,7 +2373,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
vod = op->customdata;
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
/* if one or the other zoom position aren't set, set from event */
if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
@@ -2411,7 +2439,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
ot->invoke = viewzoom_invoke;
ot->exec = viewzoom_exec;
ot->modal = viewzoom_modal;
- ot->poll = ED_operator_region_view3d_active;
+ ot->poll = view3d_zoom_or_dolly_poll;
ot->cancel = viewzoom_cancel;
/* flags */
@@ -2444,14 +2472,14 @@ void viewdolly_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Dolly Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Dolly Modal", modal_items);
/* disabled mode switching for now, can re-implement better, later on */
#if 0
@@ -2477,9 +2505,9 @@ static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
}
}
-static void view_dolly_to_vector_3d(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac)
+static void view_dolly_to_vector_3d(ARegion *region, float orig_ofs[3], float dvec[3], float dfac)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac));
}
@@ -2491,12 +2519,12 @@ static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_
float len1, len2;
if (U.uiflag & USER_ZOOM_HORIZ) {
- len1 = (vod->ar->winrct.xmax - xy[0]) + 5;
- len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) + 5;
+ len1 = (vod->region->winrct.xmax - xy[0]) + 5;
+ len2 = (vod->region->winrct.xmax - vod->init.event_xy[0]) + 5;
}
else {
- len1 = (vod->ar->winrct.ymax - xy[1]) + 5;
- len2 = (vod->ar->winrct.ymax - vod->init.event_xy[1]) + 5;
+ len1 = (vod->region->winrct.ymax - xy[1]) + 5;
+ len2 = (vod->region->winrct.ymax - vod->init.event_xy[1]) + 5;
}
if (zoom_invert) {
SWAP(float, len1, len2);
@@ -2506,16 +2534,16 @@ static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_
}
if (zfac != 1.0f) {
- view_dolly_to_vector_3d(vod->ar, vod->init.ofs, vod->init.mousevec, zfac);
+ view_dolly_to_vector_3d(vod->region, vod->init.ofs, vod->init.mousevec, zfac);
}
- if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->ar);
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->area, vod->region);
}
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
}
static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -2575,8 +2603,8 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
{
View3D *v3d;
RegionView3D *rv3d;
- ScrArea *sa;
- ARegion *ar;
+ ScrArea *area;
+ ARegion *region;
float mousevec[3];
const int delta = RNA_int_get(op->ptr, "delta");
@@ -2584,19 +2612,19 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
if (op->customdata) {
ViewOpsData *vod = op->customdata;
- sa = vod->sa;
- ar = vod->ar;
+ area = vod->area;
+ region = vod->region;
copy_v3_v3(mousevec, vod->init.mousevec);
}
else {
- sa = CTX_wm_area(C);
- ar = CTX_wm_region(C);
- negate_v3_v3(mousevec, ((RegionView3D *)ar->regiondata)->viewinv[2]);
+ area = CTX_wm_area(C);
+ region = CTX_wm_region(C);
+ negate_v3_v3(mousevec, ((RegionView3D *)region->regiondata)->viewinv[2]);
normalize_v3(mousevec);
}
- v3d = sa->spacedata.first;
- rv3d = ar->regiondata;
+ v3d = area->spacedata.first;
+ rv3d = region->regiondata;
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
@@ -2605,17 +2633,17 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
normalize_v3_v3(mousevec, rv3d->viewinv[2]);
}
- view_dolly_to_vector_3d(ar, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f);
+ view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f);
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar);
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(area, region);
}
ED_view3d_depth_tag_update(rv3d);
ED_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
viewops_data_free(C, op);
@@ -2636,12 +2664,12 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
vod = op->customdata;
/* poll should check but in some cases fails, see poll func for details */
- if (vod->rv3d->viewlock & RV3D_LOCKED) {
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_ROTATION) {
viewops_data_free(C, op);
return OPERATOR_PASS_THROUGH;
}
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
/* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */
/* switch from camera view when: */
@@ -2654,7 +2682,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else {
vod->rv3d->persp = RV3D_PERSP;
}
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
}
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
@@ -2767,17 +2795,17 @@ static bool view3d_object_skip_minmax(const View3D *v3d,
static void view3d_from_minmax(bContext *C,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
const float min[3],
const float max[3],
bool ok_dist,
const int smooth_viewtx)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
float afm[3];
float size;
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
/* SMOOTHVIEW */
float new_ofs[3];
@@ -2811,7 +2839,7 @@ static void view3d_from_minmax(bContext *C,
if (ok_dist) {
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
new_dist = ED_view3d_radius_to_dist(
- v3d, ar, depsgraph, persp, true, (size / 2) * VIEW3D_MARGIN);
+ v3d, region, depsgraph, persp, true, (size / 2) * VIEW3D_MARGIN);
if (rv3d->is_persp) {
/* don't zoom closer than the near clipping plane */
new_dist = max_ff(new_dist, v3d->clip_start * 1.5f);
@@ -2826,7 +2854,7 @@ static void view3d_from_minmax(bContext *C,
rv3d->persp = RV3D_PERSP;
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.camera_old = v3d->camera,
@@ -2837,7 +2865,7 @@ static void view3d_from_minmax(bContext *C,
else {
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.ofs = new_ofs,
@@ -2858,15 +2886,15 @@ static void view3d_from_minmax_multi(bContext *C,
const bool ok_dist,
const int smooth_viewtx)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
/* when using all regions, don't jump out of camera view,
* but _do_ allow locked cameras to be moved */
if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
- view3d_from_minmax(C, v3d, ar, min, max, ok_dist, smooth_viewtx);
+ view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx);
}
}
}
@@ -2874,7 +2902,7 @@ static void view3d_from_minmax_multi(bContext *C,
static int view3d_all_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
Scene *scene = CTX_data_scene(C);
@@ -2882,7 +2910,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
Base *base_eval;
const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
- const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
+ const bool skip_camera = (ED_view3d_camera_lock_check(v3d, region->regiondata) ||
/* any one of the regions may be locked */
(use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
const bool center = RNA_boolean_get(op->ptr, "center");
@@ -2928,7 +2956,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
}
if (!changed) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
/* TODO - should this be cancel?
* I think no, because we always move the cursor, with or without
* object, but in this case there is no change in the scene,
@@ -2943,7 +2971,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx);
}
else {
- view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx);
+ view3d_from_minmax(C, v3d, region, min, max, true, smooth_viewtx);
}
return OPERATOR_FINISHED;
@@ -2952,7 +2980,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_view_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->description = "View all objects in scene";
ot->idname = "VIEW3D_OT_view_all";
@@ -2971,7 +2999,7 @@ void VIEW3D_OT_view_all(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Selected Operator
+/** \name Frame Selected Operator
*
* Move & Zoom the view to fit selected contents.
* \{ */
@@ -2979,7 +3007,7 @@ void VIEW3D_OT_view_all(wmOperatorType *ot)
/* like a localview without local!, was centerview() in 2.4x */
static int viewselected_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
Scene *scene = CTX_data_scene(C);
@@ -2989,12 +3017,12 @@ static int viewselected_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
const bGPdata *gpd_eval = ob_eval && (ob_eval->type == OB_GPENCIL) ? ob_eval->data : NULL;
const bool is_gp_edit = gpd_eval ? GPENCIL_ANY_MODE(gpd_eval) : false;
- const bool is_face_map = ((is_gp_edit == false) && ar->gizmo_map &&
- WM_gizmomap_is_any_selected(ar->gizmo_map));
+ const bool is_face_map = ((is_gp_edit == false) && region->gizmo_map &&
+ WM_gizmomap_is_any_selected(region->gizmo_map));
float min[3], max[3];
bool ok = false, ok_dist = true;
const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
- const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
+ const bool skip_camera = (ED_view3d_camera_lock_check(v3d, region->regiondata) ||
/* any one of the regions may be locked */
(use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
@@ -3038,7 +3066,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
}
}
else if (is_face_map) {
- ok = WM_gizmomap_minmax(ar->gizmo_map, true, true, min, max);
+ ok = WM_gizmomap_minmax(region->gizmo_map, true, true, min, max);
}
else if (obedit) {
/* only selected */
@@ -3101,7 +3129,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx);
}
else {
- view3d_from_minmax(C, v3d, ar, min, max, ok_dist, smooth_viewtx);
+ view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx);
}
return OPERATOR_FINISHED;
@@ -3110,13 +3138,13 @@ static int viewselected_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_view_selected(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Selected";
+ ot->name = "Frame Selected";
ot->description = "Move the view to the selection center";
ot->idname = "VIEW3D_OT_view_selected";
/* api callbacks */
ot->exec = viewselected_exec;
- ot->poll = ED_operator_region_view3d_active;
+ ot->poll = view3d_zoom_or_dolly_poll;
/* flags */
ot->flag = 0;
@@ -3177,7 +3205,7 @@ static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
if (v3d) {
ED_view3d_lock_clear(v3d);
- v3d->ob_centre = obact; /* can be NULL */
+ v3d->ob_center = obact; /* can be NULL */
if (obact && obact->type == OB_ARMATURE) {
if (obact->mode & OB_MODE_POSE) {
@@ -3185,13 +3213,13 @@ static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
bPoseChannel *pcham_act = BKE_pose_channel_active(obact_eval);
if (pcham_act) {
- BLI_strncpy(v3d->ob_centre_bone, pcham_act->name, sizeof(v3d->ob_centre_bone));
+ BLI_strncpy(v3d->ob_center_bone, pcham_act->name, sizeof(v3d->ob_center_bone));
}
}
else {
EditBone *ebone_act = ((bArmature *)obact->data)->act_edbone;
if (ebone_act) {
- BLI_strncpy(v3d->ob_centre_bone, ebone_act->name, sizeof(v3d->ob_centre_bone));
+ BLI_strncpy(v3d->ob_center_bone, ebone_act->name, sizeof(v3d->ob_center_bone));
}
}
}
@@ -3234,15 +3262,16 @@ static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
if (rv3d) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
/* non camera center */
float new_ofs[3];
negate_v3_v3(new_ofs, scene->cursor.location);
- ED_view3d_smooth_view(C, v3d, ar, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs});
+ ED_view3d_smooth_view(
+ C, v3d, region, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs});
/* smooth view does viewlock RV3D_BOXVIEW copy */
}
@@ -3259,7 +3288,7 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
/* api callbacks */
ot->exec = viewcenter_cursor_exec;
- ot->poll = ED_operator_view3d_active;
+ ot->poll = view3d_pan_poll;
/* flags */
ot->flag = 0;
@@ -3275,27 +3304,28 @@ static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *ev
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
if (rv3d) {
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
float new_ofs[3];
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(depsgraph, ar, v3d, event->mval, new_ofs, false, NULL)) {
+ if (ED_view3d_autodist(depsgraph, region, v3d, event->mval, new_ofs, false, NULL)) {
/* pass */
}
else {
/* fallback to simple pan */
negate_v3_v3(new_ofs, rv3d->ofs);
- ED_view3d_win_to_3d_int(v3d, ar, new_ofs, event->mval, new_ofs);
+ ED_view3d_win_to_3d_int(v3d, region, new_ofs, event->mval, new_ofs);
}
negate_v3(new_ofs);
- ED_view3d_smooth_view(C, v3d, ar, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs});
+ ED_view3d_smooth_view(
+ C, v3d, region, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs});
}
return OPERATOR_FINISHED;
@@ -3310,7 +3340,7 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
/* api callbacks */
ot->invoke = viewcenter_pick_invoke;
- ot->poll = ED_operator_view3d_active;
+ ot->poll = view3d_pan_poll;
/* flags */
ot->flag = 0;
@@ -3330,20 +3360,20 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op))
float size[2];
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
RegionView3D *rv3d;
/* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
- rv3d = ar->regiondata;
+ ED_view3d_context_user_region(C, &v3d, &region);
+ rv3d = region->regiondata;
rv3d->camdx = rv3d->camdy = 0.0f;
- ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
+ ED_view3d_calc_camera_border_size(scene, depsgraph, region, v3d, rv3d, size);
/* 4px is just a little room from the edge of the area */
- xfac = (float)ar->winx / (float)(size[0] + 4);
- yfac = (float)ar->winy / (float)(size[1] + 4);
+ xfac = (float)region->winx / (float)(size[0] + 4);
+ yfac = (float)region->winy / (float)(size[1] + 4);
rv3d->camzoom = BKE_screen_view3d_zoom_from_fac(min_ff(xfac, yfac));
CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
@@ -3409,7 +3439,7 @@ void VIEW3D_OT_view_center_lock(wmOperatorType *ot)
static int render_border_exec(bContext *C, wmOperator *op)
{
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = ED_view3d_context_rv3d(C);
Scene *scene = CTX_data_scene(C);
@@ -3424,13 +3454,13 @@ static int render_border_exec(bContext *C, wmOperator *op)
if (rv3d->persp == RV3D_CAMOB) {
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &vb, false);
}
else {
vb.xmin = 0;
vb.ymin = 0;
- vb.xmax = ar->winx;
- vb.ymax = ar->winy;
+ vb.xmax = region->winx;
+ vb.ymax = region->winy;
}
border.xmin = ((float)rect.xmin - vb.xmin) / BLI_rctf_size_x(&vb);
@@ -3562,7 +3592,7 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
@@ -3592,14 +3622,14 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
ED_view3d_dist_range_get(v3d, dist_range);
/* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(CTX_data_ensure_evaluated_depsgraph(C), ar, v3d, true);
+ ED_view3d_draw_depth(CTX_data_ensure_evaluated_depsgraph(C), region, v3d, true);
{
/* avoid allocating the whole depth buffer */
ViewDepths depth_temp = {0};
/* avoid view3d_update_depths() for speed. */
- view3d_update_depths_rect(ar, &depth_temp, &rect);
+ view3d_update_depths_rect(region, &depth_temp, &rect);
/* find the closest Z pixel */
depth_close = view3d_depth_near(&depth_temp);
@@ -3619,8 +3649,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* convert border to 3d coordinates */
- if ((!ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) ||
- (!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner))) {
+ if ((!ED_view3d_unproject(region, cent[0], cent[1], depth_close, p)) ||
+ (!ED_view3d_unproject(region, rect.xmin, rect.ymin, depth_close, p_corner))) {
return OPERATOR_CANCELLED;
}
@@ -3632,15 +3662,15 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
/* ignore dist_range min */
dist_range[0] = v3d->clip_start * 1.5f;
}
- else { /* othographic */
+ else { /* orthographic */
/* find the current window width and height */
- vb[0] = ar->winx;
- vb[1] = ar->winy;
+ vb[0] = region->winx;
+ vb[1] = region->winy;
new_dist = rv3d->dist;
/* convert the drawn rectangle into 3d space */
- if (depth_close != FLT_MAX && ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) {
+ if (depth_close != FLT_MAX && ED_view3d_unproject(region, cent[0], cent[1], depth_close, p)) {
negate_v3_v3(new_ofs, p);
}
else {
@@ -3658,7 +3688,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f;
mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f;
- ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
+ ED_view3d_win_to_delta(region, mval_f, dvec, zfac);
/* center the view to the center of the rectangle */
sub_v3_v3(new_ofs, dvec);
}
@@ -3687,15 +3717,15 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.ofs = new_ofs,
.dist = &new_dist,
});
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(CTX_wm_area(C), ar);
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(CTX_wm_area(C), region);
}
return OPERATOR_FINISHED;
@@ -3714,7 +3744,7 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
ot->modal = WM_gesture_box_modal;
ot->cancel = WM_gesture_box_cancel;
- ot->poll = ED_operator_region_view3d_active;
+ ot->poll = view3d_zoom_or_dolly_poll;
/* flags */
ot->flag = 0;
@@ -3733,14 +3763,14 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
static void view3d_set_1_to_1_viewborder(Scene *scene,
Depsgraph *depsgraph,
- ARegion *ar,
+ ARegion *region,
View3D *v3d)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
float size[2];
int im_width = (scene->r.size * scene->r.xsch) / 100;
- ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
+ ED_view3d_calc_camera_border_size(scene, depsgraph, region, v3d, rv3d, size);
rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0]);
CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
@@ -3752,12 +3782,12 @@ static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
/* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
+ ED_view3d_context_user_region(C, &v3d, &region);
- view3d_set_1_to_1_viewborder(scene, depsgraph, ar, v3d);
+ view3d_set_1_to_1_viewborder(scene, depsgraph, region, v3d);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
@@ -3802,14 +3832,15 @@ static const EnumPropertyItem prop_view_items[] = {
*/
static void axis_set_view(bContext *C,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
const float quat_[4],
- short view,
+ char view,
+ char view_axis_roll,
int perspo,
const float *align_to_quat,
const int smooth_viewtx)
{
- RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */
+ RegionView3D *rv3d = region->regiondata; /* no NULL check is needed, poll checks */
float quat[4];
const short orig_persp = rv3d->persp;
@@ -3818,14 +3849,16 @@ static void axis_set_view(bContext *C,
if (align_to_quat) {
mul_qt_qtqt(quat, quat, align_to_quat);
rv3d->view = view = RV3D_VIEW_USER;
+ rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
}
if (align_to_quat == NULL) {
rv3d->view = view;
+ rv3d->view_axis_roll = view_axis_roll;
}
- if (rv3d->viewlock & RV3D_LOCKED) {
- ED_region_tag_redraw(ar);
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) {
+ ED_region_tag_redraw(region);
return;
}
@@ -3840,7 +3873,7 @@ static void axis_set_view(bContext *C,
/* to camera */
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.camera_old = v3d->camera,
@@ -3862,7 +3895,7 @@ static void axis_set_view(bContext *C,
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.ofs = ofs,
@@ -3885,7 +3918,7 @@ static void axis_set_view(bContext *C,
/* no camera involved */
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.quat = quat,
@@ -3897,17 +3930,18 @@ static void axis_set_view(bContext *C,
static int view_axis_exec(bContext *C, wmOperator *op)
{
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
RegionView3D *rv3d;
static int perspo = RV3D_PERSP;
int viewnum;
+ int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
- rv3d = ar->regiondata;
+ ED_view3d_context_user_region(C, &v3d, &region);
+ rv3d = region->regiondata;
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
viewnum = RNA_enum_get(op->ptr, "type");
@@ -3928,58 +3962,74 @@ static int view_axis_exec(bContext *C, wmOperator *op)
}
if (RNA_boolean_get(op->ptr, "relative")) {
- float z_rel[3];
+ float quat_rotate[4];
+ float quat_test[4];
- if (viewnum == RV3D_VIEW_RIGHT) {
- negate_v3_v3(z_rel, rv3d->viewinv[0]);
+ if (viewnum == RV3D_VIEW_LEFT) {
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI / 2.0f);
}
- else if (viewnum == RV3D_VIEW_LEFT) {
- copy_v3_v3(z_rel, rv3d->viewinv[0]);
+ else if (viewnum == RV3D_VIEW_RIGHT) {
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI / 2.0f);
}
else if (viewnum == RV3D_VIEW_TOP) {
- negate_v3_v3(z_rel, rv3d->viewinv[1]);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI / 2.0f);
}
else if (viewnum == RV3D_VIEW_BOTTOM) {
- copy_v3_v3(z_rel, rv3d->viewinv[1]);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI / 2.0f);
}
else if (viewnum == RV3D_VIEW_FRONT) {
- negate_v3_v3(z_rel, rv3d->viewinv[2]);
+ unit_qt(quat_rotate);
}
else if (viewnum == RV3D_VIEW_BACK) {
- copy_v3_v3(z_rel, rv3d->viewinv[2]);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI);
}
else {
BLI_assert(0);
}
- float angle_max = FLT_MAX;
- int view_closest = -1;
+ mul_qt_qtqt(quat_test, rv3d->viewquat, quat_rotate);
+
+ float angle_best = FLT_MAX;
+ int view_best = -1;
+ int view_axis_roll_best = -1;
for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) {
- float quat[4];
- float mat[3][3];
- ED_view3d_quat_from_axis_view(i, quat);
- quat[0] *= -1.0f;
- quat_to_mat3(mat, quat);
- if (align_quat) {
- mul_qt_qtqt(quat, quat, align_quat);
- }
- const float angle_test = angle_normalized_v3v3(z_rel, mat[2]);
- if (angle_max > angle_test) {
- angle_max = angle_test;
- view_closest = i;
+ for (int j = RV3D_VIEW_AXIS_ROLL_0; j <= RV3D_VIEW_AXIS_ROLL_270; j++) {
+ float quat_axis[4];
+ ED_view3d_quat_from_axis_view(i, j, quat_axis);
+ if (align_quat) {
+ mul_qt_qtqt(quat_axis, quat_axis, align_quat);
+ }
+ const float angle_test = fabsf(angle_signed_qtqt(quat_axis, quat_test));
+ if (angle_best > angle_test) {
+ angle_best = angle_test;
+ view_best = i;
+ view_axis_roll_best = j;
+ }
}
}
- if (view_closest == -1) {
- view_closest = RV3D_VIEW_FRONT;
+ if (view_best == -1) {
+ view_best = RV3D_VIEW_FRONT;
+ view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
}
- viewnum = view_closest;
+
+ /* Disallow non-upright views in turn-table modes,
+ * it's too difficult to navigate out of them. */
+ if ((U.flag & USER_TRACKBALL) == 0) {
+ if (!ELEM(view_best, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
+ view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
+ }
+ }
+
+ viewnum = view_best;
+ view_axis_roll = view_axis_roll_best;
}
/* Use this to test if we started out with a camera */
const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo;
float quat[4];
- ED_view3d_quat_from_axis_view(viewnum, quat);
- axis_set_view(C, v3d, ar, quat, viewnum, nextperspo, align_quat, smooth_viewtx);
+ ED_view3d_quat_from_axis_view(viewnum, view_axis_roll, quat);
+ axis_set_view(
+ C, v3d, region, quat, viewnum, view_axis_roll, nextperspo, align_quat, smooth_viewtx);
perspo = rv3d->persp;
@@ -4021,17 +4071,17 @@ void VIEW3D_OT_view_axis(wmOperatorType *ot)
static int view_camera_exec(bContext *C, wmOperator *op)
{
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
RegionView3D *rv3d;
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
- rv3d = ar->regiondata;
+ ED_view3d_context_user_region(C, &v3d, &region);
+ rv3d = region->regiondata;
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
/* lastview - */
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -4092,7 +4142,7 @@ static int view_camera_exec(bContext *C, wmOperator *op)
rv3d->persp = RV3D_CAMOB;
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.camera = v3d->camera,
@@ -4105,7 +4155,15 @@ static int view_camera_exec(bContext *C, wmOperator *op)
else {
/* return to settings of last view */
/* does view3d_smooth_view too */
- axis_set_view(C, v3d, ar, rv3d->lviewquat, rv3d->lview, rv3d->lpersp, NULL, smooth_viewtx);
+ axis_set_view(C,
+ v3d,
+ region,
+ rv3d->lviewquat,
+ rv3d->lview,
+ rv3d->lview_axis_roll,
+ rv3d->lpersp,
+ NULL,
+ smooth_viewtx);
}
}
@@ -4153,7 +4211,7 @@ static const EnumPropertyItem prop_view_orbit_items[] = {
static int vieworbit_exec(bContext *C, wmOperator *op)
{
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
RegionView3D *rv3d;
int orbitdir;
char view_opposite;
@@ -4164,23 +4222,23 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
/* no NULL check is needed, poll checks */
v3d = CTX_wm_view3d(C);
- ar = CTX_wm_region(C);
- rv3d = ar->regiondata;
+ region = CTX_wm_region(C);
+ rv3d = region->regiondata;
/* support for switching to the opposite view (even when in locked views) */
view_opposite = (fabsf(angle) == (float)M_PI) ? ED_view3d_axis_view_opposite(rv3d->view) :
RV3D_VIEW_USER;
orbitdir = RNA_enum_get(op->ptr, "type");
- if ((rv3d->viewlock & RV3D_LOCKED) && (view_opposite == RV3D_VIEW_USER)) {
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) && (view_opposite == RV3D_VIEW_USER)) {
/* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
- rv3d = ar->regiondata;
+ ED_view3d_context_user_region(C, &v3d, &region);
+ rv3d = region->regiondata;
}
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
- if ((rv3d->viewlock & RV3D_LOCKED) == 0 || (view_opposite != RV3D_VIEW_USER)) {
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0 || (view_opposite != RV3D_VIEW_USER)) {
if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
float quat_mul[4];
@@ -4188,7 +4246,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
if (view_opposite == RV3D_VIEW_USER) {
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ED_view3d_persp_ensure(depsgraph, v3d, ar);
+ ED_view3d_persp_ensure(depsgraph, v3d, region);
}
if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
@@ -4217,7 +4275,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
if (view_opposite != RV3D_VIEW_USER) {
rv3d->view = view_opposite;
/* avoid float in-precision, just get a new orientation */
- ED_view3d_quat_from_axis_view(view_opposite, quat_new);
+ ED_view3d_quat_from_axis_view(view_opposite, rv3d->view_axis_roll, quat_new);
}
else {
rv3d->view = RV3D_VIEW_USER;
@@ -4234,7 +4292,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.quat = quat_new,
@@ -4279,9 +4337,9 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
* \{ */
static void view_roll_angle(
- ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
+ ARegion *region, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
float quat_mul[4];
/* camera axis */
@@ -4302,14 +4360,14 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
{
float len1, len2, tot;
- tot = vod->ar->winrct.xmax - vod->ar->winrct.xmin;
- len1 = (vod->ar->winrct.xmax - x) / tot;
- len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) / tot;
+ tot = vod->region->winrct.xmax - vod->region->winrct.xmin;
+ len1 = (vod->region->winrct.xmax - x) / tot;
+ len2 = (vod->region->winrct.xmax - vod->init.event_xy[0]) / tot;
angle = (len1 - len2) * (float)M_PI * 4.0f;
}
if (angle != 0.0f) {
- view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle);
+ view_roll_angle(vod->region, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle);
}
if (vod->use_dyn_ofs) {
@@ -4317,13 +4375,13 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs);
}
- if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->ar);
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->area, vod->region);
}
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
- ED_region_tag_redraw(vod->ar);
+ ED_region_tag_redraw(vod->region);
}
static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -4390,21 +4448,21 @@ static int viewroll_exec(bContext *C, wmOperator *op)
{
View3D *v3d;
RegionView3D *rv3d;
- ARegion *ar;
+ ARegion *region;
if (op->customdata) {
ViewOpsData *vod = op->customdata;
- ar = vod->ar;
+ region = vod->region;
v3d = vod->v3d;
}
else {
- ED_view3d_context_user_region(C, &v3d, &ar);
+ ED_view3d_context_user_region(C, &v3d, &region);
}
- rv3d = ar->regiondata;
+ rv3d = region->regiondata;
if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
- ED_view3d_smooth_view_force_finish(C, v3d, ar);
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
int type = RNA_enum_get(op->ptr, "type");
float angle = (type == 0) ? RNA_float_get(op->ptr, "angle") : DEG2RADF(U.pad_rot_angle);
@@ -4419,7 +4477,7 @@ static int viewroll_exec(bContext *C, wmOperator *op)
normalize_v3_v3(mousevec, rv3d->viewinv[2]);
negate_v3(mousevec);
- view_roll_angle(ar, quat_new, rv3d->viewquat, mousevec, angle);
+ view_roll_angle(region, quat_new, rv3d->viewquat, mousevec, angle);
const float *dyn_ofs_pt = NULL;
float dyn_ofs[3];
@@ -4432,7 +4490,7 @@ static int viewroll_exec(bContext *C, wmOperator *op)
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.quat = quat_new,
@@ -4463,7 +4521,7 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
viewops_data_create(C, op, event, viewops_flag_from_prefs());
vod = op->customdata;
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
/* overwrite the mouse vector with the view direction */
normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
@@ -4586,7 +4644,7 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
/* api callbacks */
ot->invoke = viewpan_invoke;
- ot->poll = ED_operator_region_view3d_active;
+ ot->poll = view3d_pan_poll;
/* flags */
ot->flag = 0;
@@ -4605,21 +4663,22 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d_dummy;
- ARegion *ar;
+ ARegion *region;
RegionView3D *rv3d;
/* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d_dummy, &ar);
- rv3d = ar->regiondata;
+ ED_view3d_context_user_region(C, &v3d_dummy, &region);
+ rv3d = region->regiondata;
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ /* Could add a separate lock flag for locking persp. */
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
if (rv3d->persp != RV3D_ORTHO) {
rv3d->persp = RV3D_ORTHO;
}
else {
rv3d->persp = RV3D_PERSP;
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
return OPERATOR_FINISHED;
@@ -4845,7 +4904,7 @@ void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[4][4])
static int view3d_clipping_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
rcti rect;
@@ -4855,7 +4914,7 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb");
/* NULL object because we don't want it in object space */
- ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect);
+ ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, region, NULL, &rect);
return OPERATOR_FINISHED;
}
@@ -4863,11 +4922,11 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
static int view3d_clipping_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
if (rv3d->rflag & RV3D_CLIPPING) {
rv3d->rflag &= ~RV3D_CLIPPING;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
if (rv3d->clipbb) {
MEM_freeN(rv3d->clipbb);
}
@@ -4915,9 +4974,9 @@ void ED_view3d_cursor3d_position(bContext *C,
const bool use_depth,
float cursor_co[3])
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
bool flip;
bool depth_used = false;
@@ -4940,7 +4999,7 @@ void ED_view3d_cursor3d_position(bContext *C,
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(depsgraph, ar, v3d, mval, cursor_co, true, NULL)) {
+ if (ED_view3d_autodist(depsgraph, region, v3d, mval, cursor_co, true, NULL)) {
depth_used = true;
}
}
@@ -4948,7 +5007,7 @@ void ED_view3d_cursor3d_position(bContext *C,
if (depth_used == false) {
float depth_pt[3];
copy_v3_v3(depth_pt, cursor_co);
- ED_view3d_win_to_3d_int(v3d, ar, depth_pt, mval, cursor_co);
+ ED_view3d_win_to_3d_int(v3d, region, depth_pt, mval, cursor_co);
}
}
@@ -4962,8 +5021,8 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
/* XXX, caller should check. */
if (rv3d == NULL) {
@@ -4993,12 +5052,13 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
float ray_co[3];
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, scene, CTX_data_ensure_evaluated_depsgraph(C), 0, ar, v3d);
+ bmain, scene, 0, region, v3d);
float obmat[4][4];
Object *ob_dummy = NULL;
float dist_px = 0;
if (ED_transform_snap_object_project_view3d_ex(snap_context,
+ CTX_data_ensure_evaluated_depsgraph(C),
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
@@ -5075,8 +5135,8 @@ void ED_view3d_cursor3d_update(bContext *C,
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
View3DCursor *cursor_curr = &scene->cursor;
View3DCursor cursor_prev = *cursor_curr;
@@ -5104,17 +5164,17 @@ void ED_view3d_cursor3d_update(bContext *C,
}
/* offset the cursor lock to avoid jumping to new offset */
- if (v3d->ob_centre_cursor) {
+ if (v3d->ob_center_cursor) {
if (U.uiflag & USER_LOCK_CURSOR_ADJUST) {
float co_2d_curr[2], co_2d_prev[2];
if ((ED_view3d_project_float_global(
- ar, cursor_prev.location, co_2d_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
+ region, cursor_prev.location, co_2d_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
(ED_view3d_project_float_global(
- ar, cursor_curr->location, co_2d_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) {
- rv3d->ofs_lock[0] += (co_2d_curr[0] - co_2d_prev[0]) / (ar->winx * 0.5f);
- rv3d->ofs_lock[1] += (co_2d_curr[1] - co_2d_prev[1]) / (ar->winy * 0.5f);
+ region, cursor_curr->location, co_2d_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) {
+ rv3d->ofs_lock[0] += (co_2d_curr[0] - co_2d_prev[0]) / (region->winx * 0.5f);
+ rv3d->ofs_lock[1] += (co_2d_curr[1] - co_2d_prev[1]) / (region->winy * 0.5f);
}
}
else {
@@ -5219,7 +5279,7 @@ static int toggle_shading_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
View3D *v3d = CTX_wm_view3d(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
int type = RNA_enum_get(op->ptr, "type");
if (type == OB_SOLID) {
@@ -5247,7 +5307,7 @@ static int toggle_shading_exec(bContext *C, wmOperator *op)
}
}
- ED_view3d_shade_update(bmain, v3d, sa);
+ ED_view3d_shade_update(bmain, v3d, area);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
return OPERATOR_FINISHED;
@@ -5280,7 +5340,7 @@ void VIEW3D_OT_toggle_shading(wmOperatorType *ot)
static int toggle_xray_exec(bContext *C, wmOperator *op)
{
View3D *v3d = CTX_wm_view3d(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Object *obact = CTX_data_active_object(C);
if (obact && ((obact->mode & OB_MODE_POSE) ||
@@ -5302,7 +5362,7 @@ static int toggle_xray_exec(bContext *C, wmOperator *op)
}
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
@@ -5312,6 +5372,7 @@ void VIEW3D_OT_toggle_xray(wmOperatorType *ot)
/* identifiers */
ot->name = "Toggle X-Ray";
ot->idname = "VIEW3D_OT_toggle_xray";
+ ot->description = "Transparent scene display. Allow selecting through items";
/* api callbacks */
ot->exec = toggle_xray_exec;
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 903d6231b22..06d1a033a0d 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -30,8 +30,8 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -125,14 +125,14 @@ void fly_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Fly Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Fly Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Fly Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Fly Modal", modal_items);
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly");
@@ -142,7 +142,7 @@ typedef struct FlyInfo {
/* context stuff */
RegionView3D *rv3d;
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
struct Depsgraph *depsgraph;
Scene *scene;
@@ -211,7 +211,7 @@ static void flyApply_ndof(bContext *C, FlyInfo *fly, bool is_confirm);
#endif /* WITH_INPUT_NDOF */
static int flyApply(bContext *C, struct FlyInfo *fly, bool force_autokey);
-static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
{
FlyInfo *fly = arg;
rctf viewborder;
@@ -220,7 +220,7 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
if (ED_view3d_cameracontrol_object_get(fly->v3d_camera_control)) {
ED_view3d_calc_camera_border(
- fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
+ fly->scene, fly->depsgraph, fly->region, fly->v3d, fly->rv3d, &viewborder, false);
xoff = viewborder.xmin;
yoff = viewborder.ymin;
}
@@ -242,7 +242,7 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor3(TH_VIEW_OVERLAY);
immBegin(GPU_PRIM_LINES, 16);
@@ -296,7 +296,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->rv3d = CTX_wm_region_view3d(C);
fly->v3d = CTX_wm_view3d(C);
- fly->ar = CTX_wm_region(C);
+ fly->region = CTX_wm_region(C);
fly->depsgraph = CTX_data_expect_evaluated_depsgraph(C);
fly->scene = CTX_data_scene(C);
@@ -353,7 +353,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer();
fly->draw_handle_pixel = ED_region_draw_cb_activate(
- fly->ar->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL);
+ fly->region->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL);
fly->rv3d->rflag |= RV3D_NAVIGATING;
@@ -371,7 +371,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
/* calculate center */
if (ED_view3d_cameracontrol_object_get(fly->v3d_camera_control)) {
ED_view3d_calc_camera_border(
- fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
+ fly->scene, fly->depsgraph, fly->region, fly->v3d, fly->rv3d, &viewborder, false);
fly->width = BLI_rctf_size_x(&viewborder);
fly->height = BLI_rctf_size_y(&viewborder);
@@ -380,16 +380,17 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->center_mval[1] = viewborder.ymin + fly->height / 2;
}
else {
- fly->width = fly->ar->winx;
- fly->height = fly->ar->winy;
+ fly->width = fly->region->winx;
+ fly->height = fly->region->winy;
fly->center_mval[0] = fly->width / 2;
fly->center_mval[1] = fly->height / 2;
}
/* center the mouse, probably the UI mafia are against this but without its quite annoying */
- WM_cursor_warp(
- win, fly->ar->winrct.xmin + fly->center_mval[0], fly->ar->winrct.ymin + fly->center_mval[1]);
+ WM_cursor_warp(win,
+ fly->region->winrct.xmin + fly->center_mval[0],
+ fly->region->winrct.ymin + fly->center_mval[1]);
return 1;
}
@@ -424,7 +425,7 @@ static int flyEnd(bContext *C, FlyInfo *fly)
WM_event_remove_timer(CTX_wm_manager(C), win, fly->timer);
- ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel);
+ ED_region_draw_cb_exit(fly->region->type, fly->draw_handle_pixel);
ED_view3d_cameracontrol_release(fly->v3d_camera_control, fly->state == FLY_CANCEL);
@@ -592,7 +593,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
}
else {
/* flip speed rather than stopping, game like motion,
- * else increase like mousewheel if were already moving in that direction */
+ * else increase like mousewheel if we're already moving in that direction */
if (fly->speed < 0.0f) {
fly->speed = -fly->speed;
}
@@ -786,7 +787,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
}
/* scale the mouse movement by this value - scales mouse movement to the view size
- * moffset[0] / (ar->winx-xmargin * 2) - window size minus margin (same for y)
+ * moffset[0] / (region->winx-xmargin * 2) - window size minus margin (same for y)
*
* the mouse moves isn't linear */
@@ -1038,7 +1039,7 @@ static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
FlyInfo *fly;
- if (rv3d->viewlock & RV3D_LOCKED) {
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
index dbad06da5ec..ee512a5f726 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
@@ -22,18 +22,18 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BKE_armature.h"
#include "BKE_action.h"
+#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_layer.h"
#include "BKE_object.h"
-#include "DNA_object_types.h"
#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
#include "ED_armature.h"
-#include "ED_screen.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index ba5ca5fbd15..a9928fa2dc0 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -26,12 +26,12 @@
#include "BKE_context.h"
#include "BKE_layer.h"
-#include "DNA_object_types.h"
#include "DNA_camera_types.h"
+#include "DNA_object_types.h"
#include "ED_armature.h"
-#include "ED_screen.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
#include "UI_resources.h"
@@ -40,8 +40,8 @@
#include "RNA_access.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "DEG_depsgraph.h"
@@ -253,13 +253,13 @@ static void WIDGETGROUP_camera_message_subscribe(const bContext *C,
wmGizmoGroup *gzgroup,
struct wmMsgBus *mbus)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
Camera *ca = ob->data;
wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
+ .owner = region,
.user_data = gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
};
@@ -403,8 +403,8 @@ static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UN
return false;
}
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
if (rv3d->persp == RV3D_CAMOB) {
if (scene->r.mode & R_BORDER) {
/* TODO: support overrides. */
@@ -432,6 +432,8 @@ static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmGizmoGrou
/* Box style is more subtle in this case. */
RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_BOX);
+ WM_gizmo_set_scale(viewgroup->border, 10.0f / 0.15f);
+
gzgroup->customdata = viewgroup;
}
@@ -439,22 +441,22 @@ static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmGizmoGroup
{
struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* Drawing code should happen with fully evaluated graph. */
struct Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (rv3d->persp == RV3D_CAMOB) {
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
ED_view3d_calc_camera_border(
- scene, depsgraph, ar, v3d, rv3d, &viewgroup->state.view_border, false);
+ scene, depsgraph, region, v3d, rv3d, &viewgroup->state.view_border, false);
}
else {
viewgroup->state.view_border = (rctf){
.xmin = 0,
.ymin = 0,
- .xmax = ar->winx,
- .ymax = ar->winy,
+ .xmax = region->winx,
+ .ymax = region->winy,
};
}
@@ -471,8 +473,8 @@ static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmGizmoGroup *gzg
struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata;
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
Scene *scene = CTX_data_scene(C);
viewgroup->scene = scene;
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
index 793aec42dcd..7f677d88921 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
@@ -22,17 +22,17 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_image.h"
#include "BKE_layer.h"
#include "BKE_object.h"
-#include "BKE_image.h"
#include "DEG_depsgraph.h"
-#include "DNA_object_types.h"
#include "DNA_light_types.h"
+#include "DNA_object_types.h"
-#include "ED_screen.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
index 90b1539c8a7..242a0a802a6 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
@@ -24,11 +24,11 @@
#include "BKE_layer.h"
#include "BKE_object.h"
-#include "DNA_object_types.h"
#include "DNA_object_force_types.h"
+#include "DNA_object_types.h"
-#include "ED_screen.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c
index 890de0ae611..5bf105b6775 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_light.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c
@@ -27,11 +27,11 @@
#include "DEG_depsgraph.h"
-#include "DNA_object_types.h"
#include "DNA_light_types.h"
+#include "DNA_object_types.h"
-#include "ED_screen.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
index 53a5609d437..533fba3795b 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
@@ -26,8 +26,8 @@
#include "DNA_object_types.h"
-#include "ED_screen.h"
#include "ED_gizmo_library.h"
+#include "ED_screen.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -239,27 +239,27 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
struct NavigateWidgetGroup *navgroup = gzgroup->customdata;
- ARegion *ar = CTX_wm_region(C);
- const RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ const RegionView3D *rv3d = region->regiondata;
for (int i = 0; i < 3; i++) {
copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
}
- const rcti *rect_visible = ED_region_visible_rect(ar);
+ const rcti *rect_visible = ED_region_visible_rect(region);
if ((navgroup->state.rect_visible.xmax == rect_visible->xmax) &&
(navgroup->state.rect_visible.ymax == rect_visible->ymax) &&
(navgroup->state.rv3d.is_persp == rv3d->is_persp) &&
(navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) &&
- (navgroup->state.rv3d.viewlock == rv3d->viewlock)) {
+ (navgroup->state.rv3d.viewlock == RV3D_LOCK_FLAGS(rv3d))) {
return;
}
navgroup->state.rect_visible = *rect_visible;
navgroup->state.rv3d.is_persp = rv3d->is_persp;
navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB);
- navgroup->state.rv3d.viewlock = rv3d->viewlock;
+ navgroup->state.rv3d.viewlock = RV3D_LOCK_FLAGS(rv3d);
const bool show_navigate = (U.uiflag & USER_SHOW_GIZMO_NAVIGATE) != 0;
const bool show_rotate_gizmo = (U.mini_axis_type == USER_MINI_AXIS_TYPE_GIZMO);
@@ -285,8 +285,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
}
const float co[2] = {
- rect_visible->xmax - icon_offset_mini * 0.75f,
- rect_visible->ymax - icon_offset_from_axis,
+ roundf(rect_visible->xmax - icon_offset_mini * 0.75f),
+ roundf(rect_visible->ymax - icon_offset_from_axis),
};
wmGizmo *gz;
@@ -296,7 +296,6 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
- /* RV3D_LOCKED or Camera: only show supported buttons. */
if (show_rotate_gizmo) {
gz = navgroup->gz_array[GZ_INDEX_ROTATE];
gz->matrix_basis[3][0] = co_rotate[0];
@@ -306,26 +305,30 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
if (show_navigate) {
int icon_mini_slot = 0;
- gz = navgroup->gz_array[GZ_INDEX_ZOOM];
- gz->matrix_basis[3][0] = co[0];
- gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ZOOM_AND_DOLLY) == 0) {
+ gz = navgroup->gz_array[GZ_INDEX_ZOOM];
+ gz->matrix_basis[3][0] = roundf(co[0]);
+ gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ }
- gz = navgroup->gz_array[GZ_INDEX_MOVE];
- gz->matrix_basis[3][0] = co[0];
- gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_LOCATION) == 0) {
+ gz = navgroup->gz_array[GZ_INDEX_MOVE];
+ gz->matrix_basis[3][0] = roundf(co[0]);
+ gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ }
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
gz = navgroup->gz_array[GZ_INDEX_CAMERA];
- gz->matrix_basis[3][0] = co[0];
- gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][0] = roundf(co[0]);
+ gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
if (navgroup->state.rv3d.is_camera == false) {
gz = navgroup->gz_array[rv3d->is_persp ? GZ_INDEX_PERSP : GZ_INDEX_ORTHO];
- gz->matrix_basis[3][0] = co[0];
- gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][0] = roundf(co[0]);
+ gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
index 75ab6518a4f..3301e28c90c 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
@@ -33,12 +33,12 @@
#include "BKE_context.h"
+#include "GPU_batch.h"
+#include "GPU_batch_presets.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
-#include "GPU_batch.h"
-#include "GPU_batch_presets.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -197,7 +197,8 @@ static void axis_geom_draw(const wmGizmo *gz,
const bool select,
const struct AxisDrawInfo *draw_info)
{
- GPU_line_width(gz->line_width);
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
GPUVertFormat *format = immVertexFormat();
const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
@@ -239,6 +240,7 @@ static void axis_geom_draw(const wmGizmo *gz,
static float axis_color[3][4];
const float axis_depth_bias = 0.01f;
+ const float sphere_scale = 1.15f;
#ifdef USE_AXIS_FONT
struct {
@@ -268,6 +270,13 @@ static void axis_geom_draw(const wmGizmo *gz,
/* When the cursor is over any of the gizmos (show circle backdrop). */
const bool is_active = (color[3] != 0.0f);
+ const float clip_range = gz->scale_final * sphere_scale;
+ bool use_project_matrix = (clip_range >= -GPU_MATRIX_ORTHO_CLIP_NEAR_DEFAULT);
+ if (use_project_matrix) {
+ GPU_matrix_push_projection();
+ GPU_matrix_ortho_set_z(-clip_range, clip_range);
+ }
+
/* Circle defining active area. */
if (is_active) {
immUniformColor4fv(color);
@@ -332,8 +341,13 @@ static void axis_geom_draw(const wmGizmo *gz,
/* Axis Line. */
if (is_pos) {
float v_start[3];
- GPU_line_width(2.0f);
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", 2.0f * U.pixelsize);
immUniformColor4fv(is_pos_color ? color_current : color_current_fade);
+
immBegin(GPU_PRIM_LINES, 2);
if (axis_align == -1) {
zero_v3(v_start);
@@ -349,6 +363,10 @@ static void axis_geom_draw(const wmGizmo *gz,
immVertex3fv(pos_id, v_start);
immVertex3fv(pos_id, v_final);
immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
}
/* Axis Ball. */
@@ -364,11 +382,10 @@ static void axis_geom_draw(const wmGizmo *gz,
* they use a faded color which can be similar to the circle backdrop in tone. */
if (is_active && !is_highlight && !is_pos && !select && !(axis_align == axis)) {
static const float axis_black_faded[4] = {0, 0, 0, 0.2f};
- const float scale = 1.15f;
- GPU_matrix_scale_1f(scale);
+ GPU_matrix_scale_1f(sphere_scale);
GPU_batch_uniform_4fv(sphere, "color", axis_black_faded);
GPU_batch_draw(sphere);
- GPU_matrix_scale_1f(1.0 / scale);
+ GPU_matrix_scale_1f(1.0 / sphere_scale);
}
GPU_batch_uniform_4fv(sphere, "color", is_pos_color ? color_current : color_current_fade);
@@ -407,6 +424,10 @@ static void axis_geom_draw(const wmGizmo *gz,
GPU_matrix_pop();
immUnbindProgram();
+
+ if (use_project_matrix) {
+ GPU_matrix_pop_projection();
+ }
}
static void axis3d_draw_intern(const bContext *C,
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c
index b9dc287b9cb..3f07653fb2f 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c
@@ -30,8 +30,8 @@
#include "UI_resources.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "view3d_intern.h" /* own include */
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 68159e2d684..30212fcd9e5 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
@@ -31,8 +31,8 @@
#include "DNA_mesh_types.h"
#include "BKE_context.h"
-#include "BKE_layer.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -45,10 +45,10 @@
#include "bmesh.h"
-#include "ED_screen.h"
+#include "ED_gizmo_library.h"
#include "ED_mesh.h"
+#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_gizmo_library.h"
/* -------------------------------------------------------------------- */
/** \name Mesh Element (Vert/Edge/Face) Pre-Select Gizmo API
@@ -158,7 +158,7 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
float vert_p_co[3], vert_co[3];
float mval_f[2] = {UNPACK2(vc.mval)};
mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->obmat, vert->co);
- ED_view3d_project(vc.ar, vert_co, vert_p_co);
+ ED_view3d_project(vc.region, vert_co, vert_p_co);
float len = len_v2v2(vert_p_co, mval_f);
if (len < 35) {
best.ele = (BMElem *)eve_test;
@@ -226,8 +226,8 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
RNA_int_set(gz->ptr, "face_index", gz_ele->face_index);
if (best.ele) {
- ARegion *ar = CTX_wm_region(C);
- ED_region_tag_redraw(ar);
+ ARegion *region = CTX_wm_region(C);
+ ED_region_tag_redraw_editor_overlays(region);
}
// return best.eed ? 0 : -1;
@@ -382,8 +382,8 @@ static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const
RNA_int_set(gz->ptr, "object_index", gz_ring->base_index);
RNA_int_set(gz->ptr, "edge_index", gz_ring->edge_index);
- ARegion *ar = CTX_wm_region(C);
- ED_region_tag_redraw(ar);
+ ARegion *region = CTX_wm_region(C);
+ ED_region_tag_redraw_editor_overlays(region);
}
// return best.eed ? 0 : -1;
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index e53957b054d..e4863c0cdeb 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -19,9 +19,9 @@
*/
#include "BLI_listbase.h"
-#include "BLI_string.h"
-#include "BLI_rect.h"
#include "BLI_math.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -31,13 +31,13 @@
#include "BKE_main.h"
#include "BKE_report.h"
+#include "BKE_material.h"
#include "BKE_object.h"
#include "BKE_unit.h"
-#include "BKE_material.h"
+#include "DNA_gpencil_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "DNA_gpencil_types.h"
#include "DNA_view3d_types.h"
#include "ED_gizmo_utils.h"
@@ -46,16 +46,16 @@
#include "ED_transform_snap_object_context.h"
#include "ED_view3d.h"
-#include "UI_resources.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "view3d_intern.h" /* own include */
@@ -110,8 +110,8 @@ typedef struct RulerInfo {
/* wm state */
wmWindow *win;
- ScrArea *sa;
- ARegion *ar; /* re-assigned every modal update */
+ ScrArea *area;
+ ARegion *region; /* re-assigned every modal update */
/* Track changes in state. */
struct {
@@ -201,7 +201,7 @@ static bool view3d_ruler_pick(wmGizmoGroup *gzgroup,
int *r_co_index)
{
RulerInfo *ruler_info = gzgroup->customdata;
- ARegion *ar = ruler_info->ar;
+ ARegion *region = ruler_info->region;
bool found = false;
float dist_best = RULER_PICK_DIST_SQ;
@@ -214,7 +214,7 @@ static bool view3d_ruler_pick(wmGizmoGroup *gzgroup,
/* should these be checked? - ok for now not to */
for (j = 0; j < 3; j++) {
- ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(region, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
}
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
@@ -288,12 +288,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
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_ensure_evaluated_depsgraph(C),
- 0,
- ruler_info->ar,
- CTX_wm_view3d(C));
+ bmain, CTX_data_scene(C), 0, ruler_info->region, CTX_wm_view3d(C));
}
else {
BLI_assert(0);
@@ -304,11 +299,12 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3], const int xy[2])
{
- ED_view3d_win_to_3d_int(ruler_info->sa->spacedata.first, ruler_info->ar, r_co, xy, r_co);
+ ED_view3d_win_to_3d_int(ruler_info->area->spacedata.first, ruler_info->region, r_co, xy, r_co);
}
/* use for mousemove events */
-static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
+static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
+ RulerInfo *ruler_info,
RulerItem *ruler_item,
const int mval[2],
const bool do_thickness,
@@ -327,7 +323,7 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
view3d_ruler_item_project(ruler_info, co, mval);
if (do_thickness && inter->co_index != 1) {
// Scene *scene = CTX_data_scene(C);
- // View3D *v3d = ruler_info->sa->spacedata.first;
+ // View3D *v3d = ruler_info->area->spacedata.first;
const float mval_fl[2] = {UNPACK2(mval)};
float ray_normal[3];
float ray_start[3];
@@ -336,6 +332,7 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0];
if (ED_transform_snap_object_project_view3d(ruler_info->snap_context,
+ depsgraph,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
@@ -350,6 +347,7 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
/* add some bias */
madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias);
ED_transform_snap_object_project_ray(ruler_info->snap_context,
+ depsgraph,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,
@@ -379,6 +377,7 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
+ depsgraph,
(SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR),
&(const struct SnapObjectParams){
@@ -410,7 +409,7 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
/* Helper: Find the layer created as ruler. */
static bGPDlayer *view3d_ruler_layer_get(bGPdata *gpd)
{
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->flag & GP_LAYER_IS_RULER) {
return gpl;
}
@@ -446,7 +445,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
gpl->flag |= GP_LAYER_HIDE | GP_LAYER_IS_RULER;
}
- gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
BKE_gpencil_free_strokes(gpf);
for (ruler_item = gzgroup->gizmos.first; ruler_item;
@@ -478,9 +477,10 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
}
gps->flag = GP_STROKE_3DSPACE;
gps->thickness = 3;
- gps->gradient_f = 1.0f;
- gps->gradient_s[0] = 1.0f;
- gps->gradient_s[1] = 1.0f;
+ gps->hardeness = 1.0f;
+ gps->fill_opacity_fac = 1.0f;
+ copy_v2_fl(gps->aspect_ratio, 1.0f);
+ gps->uv_scale = 1.0f;
BLI_addtail(&gpf->strokes, gps);
changed = true;
@@ -499,7 +499,7 @@ static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup)
gpl = view3d_ruler_layer_get(scene->gpd);
if (gpl) {
bGPDframe *gpf;
- gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
if (gpf) {
bGPDstroke *gps;
for (gps = gpf->strokes.first; gps; gps = gps->next) {
@@ -543,8 +543,8 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
UnitSettings *unit = &scene->unit;
RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
RulerItem *ruler_item = (RulerItem *)gz;
- ARegion *ar = ruler_info->ar;
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = ruler_info->region;
+ RegionView3D *rv3d = region->regiondata;
const float cap_size = 4.0f;
const float bg_margin = 4.0f * U.pixelsize;
const float arc_size = 64.0f * U.pixelsize;
@@ -579,7 +579,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
/* should these be checked? - ok for now not to */
for (j = 0; j < 3; j++) {
- ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(region, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
}
GPU_blend(true);
@@ -649,7 +649,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
for (j = 0; j <= arc_steps; j++) {
madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
- ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(region, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP);
mul_qt_v3(quat, dir_tmp);
immVertex2fv(shdr_pos, arc_ss_coord);
@@ -859,12 +859,12 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
float co_ss_snap[3];
ED_view3d_project_float_global(
- ar, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP);
+ region, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4fv(color_act);
+ immUniformThemeColor3(TH_GIZMO_VIEW_ALIGN);
imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32);
@@ -901,10 +901,10 @@ static int gizmo_ruler_modal(bContext *C,
int exit_code = OPERATOR_RUNNING_MODAL;
RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
RulerItem *ruler_item = (RulerItem *)gz;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
bool do_cursor_update = false;
- ruler_info->ar = ar;
+ ruler_info->region = region;
switch (event->type) {
case MOUSEMOVE: {
@@ -922,8 +922,9 @@ static int gizmo_ruler_modal(bContext *C,
if (do_cursor_update) {
if (ruler_info->state == RULER_STATE_DRAG) {
+ struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
if (view3d_ruler_item_mousemove(
- ruler_info, ruler_item, event->mval, do_thickness, do_snap)) {
+ depsgraph, ruler_info, ruler_item, event->mval, do_thickness, do_snap)) {
do_draw = true;
}
}
@@ -933,7 +934,7 @@ static int gizmo_ruler_modal(bContext *C,
ruler_info->drag_state_prev.do_thickness = do_thickness;
if (do_draw) {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_editor_overlays(region);
}
return exit_code;
}
@@ -946,7 +947,7 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__);
gz->interaction_data = inter;
- ARegion *ar = ruler_info->ar;
+ ARegion *region = ruler_info->region;
const float mval_fl[2] = {UNPACK2(event->mval)};
@@ -963,8 +964,10 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
float co_ss[2][2];
float fac;
- ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP);
- ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(
+ region, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(
+ region, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP);
fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]);
CLAMP(fac, 0.0f, 1.0f);
@@ -974,7 +977,9 @@ 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, false, false);
+ struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ view3d_ruler_item_mousemove(
+ depsgraph, ruler_info, ruler_item_pick, event->mval, false, false);
}
}
else {
@@ -1059,11 +1064,11 @@ static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *gzgroup)
}
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
ruler_info->win = win;
- ruler_info->sa = sa;
- ruler_info->ar = ar;
+ ruler_info->area = area;
+ ruler_info->region = region;
gzgroup->customdata = ruler_info;
}
@@ -1100,16 +1105,16 @@ static bool view3d_ruler_poll(bContext *C)
static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
BKE_report(op->reports, RPT_WARNING, "Gizmos hidden in this view");
return OPERATOR_CANCELLED;
}
- wmGizmoMap *gzmap = ar->gizmo_map;
+ wmGizmoMap *gzmap = region->gizmo_map;
wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id);
const bool use_depth = (v3d->shading.type >= OB_SOLID);
@@ -1124,9 +1129,10 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e
RulerInfo *ruler_info = gzgroup->customdata;
RulerInteraction *inter = ruler_item->gz.interaction_data;
if (use_depth) {
+ struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
/* snap the first point added, not essential but handy */
inter->co_index = 0;
- view3d_ruler_item_mousemove(ruler_info, ruler_item, event->mval, false, true);
+ view3d_ruler_item_mousemove(depsgraph, ruler_info, ruler_item, event->mval, false, true);
copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]);
}
else {
@@ -1162,7 +1168,7 @@ void VIEW3D_OT_ruler_add(wmOperatorType *ot)
static int view3d_ruler_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
@@ -1170,7 +1176,7 @@ static int view3d_ruler_remove_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_CANCELLED;
}
- wmGizmoMap *gzmap = ar->gizmo_map;
+ wmGizmoMap *gzmap = region->gizmo_map;
wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id);
if (gzgroup) {
RulerInfo *ruler_info = gzgroup->customdata;
@@ -1187,7 +1193,7 @@ static int view3d_ruler_remove_invoke(bContext *C, wmOperator *op, const wmEvent
/* Update the annotation layer. */
view3d_ruler_to_gpencil(C, gzgroup);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_editor_overlays(region);
return OPERATOR_FINISHED;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c
index 75d0384182b..18617b4368f 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c
@@ -24,10 +24,10 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "ED_screen.h"
-#include "ED_transform.h"
#include "ED_gizmo_library.h"
#include "ED_gizmo_utils.h"
+#include "ED_screen.h"
+#include "ED_transform.h"
#include "UI_resources.h"
@@ -38,9 +38,9 @@
#include "RNA_access.h"
#include "WM_api.h"
-#include "WM_types.h"
-#include "WM_toolsystem.h"
#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "view3d_intern.h" /* own include */
@@ -164,10 +164,10 @@ static void WIDGETGROUP_gizmo_message_subscribe(const bContext *C,
wmGizmoGroup *gzgroup,
struct wmMsgBus *mbus)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
+ .owner = region,
.user_data = gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
};
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 200cc12a6c1..829d793333e 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -21,13 +21,13 @@
* \ingroup spview3d
*/
-#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_math_base.h"
#include "BLI_utildefines.h"
@@ -47,8 +47,8 @@
#include "WM_types.h"
#include "ED_mesh.h"
-#include "ED_undo.h"
#include "ED_screen.h"
+#include "ED_undo.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -77,7 +77,8 @@ static int toggle_matcap_flip(bContext *C, wmOperator *UNUSED(op))
else {
Scene *scene = CTX_data_scene(C);
scene->display.shading.flag ^= V3D_SHADING_MATCAP_FLIP_X;
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, v3d);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
}
return OPERATOR_FINISHED;
@@ -105,7 +106,7 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
wmWindow *win = CTX_wm_window(C);
const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift;
- /* watch it: if sa->win does not exist, check that when calling direct drawing routines */
+ /* watch it: if area->win does not exist, check that when calling direct drawing routines */
switch (event) {
case B_SEL_VERT:
@@ -138,10 +139,11 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
if (obedit && (obedit->type == OB_MESH)) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
uiLayout *row;
+ uiBut *but;
row = uiLayoutRow(layout, true);
block = uiLayoutGetBlock(row);
- uiDefIconButBitS(
+ but = uiDefIconButBitS(
block,
UI_BTYPE_TOGGLE,
SCE_SELECT_VERTEX,
@@ -157,23 +159,26 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
0,
0,
TIP_("Vertex select - Shift-Click for multiple modes, Ctrl-Click contracts selection"));
- uiDefIconButBitS(block,
- UI_BTYPE_TOGGLE,
- SCE_SELECT_EDGE,
- B_SEL_EDGE,
- ICON_EDGESEL,
- 0,
- 0,
- ceilf(UI_UNIT_X - U.pixelsize),
- UI_UNIT_Y,
- &em->selectmode,
- 1.0,
- 0.0,
- 0,
- 0,
- TIP_("Edge select - Shift-Click for multiple modes, Ctrl-Click "
- "expands/contracts selection"));
- uiDefIconButBitS(
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+ but = uiDefIconButBitS(
+ block,
+ UI_BTYPE_TOGGLE,
+ SCE_SELECT_EDGE,
+ B_SEL_EDGE,
+ ICON_EDGESEL,
+ 0,
+ 0,
+ ceilf(UI_UNIT_X - U.pixelsize),
+ UI_UNIT_Y,
+ &em->selectmode,
+ 1.0,
+ 0.0,
+ 0,
+ 0,
+ TIP_("Edge select - Shift-Click for multiple modes, "
+ "Ctrl-Click expands/contracts selection depending on the current mode"));
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+ but = uiDefIconButBitS(
block,
UI_BTYPE_TOGGLE,
SCE_SELECT_FACE,
@@ -189,6 +194,7 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
0,
0,
TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
+ UI_but_flag_disable(but, UI_BUT_UNDO);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index ddbb64bf067..c16131c8317 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -91,8 +91,8 @@ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_shading(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_xray(struct wmOperatorType *ot);
-void view3d_boxview_copy(struct ScrArea *sa, struct ARegion *ar);
-void view3d_boxview_sync(struct ScrArea *sa, struct ARegion *ar);
+void view3d_boxview_copy(struct ScrArea *area, struct ARegion *region);
+void view3d_boxview_sync(struct ScrArea *area, struct ARegion *region);
void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
const float ofs_old[3],
@@ -120,18 +120,18 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot);
void VIEW3D_OT_walk(struct wmOperatorType *ot);
/* view3d_draw.c */
-void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar);
-void view3d_draw_region_info(const struct bContext *C, struct ARegion *ar);
+void view3d_main_region_draw(const struct bContext *C, struct ARegion *region);
+void view3d_draw_region_info(const struct bContext *C, struct ARegion *region);
void ED_view3d_draw_depth(struct Depsgraph *depsgraph,
- struct ARegion *ar,
+ struct ARegion *region,
View3D *v3d,
bool alphaoverride);
/* view3d_draw_legacy.c */
void ED_view3d_draw_depth_gpencil(struct Depsgraph *depsgraph,
Scene *scene,
- struct ARegion *ar,
+ struct ARegion *region,
View3D *v3d);
void ED_view3d_draw_select_loop(struct Depsgraph *depsgraph,
@@ -139,16 +139,16 @@ void ED_view3d_draw_select_loop(struct Depsgraph *depsgraph,
Scene *scene,
struct ViewLayer *view_layer,
View3D *v3d,
- struct ARegion *ar,
+ struct ARegion *region,
bool use_obedit_skip,
bool use_nearest);
void ED_view3d_draw_depth_loop(struct Depsgraph *depsgraph,
Scene *scene,
- struct ARegion *ar,
+ struct ARegion *region,
View3D *v3d);
-void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect);
+void view3d_update_depths_rect(struct ARegion *region, struct ViewDepths *d, struct rcti *rect);
float view3d_depth_near(struct ViewDepths *d);
/* view3d_select.c */
@@ -181,28 +181,28 @@ typedef struct V3D_SmoothParams {
void ED_view3d_smooth_view_ex(const struct Depsgraph *depsgraph,
struct wmWindowManager *wm,
struct wmWindow *win,
- struct ScrArea *sa,
+ struct ScrArea *area,
struct View3D *v3d,
- struct ARegion *ar,
+ struct ARegion *region,
const int smooth_viewtx,
const V3D_SmoothParams *sview);
void ED_view3d_smooth_view(struct bContext *C,
struct View3D *v3d,
- struct ARegion *ar,
+ struct ARegion *region,
const int smooth_viewtx,
const V3D_SmoothParams *sview);
void ED_view3d_smooth_view_force_finish(struct bContext *C,
struct View3D *v3d,
- struct ARegion *ar);
+ struct ARegion *region);
void view3d_winmatrix_set(struct Depsgraph *depsgraph,
- struct ARegion *ar,
+ struct ARegion *region,
const View3D *v3d,
const rcti *rect);
void view3d_viewmatrix_set(struct Depsgraph *depsgraph,
- Scene *scene,
+ const struct Scene *scene,
const View3D *v3d,
RegionView3D *rv3d,
const float rect_scale[2]);
@@ -232,9 +232,6 @@ void ED_view3d_cameracontrol_update(struct View3DCameraControl *vctrl,
void ED_view3d_cameracontrol_release(struct View3DCameraControl *vctrl, const bool restore);
struct Object *ED_view3d_cameracontrol_object_get(struct View3DCameraControl *vctrl);
-/* view3d_toolbar.c */
-void VIEW3D_OT_toolshelf(struct wmOperatorType *ot);
-
/* view3d_snap.c */
bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]);
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index f6fa6f6fb45..08e68c9174e 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -18,27 +18,27 @@
* \ingroup spview3d
*/
+#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
-#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_armature_types.h"
+#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
-#include "BLI_rect.h"
#include "BLI_math_geom.h"
+#include "BLI_rect.h"
+#include "BLI_utildefines.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_curve.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
-#include "BKE_mesh_runtime.h"
#include "BKE_mesh_iterators.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "DEG_depsgraph.h"
@@ -46,8 +46,8 @@
#include "bmesh.h"
-#include "ED_screen.h"
#include "ED_armature.h"
+#include "ED_screen.h"
#include "ED_view3d.h"
typedef struct foreachScreenObjectVert_userData {
@@ -73,7 +73,7 @@ typedef struct foreachScreenEdge_userData {
int index);
void *userData;
ViewContext vc;
- rctf win_rect; /* copy of: vc.ar->winx/winy, use for faster tests, minx/y will always be 0 */
+ rctf win_rect; /* copy of: vc.region->winx/winy, use for faster tests, minx/y will always be 0 */
eV3DProjTest clip_flag;
} foreachScreenEdge_userData;
@@ -105,7 +105,7 @@ static void meshobject_foreachScreenVert__mapFunc(void *userData,
if (!(mv->flag & ME_HIDE)) {
float screen_co[2];
- if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) !=
+ if (ED_view3d_project_float_object(data->vc.region, co, screen_co, data->clip_flag) !=
V3D_PROJ_RET_OK) {
return;
}
@@ -154,7 +154,7 @@ static void mesh_foreachScreenVert__mapFunc(void *userData,
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
float screen_co[2];
- if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) !=
+ if (ED_view3d_project_float_object(data->vc.region, co, screen_co, data->clip_flag) !=
V3D_PROJ_RET_OK) {
return;
}
@@ -204,11 +204,11 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData,
float screen_co_b[2];
eV3DProjTest clip_flag_nowin = data->clip_flag & ~V3D_PROJ_TEST_CLIP_WIN;
- if (ED_view3d_project_float_object(data->vc.ar, v0co, screen_co_a, clip_flag_nowin) !=
+ if (ED_view3d_project_float_object(data->vc.region, v0co, screen_co_a, clip_flag_nowin) !=
V3D_PROJ_RET_OK) {
return;
}
- if (ED_view3d_project_float_object(data->vc.ar, v1co, screen_co_b, clip_flag_nowin) !=
+ if (ED_view3d_project_float_object(data->vc.region, v1co, screen_co_b, clip_flag_nowin) !=
V3D_PROJ_RET_OK) {
return;
}
@@ -243,8 +243,8 @@ void mesh_foreachScreenEdge(ViewContext *vc,
data.win_rect.xmin = 0;
data.win_rect.ymin = 0;
- data.win_rect.xmax = vc->ar->winx;
- data.win_rect.ymax = vc->ar->winy;
+ data.win_rect.xmax = vc->region->winx;
+ data.win_rect.ymax = vc->region->winy;
data.func = func;
data.userData = userData;
@@ -289,11 +289,11 @@ static void mesh_foreachScreenEdge_clip_bb_segment__mapFunc(void *userData,
eV3DProjTest clip_flag_nowin = data->clip_flag &
~(V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_BB);
- if (ED_view3d_project_float_object(data->vc.ar, v0co_clip, screen_co_a, clip_flag_nowin) !=
+ if (ED_view3d_project_float_object(data->vc.region, v0co_clip, screen_co_a, clip_flag_nowin) !=
V3D_PROJ_RET_OK) {
return;
}
- if (ED_view3d_project_float_object(data->vc.ar, v1co_clip, screen_co_b, clip_flag_nowin) !=
+ if (ED_view3d_project_float_object(data->vc.region, v1co_clip, screen_co_b, clip_flag_nowin) !=
V3D_PROJ_RET_OK) {
return;
}
@@ -332,8 +332,8 @@ void mesh_foreachScreenEdge_clip_bb_segment(ViewContext *vc,
data.win_rect.xmin = 0;
data.win_rect.ymin = 0;
- data.win_rect.xmax = vc->ar->winx;
- data.win_rect.ymax = vc->ar->winy;
+ data.win_rect.xmax = vc->region->winx;
+ data.win_rect.ymax = vc->region->winy;
data.func = func;
data.userData = userData;
@@ -362,7 +362,7 @@ static void mesh_foreachScreenFace__mapFunc(void *userData,
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
float screen_co[2];
- if (ED_view3d_project_float_object(data->vc.ar, cent, screen_co, data->clip_flag) ==
+ if (ED_view3d_project_float_object(data->vc.region, cent, screen_co, data->clip_flag) ==
V3D_PROJ_RET_OK) {
data->func(data->userData, efa, screen_co, index);
}
@@ -388,7 +388,7 @@ void mesh_foreachScreenFace(
BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE);
- if (modifiers_usesSubsurfFacedots(vc->scene, vc->obedit)) {
+ if (BKE_modifiers_uses_subsurf_facedots(vc->scene, vc->obedit)) {
BKE_mesh_foreach_mapped_subdiv_face_center(
me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
}
@@ -430,7 +430,7 @@ void nurbs_foreachScreenVert(ViewContext *vc,
float screen_co[2];
if ((vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- if (ED_view3d_project_float_object(vc->ar,
+ if (ED_view3d_project_float_object(vc->region,
bezt->vec[1],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
@@ -439,21 +439,21 @@ void nurbs_foreachScreenVert(ViewContext *vc,
}
}
else {
- if (ED_view3d_project_float_object(vc->ar,
+ if (ED_view3d_project_float_object(vc->region,
bezt->vec[0],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
func(userData, nu, NULL, bezt, 0, screen_co);
}
- if (ED_view3d_project_float_object(vc->ar,
+ if (ED_view3d_project_float_object(vc->region,
bezt->vec[1],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
func(userData, nu, NULL, bezt, 1, screen_co);
}
- if (ED_view3d_project_float_object(vc->ar,
+ if (ED_view3d_project_float_object(vc->region,
bezt->vec[2],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
@@ -471,7 +471,7 @@ void nurbs_foreachScreenVert(ViewContext *vc,
if (bp->hide == 0) {
float screen_co[2];
if (ED_view3d_project_float_object(
- vc->ar, bp->vec, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
+ vc->region, bp->vec, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
func(userData, nu, bp, NULL, -1, screen_co);
}
@@ -498,7 +498,8 @@ void mball_foreachScreenElem(struct ViewContext *vc,
for (ml = mb->editelems->first; ml; ml = ml->next) {
float screen_co[2];
- if (ED_view3d_project_float_object(vc->ar, &ml->x, screen_co, clip_flag) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(vc->region, &ml->x, screen_co, clip_flag) ==
+ V3D_PROJ_RET_OK) {
func(userData, ml, screen_co);
}
}
@@ -529,7 +530,7 @@ void lattice_foreachScreenVert(ViewContext *vc,
for (i = 0; i < N; i++, bp++, co += 3) {
if (bp->hide == 0) {
float screen_co[2];
- if (ED_view3d_project_float_object(vc->ar, dl ? co : bp->vec, screen_co, clip_flag) ==
+ if (ED_view3d_project_float_object(vc->region, dl ? co : bp->vec, screen_co, clip_flag) ==
V3D_PROJ_RET_OK) {
func(userData, bp, screen_co);
}
@@ -559,7 +560,7 @@ void armature_foreachScreenBone(struct ViewContext *vc,
int points_proj_tot = 0;
/* project head location to screenspace */
- if (ED_view3d_project_float_object(vc->ar, ebone->head, screen_co_a, clip_flag) ==
+ if (ED_view3d_project_float_object(vc->region, ebone->head, screen_co_a, clip_flag) ==
V3D_PROJ_RET_OK) {
points_proj_tot++;
}
@@ -569,7 +570,7 @@ void armature_foreachScreenBone(struct ViewContext *vc,
}
/* project tail location to screenspace */
- if (ED_view3d_project_float_object(vc->ar, ebone->tail, screen_co_b, clip_flag) ==
+ if (ED_view3d_project_float_object(vc->region, ebone->tail, screen_co_b, clip_flag) ==
V3D_PROJ_RET_OK) {
points_proj_tot++;
}
@@ -611,8 +612,8 @@ void pose_foreachScreenBone(struct ViewContext *vc,
int points_proj_tot = 0;
/* project head location to screenspace */
- if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_head, screen_co_a, clip_flag) ==
- V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(
+ vc->region, pchan_eval->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) {
points_proj_tot++;
}
else {
@@ -621,8 +622,8 @@ void pose_foreachScreenBone(struct ViewContext *vc,
}
/* project tail location to screenspace */
- if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_tail, screen_co_b, clip_flag) ==
- V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(
+ vc->region, pchan_eval->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) {
points_proj_tot++;
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index cfdd3dcbb6f..1ad3f8bb1f5 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -21,8 +21,8 @@
* \ingroup spview3d
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include "DNA_collection_types.h"
#include "DNA_object_types.h"
@@ -47,6 +47,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_transform.h"
@@ -76,7 +77,7 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
+ BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
BKE_copybuffer_save(bmain, str, op->reports);
BKE_reportf(op->reports, RPT_INFO, "Copied %d selected object(s)", num_copied);
@@ -108,7 +109,7 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
flag |= FILE_ACTIVE_COLLECTION;
}
- BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
+ BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, FILTER_ID_OB);
if (num_pasted == 0) {
@@ -117,6 +118,7 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_WINDOW, NULL);
+ ED_outliner_select_sync_from_object_tag(C);
BKE_reportf(op->reports, RPT_INFO, "%d object(s) pasted", num_pasted);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 56c8b4bcbe9..3a0f0f468fc 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -23,8 +23,8 @@
#include "DNA_camera_types.h"
#include "DNA_object_types.h"
-#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "BLI_sys_types.h" /* int64_t */
@@ -47,7 +47,7 @@
/**
* \note use #ED_view3d_ob_project_mat_get to get the projection matrix
*/
-void ED_view3d_project_float_v2_m4(const ARegion *ar,
+void ED_view3d_project_float_v2_m4(const ARegion *region,
const float co[3],
float r_co[2],
float mat[4][4])
@@ -61,8 +61,8 @@ void ED_view3d_project_float_v2_m4(const ARegion *ar,
mul_m4_v4(mat, vec4);
if (vec4[3] > FLT_EPSILON) {
- r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3];
- r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3];
+ r_co[0] = (float)(region->winx / 2.0f) + (region->winx / 2.0f) * vec4[0] / vec4[3];
+ r_co[1] = (float)(region->winy / 2.0f) + (region->winy / 2.0f) * vec4[1] / vec4[3];
}
else {
zero_v2(r_co);
@@ -72,7 +72,7 @@ void ED_view3d_project_float_v2_m4(const ARegion *ar,
/**
* \note use #ED_view3d_ob_project_mat_get to get projecting mat
*/
-void ED_view3d_project_float_v3_m4(const ARegion *ar,
+void ED_view3d_project_float_v3_m4(const ARegion *region,
const float vec[3],
float r_co[3],
float mat[4][4])
@@ -86,8 +86,8 @@ void ED_view3d_project_float_v3_m4(const ARegion *ar,
mul_m4_v4(mat, vec4);
if (vec4[3] > FLT_EPSILON) {
- r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3];
- r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3];
+ r_co[0] = (float)(region->winx / 2.0f) + (region->winx / 2.0f) * vec4[0] / vec4[3];
+ r_co[1] = (float)(region->winy / 2.0f) + (region->winy / 2.0f) * vec4[1] / vec4[3];
r_co[2] = vec4[2] / vec4[3];
}
else {
@@ -98,10 +98,10 @@ void ED_view3d_project_float_v3_m4(const ARegion *ar,
/* Clipping Projection Functions
* ***************************** */
-eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base)
+eV3DProjStatus ED_view3d_project_base(const struct ARegion *region, struct Base *base)
{
eV3DProjStatus ret = ED_view3d_project_short_global(
- ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT);
+ region, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT);
if (ret != V3D_PROJ_RET_OK) {
base->sx = IS_CLIPPED;
@@ -115,7 +115,7 @@ eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *bas
* - 'rv3d->perspmat', is_local == false
* - 'rv3d->persmatob', is_local == true
*/
-static eV3DProjStatus ed_view3d_project__internal(const ARegion *ar,
+static eV3DProjStatus ed_view3d_project__internal(const ARegion *region,
const float perspmat[4][4],
const bool is_local, /* normally hidden */
const float co[3],
@@ -128,7 +128,7 @@ static eV3DProjStatus ed_view3d_project__internal(const ARegion *ar,
BLI_assert((flag & V3D_PROJ_TEST_ALL) == flag);
if (flag & V3D_PROJ_TEST_CLIP_BB) {
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (rv3d->rflag & RV3D_CLIPPING) {
if (ED_view3d_clipping_test(rv3d, co, is_local)) {
return V3D_PROJ_RET_CLIP_BB;
@@ -143,10 +143,10 @@ static eV3DProjStatus ed_view3d_project__internal(const ARegion *ar,
if (((flag & V3D_PROJ_TEST_CLIP_ZERO) == 0) || (fabsf(vec4[3]) > (float)BL_ZERO_CLIP)) {
if (((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) || (vec4[3] > (float)BL_NEAR_CLIP)) {
const float scalar = (vec4[3] != 0.0f) ? (1.0f / vec4[3]) : 0.0f;
- const float fx = ((float)ar->winx / 2.0f) * (1.0f + (vec4[0] * scalar));
- if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0.0f && fx < (float)ar->winx)) {
- const float fy = ((float)ar->winy / 2.0f) * (1.0f + (vec4[1] * scalar));
- if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)ar->winy)) {
+ const float fx = ((float)region->winx / 2.0f) * (1.0f + (vec4[0] * scalar));
+ if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0.0f && fx < (float)region->winx)) {
+ const float fy = ((float)region->winy / 2.0f) * (1.0f + (vec4[1] * scalar));
+ if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)region->winy)) {
r_co[0] = fx;
r_co[1] = fy;
@@ -174,7 +174,7 @@ static eV3DProjStatus ed_view3d_project__internal(const ARegion *ar,
return V3D_PROJ_RET_OK;
}
-eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar,
+eV3DProjStatus ED_view3d_project_short_ex(const ARegion *region,
float perspmat[4][4],
const bool is_local,
const float co[3],
@@ -182,7 +182,7 @@ eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar,
const eV3DProjTest flag)
{
float tvec[2];
- eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag);
+ eV3DProjStatus ret = ed_view3d_project__internal(region, perspmat, is_local, co, tvec, flag);
if (ret == V3D_PROJ_RET_OK) {
if ((tvec[0] > -32700.0f && tvec[0] < 32700.0f) &&
(tvec[1] > -32700.0f && tvec[1] < 32700.0f)) {
@@ -196,7 +196,7 @@ eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar,
return ret;
}
-eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar,
+eV3DProjStatus ED_view3d_project_int_ex(const ARegion *region,
float perspmat[4][4],
const bool is_local,
const float co[3],
@@ -204,7 +204,7 @@ eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar,
const eV3DProjTest flag)
{
float tvec[2];
- eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag);
+ eV3DProjStatus ret = ed_view3d_project__internal(region, perspmat, is_local, co, tvec, flag);
if (ret == V3D_PROJ_RET_OK) {
if ((tvec[0] > -2140000000.0f && tvec[0] < 2140000000.0f) &&
(tvec[1] > -2140000000.0f && tvec[1] < 2140000000.0f)) {
@@ -218,7 +218,7 @@ eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar,
return ret;
}
-eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar,
+eV3DProjStatus ED_view3d_project_float_ex(const ARegion *region,
float perspmat[4][4],
const bool is_local,
const float co[3],
@@ -226,7 +226,7 @@ eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar,
const eV3DProjTest flag)
{
float tvec[2];
- eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag);
+ eV3DProjStatus ret = ed_view3d_project__internal(region, perspmat, is_local, co, tvec, flag);
if (ret == V3D_PROJ_RET_OK) {
if (isfinite(tvec[0]) && isfinite(tvec[1])) {
copy_v2_v2(r_co, tvec);
@@ -239,63 +239,63 @@ eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar,
}
/* --- short --- */
-eV3DProjStatus ED_view3d_project_short_global(const ARegion *ar,
+eV3DProjStatus ED_view3d_project_short_global(const ARegion *region,
const float co[3],
short r_co[2],
const eV3DProjTest flag)
{
- RegionView3D *rv3d = ar->regiondata;
- return ED_view3d_project_short_ex(ar, rv3d->persmat, false, co, r_co, flag);
+ RegionView3D *rv3d = region->regiondata;
+ return ED_view3d_project_short_ex(region, rv3d->persmat, false, co, r_co, flag);
}
/* object space, use ED_view3d_init_mats_rv3d before calling */
-eV3DProjStatus ED_view3d_project_short_object(const ARegion *ar,
+eV3DProjStatus ED_view3d_project_short_object(const ARegion *region,
const float co[3],
short r_co[2],
const eV3DProjTest flag)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
ED_view3d_check_mats_rv3d(rv3d);
- return ED_view3d_project_short_ex(ar, rv3d->persmatob, true, co, r_co, flag);
+ return ED_view3d_project_short_ex(region, rv3d->persmatob, true, co, r_co, flag);
}
/* --- int --- */
-eV3DProjStatus ED_view3d_project_int_global(const ARegion *ar,
+eV3DProjStatus ED_view3d_project_int_global(const ARegion *region,
const float co[3],
int r_co[2],
const eV3DProjTest flag)
{
- RegionView3D *rv3d = ar->regiondata;
- return ED_view3d_project_int_ex(ar, rv3d->persmat, false, co, r_co, flag);
+ RegionView3D *rv3d = region->regiondata;
+ return ED_view3d_project_int_ex(region, rv3d->persmat, false, co, r_co, flag);
}
/* object space, use ED_view3d_init_mats_rv3d before calling */
-eV3DProjStatus ED_view3d_project_int_object(const ARegion *ar,
+eV3DProjStatus ED_view3d_project_int_object(const ARegion *region,
const float co[3],
int r_co[2],
const eV3DProjTest flag)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
ED_view3d_check_mats_rv3d(rv3d);
- return ED_view3d_project_int_ex(ar, rv3d->persmatob, true, co, r_co, flag);
+ return ED_view3d_project_int_ex(region, rv3d->persmatob, true, co, r_co, flag);
}
/* --- float --- */
-eV3DProjStatus ED_view3d_project_float_global(const ARegion *ar,
+eV3DProjStatus ED_view3d_project_float_global(const ARegion *region,
const float co[3],
float r_co[2],
const eV3DProjTest flag)
{
- RegionView3D *rv3d = ar->regiondata;
- return ED_view3d_project_float_ex(ar, rv3d->persmat, false, co, r_co, flag);
+ RegionView3D *rv3d = region->regiondata;
+ return ED_view3d_project_float_ex(region, rv3d->persmat, false, co, r_co, flag);
}
/* object space, use ED_view3d_init_mats_rv3d before calling */
-eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar,
+eV3DProjStatus ED_view3d_project_float_object(const ARegion *region,
const float co[3],
float r_co[2],
const eV3DProjTest flag)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
ED_view3d_check_mats_rv3d(rv3d);
- return ED_view3d_project_float_ex(ar, rv3d->persmatob, true, co, r_co, flag);
+ return ED_view3d_project_float_ex(region, rv3d->persmatob, true, co, r_co, flag);
}
/* More Generic Window/Ray/Vector projection functions
@@ -338,7 +338,7 @@ float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_f
}
static void view3d_win_to_ray_segment(struct Depsgraph *depsgraph,
- const ARegion *ar,
+ const ARegion *region,
const View3D *v3d,
const float mval[2],
float r_ray_co[3],
@@ -346,7 +346,7 @@ static void view3d_win_to_ray_segment(struct Depsgraph *depsgraph,
float r_ray_start[3],
float r_ray_end[3])
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
float _ray_co[3], _ray_dir[3], start_offset, end_offset;
if (!r_ray_co) {
@@ -356,8 +356,8 @@ static void view3d_win_to_ray_segment(struct Depsgraph *depsgraph,
r_ray_dir = _ray_dir;
}
- ED_view3d_win_to_origin(ar, mval, r_ray_co);
- ED_view3d_win_to_vector(ar, mval, r_ray_dir);
+ ED_view3d_win_to_origin(region, mval, r_ray_co);
+ ED_view3d_win_to_vector(region, mval, r_ray_dir);
if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) {
end_offset = v3d->clip_end / 2.0f;
@@ -391,7 +391,7 @@ bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float
* In orthographic view the resulting ray_normal will match the view vector.
* This version also returns the ray_co point of the ray on window plane, useful to fix precision
* issues esp. with ortho view, where default ray_start is set rather far away.
- * \param ar: The region (used for the window width and height).
+ * \param region: The region (used for the window width and height).
* \param v3d: The 3d viewport (used for near clipping value).
* \param mval: The area relative 2d location (such as event->mval, converted into float[2]).
* \param r_ray_co: The world-space point where the ray intersects the window plane.
@@ -401,7 +401,7 @@ bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float
* \return success, false if the ray is totally clipped.
*/
bool ED_view3d_win_to_ray_clipped_ex(struct Depsgraph *depsgraph,
- const ARegion *ar,
+ const ARegion *region,
const View3D *v3d,
const float mval[2],
float r_ray_co[3],
@@ -412,11 +412,11 @@ bool ED_view3d_win_to_ray_clipped_ex(struct Depsgraph *depsgraph,
float ray_end[3];
view3d_win_to_ray_segment(
- depsgraph, ar, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end);
+ depsgraph, region, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end);
/* bounds clipping */
if (do_clip_planes) {
- return ED_view3d_clip_segment(ar->regiondata, r_ray_start, ray_end);
+ return ED_view3d_clip_segment(region->regiondata, r_ray_start, ray_end);
}
return true;
@@ -427,7 +427,7 @@ bool ED_view3d_win_to_ray_clipped_ex(struct Depsgraph *depsgraph,
* This ray_start is located at the viewpoint, ray_normal is the direction towards mval.
* ray_start is clipped by the view near limit so points in front of it are always in view.
* In orthographic view the resulting ray_normal will match the view vector.
- * \param ar: The region (used for the window width and height).
+ * \param region: The region (used for the window width and height).
* \param v3d: The 3d viewport (used for near clipping value).
* \param mval: The area relative 2d location (such as event->mval, converted into float[2]).
* \param r_ray_start: The world-space point where the ray intersects the window plane.
@@ -436,7 +436,7 @@ bool ED_view3d_win_to_ray_clipped_ex(struct Depsgraph *depsgraph,
* \return success, false if the ray is totally clipped.
*/
bool ED_view3d_win_to_ray_clipped(struct Depsgraph *depsgraph,
- const ARegion *ar,
+ const ARegion *region,
const View3D *v3d,
const float mval[2],
float r_ray_start[3],
@@ -444,13 +444,13 @@ bool ED_view3d_win_to_ray_clipped(struct Depsgraph *depsgraph,
const bool do_clip_planes)
{
return ED_view3d_win_to_ray_clipped_ex(
- depsgraph, ar, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip_planes);
+ depsgraph, region, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip_planes);
}
/**
* Calculate a 3d viewpoint and direction vector from 2d window coordinates.
* This ray_start is located at the viewpoint, ray_normal is the direction towards mval.
- * \param ar: The region (used for the window width and height).
+ * \param region: The region (used for the window width and height).
* \param mval: The area relative 2d location (such as event->mval, converted into float[2]).
* \param r_ray_start: The world-space point where the ray intersects the window plane.
* \param r_ray_normal: The normalized world-space direction of towards mval.
@@ -458,13 +458,13 @@ bool ED_view3d_win_to_ray_clipped(struct Depsgraph *depsgraph,
* \note Ignores view near/far clipping,
* to take this into account use #ED_view3d_win_to_ray_clipped.
*/
-void ED_view3d_win_to_ray(const ARegion *ar,
+void ED_view3d_win_to_ray(const ARegion *region,
const float mval[2],
float r_ray_start[3],
float r_ray_normal[3])
{
- ED_view3d_win_to_origin(ar, mval, r_ray_start);
- ED_view3d_win_to_vector(ar, mval, r_ray_normal);
+ ED_view3d_win_to_origin(region, mval, r_ray_start);
+ ED_view3d_win_to_vector(region, mval, r_ray_normal);
}
/**
@@ -499,22 +499,22 @@ void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3],
/* very similar to ED_view3d_win_to_3d() but has no advantage, de-duplicating */
#if 0
-bool view3d_get_view_aligned_coordinate(ARegion *ar,
+bool view3d_get_view_aligned_coordinate(ARegion *region,
float fp[3],
const int mval[2],
const bool do_fallback)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
float dvec[3];
int mval_cpy[2];
eV3DProjStatus ret;
- ret = ED_view3d_project_int_global(ar, fp, mval_cpy, V3D_PROJ_TEST_NOP);
+ ret = ED_view3d_project_int_global(region, fp, mval_cpy, V3D_PROJ_TEST_NOP);
if (ret == V3D_PROJ_RET_OK) {
const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]), (float)(mval_cpy[1] - mval[1])};
const float zfac = ED_view3d_calc_zfac(rv3d, fp, NULL);
- ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
+ ED_view3d_win_to_delta(region, mval_f, dvec, zfac);
sub_v3_v3(fp, dvec);
return true;
@@ -523,7 +523,7 @@ bool view3d_get_view_aligned_coordinate(ARegion *ar,
/* fallback to the view center */
if (do_fallback) {
negate_v3_v3(fp, rv3d->ofs);
- return view3d_get_view_aligned_coordinate(ar, fp, mval, false);
+ return view3d_get_view_aligned_coordinate(region, fp, mval, false);
}
else {
return false;
@@ -534,18 +534,18 @@ bool view3d_get_view_aligned_coordinate(ARegion *ar,
/**
* Calculate a 3d location from 2d window coordinates.
- * \param ar: The region (used for the window width and height).
+ * \param region: The region (used for the window width and height).
* \param depth_pt: The reference location used to calculate the Z depth.
* \param mval: The area relative location (such as event->mval converted to floats).
* \param r_out: The resulting world-space location.
*/
void ED_view3d_win_to_3d(const View3D *v3d,
- const ARegion *ar,
+ const ARegion *region,
const float depth_pt[3],
const float mval[2],
float r_out[3])
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
float ray_origin[3];
float ray_direction[3];
@@ -555,7 +555,7 @@ void ED_view3d_win_to_3d(const View3D *v3d,
float plane[4];
copy_v3_v3(ray_origin, rv3d->viewinv[3]);
- ED_view3d_win_to_vector(ar, mval, ray_direction);
+ ED_view3d_win_to_vector(region, mval, ray_direction);
/* note, we could use isect_line_plane_v3()
* however we want the intersection to be infront of the view no matter what,
@@ -566,16 +566,16 @@ void ED_view3d_win_to_3d(const View3D *v3d,
lambda = fabsf(lambda);
}
else {
- float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f;
- float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f;
+ float dx = (2.0f * mval[0] / (float)region->winx) - 1.0f;
+ float dy = (2.0f * mval[1] / (float)region->winy) - 1.0f;
if (rv3d->persp == RV3D_CAMOB) {
/* ortho camera needs offset applied */
const Camera *cam = v3d->camera->data;
- const int sensor_fit = BKE_camera_sensor_fit(cam->sensor_fit, ar->winx, ar->winy);
+ const int sensor_fit = BKE_camera_sensor_fit(cam->sensor_fit, region->winx, region->winy);
const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 4.0f;
- const float aspx = ar->winx / (float)ar->winy;
- const float aspy = ar->winy / (float)ar->winx;
+ const float aspx = region->winx / (float)region->winy;
+ const float aspy = region->winy / (float)region->winx;
const float shiftx = cam->shiftx * 0.5f *
(sensor_fit == CAMERA_SENSOR_FIT_HOR ? 1.0f : aspy);
const float shifty = cam->shifty * 0.5f *
@@ -596,24 +596,24 @@ void ED_view3d_win_to_3d(const View3D *v3d,
}
void ED_view3d_win_to_3d_int(const View3D *v3d,
- const ARegion *ar,
+ const ARegion *region,
const float depth_pt[3],
const int mval[2],
float r_out[3])
{
const float mval_fl[2] = {mval[0], mval[1]};
- ED_view3d_win_to_3d(v3d, ar, depth_pt, mval_fl, r_out);
+ ED_view3d_win_to_3d(v3d, region, depth_pt, mval_fl, r_out);
}
-bool ED_view3d_win_to_3d_on_plane(const ARegion *ar,
+bool ED_view3d_win_to_3d_on_plane(const ARegion *region,
const float plane[4],
const float mval[2],
const bool do_clip,
float r_out[3])
{
float ray_co[3], ray_no[3];
- ED_view3d_win_to_origin(ar, mval, ray_co);
- ED_view3d_win_to_vector(ar, mval, ray_no);
+ ED_view3d_win_to_origin(region, mval, ray_co);
+ ED_view3d_win_to_vector(region, mval, ray_no);
float lambda;
if (isect_ray_plane_v3(ray_co, ray_no, plane, &lambda, do_clip)) {
madd_v3_v3v3fl(r_out, ray_co, ray_no, lambda);
@@ -622,28 +622,34 @@ bool ED_view3d_win_to_3d_on_plane(const ARegion *ar,
return false;
}
-bool ED_view3d_win_to_3d_on_plane_int(
- const ARegion *ar, const float plane[4], const int mval[2], const bool do_clip, float r_out[3])
+bool ED_view3d_win_to_3d_on_plane_int(const ARegion *region,
+ const float plane[4],
+ const int mval[2],
+ const bool do_clip,
+ float r_out[3])
{
const float mval_fl[2] = {mval[0], mval[1]};
- return ED_view3d_win_to_3d_on_plane(ar, plane, mval_fl, do_clip, r_out);
+ return ED_view3d_win_to_3d_on_plane(region, plane, mval_fl, do_clip, r_out);
}
/**
* Calculate a 3d difference vector from 2d window offset.
* note that #ED_view3d_calc_zfac() must be called first to determine
* the depth used to calculate the delta.
- * \param ar: The region (used for the window width and height).
+ * \param region: The region (used for the window width and height).
* \param mval: The area relative 2d difference (such as event->mval[0] - other_x).
* \param out: The resulting world-space delta.
*/
-void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3], const float zfac)
+void ED_view3d_win_to_delta(const ARegion *region,
+ const float mval[2],
+ float out[3],
+ const float zfac)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
float dx, dy;
- dx = 2.0f * mval[0] * zfac / ar->winx;
- dy = 2.0f * mval[1] * zfac / ar->winy;
+ dx = 2.0f * mval[0] * zfac / region->winx;
+ dy = 2.0f * mval[1] * zfac / region->winy;
out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy);
out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy);
@@ -656,19 +662,19 @@ void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3]
* Since far clip can be a very large value resulting in numeric precision issues,
* the origin in this case is close to zero coordinate.
*
- * \param ar: The region (used for the window width and height).
+ * \param region: The region (used for the window width and height).
* \param mval: The area relative 2d location (such as event->mval converted to floats).
* \param out: The resulting normalized world-space direction vector.
*/
-void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3])
+void ED_view3d_win_to_origin(const ARegion *region, const float mval[2], float out[3])
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (rv3d->is_persp) {
copy_v3_v3(out, rv3d->viewinv[3]);
}
else {
- out[0] = 2.0f * mval[0] / ar->winx - 1.0f;
- out[1] = 2.0f * mval[1] / ar->winy - 1.0f;
+ out[0] = 2.0f * mval[0] / region->winx - 1.0f;
+ out[1] = 2.0f * mval[1] / region->winy - 1.0f;
if (rv3d->persp == RV3D_CAMOB) {
out[2] = -1.0f;
@@ -690,17 +696,17 @@ void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3
* for perspective view, get the vector direction to
* the mouse cursor as a normalized vector.
*
- * \param ar: The region (used for the window width and height).
+ * \param region: The region (used for the window width and height).
* \param mval: The area relative 2d location (such as event->mval converted to floats).
* \param out: The resulting normalized world-space direction vector.
*/
-void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3])
+void ED_view3d_win_to_vector(const ARegion *region, const float mval[2], float out[3])
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (rv3d->is_persp) {
- out[0] = 2.0f * (mval[0] / ar->winx) - 1.0f;
- out[1] = 2.0f * (mval[1] / ar->winy) - 1.0f;
+ out[0] = 2.0f * (mval[0] / region->winx) - 1.0f;
+ out[1] = 2.0f * (mval[1] / region->winy) - 1.0f;
out[2] = -0.5f;
mul_project_m4_v3(rv3d->persinv, out);
sub_v3_v3(out, rv3d->viewinv[3]);
@@ -717,7 +723,7 @@ void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3
* ray_start and ray_end are clipped by the view near and far limits
* so points along this line are always in view.
* In orthographic view all resulting segments will be parallel.
- * \param ar: The region (used for the window width and height).
+ * \param region: The region (used for the window width and height).
* \param v3d: The 3d viewport (used for near and far clipping range).
* \param mval: The area relative 2d location (such as event->mval, converted into float[2]).
* \param r_ray_start: The world-space starting point of the segment.
@@ -726,18 +732,18 @@ void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3
* \return success, false if the segment is totally clipped.
*/
bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph,
- const ARegion *ar,
+ const ARegion *region,
View3D *v3d,
const float mval[2],
float r_ray_start[3],
float r_ray_end[3],
const bool do_clip_planes)
{
- view3d_win_to_ray_segment(depsgraph, ar, v3d, mval, NULL, NULL, r_ray_start, r_ray_end);
+ view3d_win_to_ray_segment(depsgraph, region, v3d, mval, NULL, NULL, r_ray_start, r_ray_end);
/* bounds clipping */
if (do_clip_planes) {
- return ED_view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end);
+ return ED_view3d_clip_segment((RegionView3D *)region->regiondata, r_ray_start, r_ray_end);
}
return true;
@@ -767,21 +773,21 @@ void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d,
/**
* Convert between region relative coordinates (x,y) and depth component z and
* a point in world space. */
-void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3])
+void ED_view3d_project(const struct ARegion *region, const float world[3], float r_region_co[3])
{
// viewport is set up to make coordinates relative to the region, not window
- RegionView3D *rv3d = ar->regiondata;
- int viewport[4] = {0, 0, ar->winx, ar->winy};
+ RegionView3D *rv3d = region->regiondata;
+ int viewport[4] = {0, 0, region->winx, region->winy};
- GPU_matrix_project(world, rv3d->viewmat, rv3d->winmat, viewport, region);
+ GPU_matrix_project(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co);
}
bool ED_view3d_unproject(
- const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3])
+ const struct ARegion *region, float regionx, float regiony, float regionz, float world[3])
{
- RegionView3D *rv3d = ar->regiondata;
- int viewport[4] = {0, 0, ar->winx, ar->winy};
- float region[3] = {regionx, regiony, regionz};
+ RegionView3D *rv3d = region->regiondata;
+ int viewport[4] = {0, 0, region->winx, region->winy};
+ float region_co[3] = {regionx, regiony, regionz};
- return GPU_matrix_unproject(region, rv3d->viewmat, rv3d->winmat, viewport, world);
+ return GPU_matrix_unproject(region_co, rv3d->viewmat, rv3d->winmat, viewport, world);
}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 89baf60bd8c..2ce2edb98fe 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -21,32 +21,32 @@
* \ingroup spview3d
*/
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-#include <float.h>
#include <assert.h>
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
-#include "DNA_meta_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_tracking_types.h"
-#include "DNA_gpencil_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_array.h"
#include "BLI_bitmap.h"
-#include "BLI_math.h"
#include "BLI_lasso_2d.h"
-#include "BLI_rect.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -55,20 +55,20 @@
#endif
/* vertex box select */
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_curve.h"
+#include "BKE_editmesh.h"
#include "BKE_layer.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_editmesh.h"
#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "BKE_workspace.h"
@@ -84,16 +84,16 @@
#include "ED_armature.h"
#include "ED_curve.h"
+#include "ED_gpencil.h"
#include "ED_lattice.h"
-#include "ED_particle.h"
+#include "ED_mball.h"
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_outliner.h"
+#include "ED_particle.h"
#include "ED_screen.h"
-#include "ED_select_utils.h"
#include "ED_sculpt.h"
-#include "ED_mball.h"
-#include "ED_gpencil.h"
+#include "ED_select_utils.h"
#include "UI_interface.h"
@@ -124,7 +124,7 @@ void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc, Depsgraph *depsgra
{
memset(vc, 0, sizeof(ViewContext));
vc->C = C;
- vc->ar = CTX_wm_region(C);
+ vc->region = CTX_wm_region(C);
vc->bmain = CTX_data_main(C);
vc->depsgraph = depsgraph;
vc->scene = CTX_data_scene(C);
@@ -157,7 +157,7 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
static bool object_deselect_all_visible(ViewLayer *view_layer, View3D *v3d)
{
bool changed = false;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->flag & BASE_SELECTED) {
if (BASE_SELECTABLE(v3d, base)) {
ED_object_base_select(base, BA_DESELECT);
@@ -172,7 +172,7 @@ static bool object_deselect_all_visible(ViewLayer *view_layer, View3D *v3d)
static bool object_deselect_all_except(ViewLayer *view_layer, Base *b)
{
bool changed = false;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->flag & BASE_SELECTED) {
if (b != base) {
ED_object_base_select(base, BA_DESELECT);
@@ -408,8 +408,8 @@ typedef struct LassoSelectUserData {
const rcti *rect;
const rctf *rect_fl;
rctf _rect_fl;
- const int (*mcords)[2];
- int moves;
+ const int (*mcoords)[2];
+ int mcoords_len;
eSelectOp sel_op;
/* runtime */
@@ -421,8 +421,8 @@ typedef struct LassoSelectUserData {
static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
ViewContext *vc,
const rcti *rect,
- const int (*mcords)[2],
- const int moves,
+ const int (*mcoords)[2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
r_data->vc = vc;
@@ -431,8 +431,8 @@ static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
r_data->rect_fl = &r_data->_rect_fl;
BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
- r_data->mcords = mcords;
- r_data->moves = moves;
+ r_data->mcoords = mcoords;
+ r_data->mcoords_len = mcoords_len;
r_data->sel_op = sel_op;
/* runtime */
@@ -527,7 +527,8 @@ static void do_lasso_select_pose__do_tag(void *userData,
if (screen_co_a[0] != IS_CLIPPED) {
points_proj_tot++;
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) {
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) {
is_point_done = true;
}
}
@@ -536,22 +537,28 @@ static void do_lasso_select_pose__do_tag(void *userData,
if (screen_co_b[0] != IS_CLIPPED) {
points_proj_tot++;
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) {
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) {
is_point_done = true;
}
}
/* if one of points selected, we skip the bone itself */
- if ((is_point_done == true) ||
- ((is_point_done == false) && (points_proj_tot == 2) &&
- BLI_lasso_is_edge_inside(
- data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX))) {
+ if ((is_point_done == true) || ((is_point_done == false) && (points_proj_tot == 2) &&
+ BLI_lasso_is_edge_inside(data->mcoords,
+ data->mcoords_len,
+ UNPACK2(screen_co_a),
+ UNPACK2(screen_co_b),
+ INT_MAX))) {
pchan->bone->flag |= BONE_DONE;
}
data->is_changed |= is_point_done;
}
}
-static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves)
+static void do_lasso_tag_pose(ViewContext *vc,
+ Object *ob,
+ const int mcoords[][2],
+ const int mcoords_len)
{
ViewContext vc_tmp;
LassoSelectUserData data;
@@ -564,9 +571,9 @@ static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2]
vc_tmp = *vc;
vc_tmp.obact = ob;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, 0);
ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d);
@@ -574,8 +581,8 @@ static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2]
}
static bool do_lasso_select_objects(ViewContext *vc,
- const int mcords[][2],
- const short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
View3D *v3d = vc->v3d;
@@ -589,9 +596,9 @@ static bool do_lasso_select_objects(ViewContext *vc,
for (base = vc->view_layer->object_bases.first; base; base = base->next) {
if (BASE_SELECTABLE(v3d, base)) { /* use this to avoid un-needed lasso lookups */
const bool is_select = base->flag & BASE_SELECTED;
- const bool is_inside = ((ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) &&
+ const bool is_inside = ((ED_view3d_project_base(vc->region, base) == V3D_PROJ_RET_OK) &&
BLI_lasso_is_point_inside(
- mcords, moves, base->sx, base->sy, IS_CLIPPED));
+ mcoords, mcoords_len, base->sx, base->sy, IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT);
@@ -617,7 +624,7 @@ static Base **do_pose_tag_select_op_prepare(ViewContext *vc, uint *r_bases_len)
FOREACH_BASE_IN_MODE_BEGIN (vc->view_layer, vc->v3d, OB_ARMATURE, OB_MODE_POSE, base_iter) {
Object *ob_iter = base_iter->object;
bArmature *arm = ob_iter->data;
- for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_iter->pose->chanbase) {
Bone *bone = pchan->bone;
bone->flag &= ~BONE_DONE;
}
@@ -659,7 +666,7 @@ static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const
}
bool changed = true;
- for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_iter->pose->chanbase) {
Bone *bone = pchan->bone;
if ((bone->flag & BONE_UNSELECTABLE) == 0) {
const bool is_select = bone->flag & BONE_SELECTED;
@@ -685,8 +692,8 @@ static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const
}
static bool do_lasso_select_pose(ViewContext *vc,
- const int mcords[][2],
- const short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
uint bases_len;
@@ -695,7 +702,7 @@ static bool do_lasso_select_pose(ViewContext *vc,
for (int i = 0; i < bases_len; i++) {
Base *base_iter = bases[i];
Object *ob_iter = base_iter->object;
- do_lasso_tag_pose(vc, ob_iter, mcords, moves);
+ do_lasso_tag_pose(vc, ob_iter, mcoords, mcoords_len);
}
const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
@@ -715,9 +722,10 @@ static void do_lasso_select_mesh__doSelectVert(void *userData,
{
LassoSelectUserData *data = userData;
const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_vert_select_set(data->vc->em->bm, eve, sel_op_result);
@@ -746,8 +754,10 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data,
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
const bool is_inside =
(is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED));
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), IS_CLIPPED) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
@@ -770,8 +780,8 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data,
}
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords,
- data->moves,
+ const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcoords,
+ data->mcoords_len,
UNPACK2(screen_co_a),
UNPACK2(screen_co_b),
IS_CLIPPED));
@@ -789,9 +799,10 @@ static void do_lasso_select_mesh__doSelectFace(void *userData,
{
LassoSelectUserData *data = userData;
const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_face_select_set(data->vc->em->bm, efa, sel_op_result);
@@ -801,8 +812,8 @@ static void do_lasso_select_mesh__doSelectFace(void *userData,
static bool do_lasso_select_mesh(ViewContext *vc,
wmGenericUserData *wm_userdata,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
LassoSelectUserData data;
@@ -812,9 +823,9 @@ static bool do_lasso_select_mesh(ViewContext *vc,
/* set editmesh */
vc->em = BKE_editmesh_from_object(vc->obedit);
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
if (vc->em->bm->totvertsel) {
@@ -836,7 +847,7 @@ static bool do_lasso_select_mesh(ViewContext *vc,
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode);
esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(
- vc->depsgraph, vc->ar, vc->v3d, mcords, moves, &rect, NULL);
+ vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL);
}
}
@@ -897,7 +908,7 @@ static void do_lasso_select_curve__doSelect(void *userData,
LassoSelectUserData *data = userData;
const bool is_inside = BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED);
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED);
if (bp) {
const bool is_select = bp->f1 & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
@@ -930,16 +941,16 @@ static void do_lasso_select_curve__doSelect(void *userData,
}
static bool do_lasso_select_curve(ViewContext *vc,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
LassoSelectUserData data;
rcti rect;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
Curve *curve = (Curve *)vc->obedit->data;
@@ -958,9 +969,10 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const
{
LassoSelectUserData *data = userData;
const bool is_select = bp->f1 & SELECT;
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
@@ -968,16 +980,16 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const
}
}
static bool do_lasso_select_lattice(ViewContext *vc,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
LassoSelectUserData data;
rcti rect;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
data.is_changed |= ED_lattice_flags_set(vc->obedit, 0);
@@ -1002,7 +1014,8 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
if (screen_co_a[0] != IS_CLIPPED) {
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) {
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) {
is_inside_flag |= BONESEL_ROOT;
}
}
@@ -1012,7 +1025,8 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
if (screen_co_b[0] != IS_CLIPPED) {
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) {
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) {
is_inside_flag |= BONESEL_TIP;
}
}
@@ -1022,8 +1036,11 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
if (is_ignore_flag == 0) {
if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) ||
- BLI_lasso_is_edge_inside(
- data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) {
+ BLI_lasso_is_edge_inside(data->mcoords,
+ data->mcoords_len,
+ UNPACK2(screen_co_a),
+ UNPACK2(screen_co_b),
+ INT_MAX)) {
is_inside_flag |= BONESEL_BONE;
}
}
@@ -1033,16 +1050,16 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
}
static bool do_lasso_select_armature(ViewContext *vc,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
LassoSelectUserData data;
rcti rect;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit);
@@ -1071,9 +1088,10 @@ static void do_lasso_select_mball__doSelectElem(void *userData,
{
LassoSelectUserData *data = userData;
const bool is_select = ml->flag & SELECT;
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], INT_MAX));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT);
@@ -1081,8 +1099,8 @@ static void do_lasso_select_mball__doSelectElem(void *userData,
}
}
static bool do_lasso_select_meta(ViewContext *vc,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
LassoSelectUserData data;
@@ -1090,9 +1108,9 @@ static bool do_lasso_select_meta(ViewContext *vc,
MetaBall *mb = (MetaBall *)vc->obedit->data;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
data.is_changed |= BKE_mball_deselect_all(mb);
@@ -1113,9 +1131,10 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData,
{
LassoSelectUserData *data = userData;
const bool is_select = mv->flag & SELECT;
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
@@ -1124,8 +1143,8 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData,
}
static bool do_lasso_select_paintvert(ViewContext *vc,
wmGenericUserData *wm_userdata,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
@@ -1143,7 +1162,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
}
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
struct EditSelectBuf_Cache *esel = wm_userdata->data;
if (use_zbuf) {
@@ -1151,7 +1170,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX);
esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(
- vc->depsgraph, vc->ar, vc->v3d, mcords, moves, &rect, NULL);
+ vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL);
}
}
@@ -1163,7 +1182,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
else {
LassoSelectUserData data;
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
@@ -1185,8 +1204,8 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
}
static bool do_lasso_select_paintface(ViewContext *vc,
wmGenericUserData *wm_userdata,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
Object *ob = vc->obact;
@@ -1203,14 +1222,14 @@ static bool do_lasso_select_paintface(ViewContext *vc,
changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
}
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
struct EditSelectBuf_Cache *esel = wm_userdata->data;
if (esel == NULL) {
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE);
esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(
- vc->depsgraph, vc->ar, vc->v3d, mcords, moves, &rect, NULL);
+ vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL);
}
if (esel->select_bitmap) {
@@ -1224,9 +1243,9 @@ static bool do_lasso_select_paintface(ViewContext *vc,
}
#if 0
-static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp sel_op)
+static void do_lasso_select_node(int mcoords[][2], const int mcoords_len, const eSelectOp sel_op)
{
- SpaceNode *snode = sa->spacedata.first;
+ SpaceNode *snode = area->spacedata.first;
bNode *node;
rcti rect;
@@ -1234,7 +1253,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s
float node_centf[2];
bool changed = false;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
/* store selection in temp test flag */
for (node = snode->edittree->nodes.first; node; node = node->next) {
@@ -1244,7 +1263,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s
ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent);
const bool is_select = node->flag & SELECT;
const bool is_inside = (BLI_rcti_isect_pt_v(&rect, node_cent) &&
- BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1]));
+ BLI_lasso_is_point_inside(mcoords, mcoords_len, node_cent[0], node_cent[1]));
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(node->flag, sel_op_result, SELECT);
@@ -1257,8 +1276,11 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s
}
#endif
-static bool view3d_lasso_select(
- bContext *C, ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
+static bool view3d_lasso_select(bContext *C,
+ ViewContext *vc,
+ const int mcoords[][2],
+ const int mcoords_len,
+ const eSelectOp sel_op)
{
Object *ob = CTX_data_active_object(C);
bool changed_multi = false;
@@ -1268,26 +1290,26 @@ static bool view3d_lasso_select(
if (vc->obedit == NULL) { /* Object Mode */
if (BKE_paint_select_face_test(ob)) {
- changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcoords, mcoords_len, sel_op);
}
else if (BKE_paint_select_vert_test(ob)) {
- changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcoords, mcoords_len, sel_op);
}
else if (ob &&
(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
/* pass */
}
else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- changed_multi |= PE_lasso_select(C, mcords, moves, sel_op);
+ changed_multi |= PE_lasso_select(C, mcoords, mcoords_len, sel_op);
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
- changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_pose(vc, mcoords, mcoords_len, sel_op);
if (changed_multi) {
ED_outliner_select_sync_from_pose_bone_tag(C);
}
}
else {
- changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_objects(vc, mcoords, mcoords_len, sel_op);
if (changed_multi) {
ED_outliner_select_sync_from_object_tag(C);
}
@@ -1300,23 +1322,23 @@ static bool view3d_lasso_select(
switch (vc->obedit->type) {
case OB_MESH:
- changed = do_lasso_select_mesh(vc, wm_userdata, mcords, moves, sel_op);
+ changed = do_lasso_select_mesh(vc, wm_userdata, mcoords, mcoords_len, sel_op);
break;
case OB_CURVE:
case OB_SURF:
- changed = do_lasso_select_curve(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_curve(vc, mcoords, mcoords_len, sel_op);
break;
case OB_LATTICE:
- changed = do_lasso_select_lattice(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_lattice(vc, mcoords, mcoords_len, sel_op);
break;
case OB_ARMATURE:
- changed = do_lasso_select_armature(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_armature(vc, mcoords, mcoords_len, sel_op);
if (changed) {
ED_outliner_select_sync_from_edit_bone_tag(C);
}
break;
case OB_MBALL:
- changed = do_lasso_select_meta(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_meta(vc, mcoords, mcoords_len, sel_op);
break;
default:
BLI_assert(!"lasso select on incorrect object type");
@@ -1342,10 +1364,10 @@ static bool view3d_lasso_select(
static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
{
ViewContext vc;
- int mcords_tot;
- const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+ int mcoords_len;
+ const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len);
- if (mcords) {
+ if (mcoords) {
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
view3d_operator_needs_opengl(C);
BKE_object_update_select_id(CTX_data_main(C));
@@ -1354,9 +1376,9 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
ED_view3d_viewcontext_init(C, &vc, depsgraph);
eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- bool changed_multi = view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op);
+ bool changed_multi = view3d_lasso_select(C, &vc, mcoords, mcoords_len, sel_op);
- MEM_freeN((void *)mcords);
+ MEM_freeN((void *)mcoords);
if (changed_multi) {
return OPERATOR_FINISHED;
@@ -1566,7 +1588,7 @@ static Base *object_mouse_select_menu(bContext *C,
}
else {
const int dist = 15 * U.pixelsize;
- if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_base(vc->region, base) == V3D_PROJ_RET_OK) {
const int delta_px[2] = {base->sx - mval[0], base->sy - mval[1]};
if (len_manhattan_v2_int(delta_px) < dist) {
ok = true;
@@ -1663,20 +1685,31 @@ static int selectbuffer_ret_hits_5(uint *buffer,
/**
* Populate a select buffer with objects and bones, if there are any.
* Checks three selection levels and compare.
+ *
+ * \param do_nearest_xray_if_supported: When set, read in hits that don't stop
+ * at the nearest surface. The hit's must still be ordered by depth.
+ * Needed so we can step to the next, non-active object when it's already selected, see: T76445.
*/
static int mixed_bones_object_selectbuffer(ViewContext *vc,
uint *buffer,
const int mval[2],
eV3DSelectObjectFilter select_filter,
- bool do_nearest)
+ bool do_nearest,
+ bool do_nearest_xray_if_supported)
{
rcti rect;
int hits15, hits9 = 0, hits5 = 0;
bool has_bones15 = false, has_bones9 = false, has_bones5 = false;
- const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
+ int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
int hits = 0;
+ if (do_nearest_xray_if_supported) {
+ if ((U.gpu_flag & USER_GPU_FLAG_NO_DEPT_PICK) == 0) {
+ select_mode = VIEW3D_SELECT_PICK_ALL;
+ }
+ }
+
/* we _must_ end cache before return, use 'goto finally' */
view3d_opengl_select_cache_begin();
@@ -1780,7 +1813,7 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
do_nearest = do_nearest && !enumerate;
- int hits = mixed_bones_object_selectbuffer(vc, buffer, mval, select_filter, do_nearest);
+ int hits = mixed_bones_object_selectbuffer(vc, buffer, mval, select_filter, do_nearest, true);
return hits;
}
@@ -1912,7 +1945,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
const bool do_nearest = !XRAY_ACTIVE(vc.v3d);
const int hits = mixed_bones_object_selectbuffer(
- &vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest);
+ &vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest, false);
if (hits > 0) {
const bool has_bones = selectbuffer_has_bones(buffer, hits);
@@ -1971,7 +2004,7 @@ static bool ed_object_select_pick(bContext *C,
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc, depsgraph);
- ARegion *ar = CTX_wm_region(C);
+ const ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -1987,7 +2020,7 @@ static bool ed_object_select_pick(bContext *C,
is_obedit = (vc.obedit != NULL);
if (object) {
- /* signal for view3d_opengl_select to skip editmode objects */
+ /* Signal for #view3d_opengl_select to skip edit-mode objects. */
vc.obedit = NULL;
}
@@ -2003,7 +2036,7 @@ static bool ed_object_select_pick(bContext *C,
/* This block uses the control key to make the object selected
* by its center point rather than its contents */
- /* in editmode do not activate */
+ /* In edit-mode do not activate. */
if (obcenter) {
/* note; shift+alt goes to group-flush-selecting */
@@ -2015,7 +2048,7 @@ static bool ed_object_select_pick(bContext *C,
while (base) {
if (BASE_SELECTABLE(v3d, base)) {
float screen_co[2];
- if (ED_view3d_project_float_global(ar,
+ if (ED_view3d_project_float_global(region,
base->object->obmat[3],
screen_co,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN |
@@ -2265,7 +2298,8 @@ static bool ed_object_select_pick(bContext *C,
if (ELEM(basact->object->mode,
OB_MODE_PAINT_GPENCIL,
OB_MODE_SCULPT_GPENCIL,
- OB_MODE_WEIGHT_GPENCIL)) {
+ OB_MODE_WEIGHT_GPENCIL,
+ OB_MODE_VERTEX_GPENCIL)) {
ED_gpencil_toggle_brush_cursor(C, true, NULL);
}
else {
@@ -2336,11 +2370,11 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
bool toggle = RNA_boolean_get(op->ptr, "toggle");
bool center = RNA_boolean_get(op->ptr, "center");
bool enumerate = RNA_boolean_get(op->ptr, "enumerate");
- /* only force object select for editmode to support vertex parenting,
- * or paint-select to allow pose bone select with vert/face select */
+ /* Only force object select for edit-mode to support vertex parenting,
+ * or paint-select to allow pose bone select with vert/face select. */
bool object = (RNA_boolean_get(op->ptr, "object") &&
(obedit || BKE_paint_select_elem_test(obact) ||
- /* so its possible to select bones in weightpaint mode (LMB select) */
+ /* so its possible to select bones in weight-paint mode (LMB select) */
(obact && (obact->mode & OB_MODE_WEIGHT_PAINT) &&
BKE_object_pose_armature_get(obact))));
@@ -2357,8 +2391,8 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
obact = NULL;
/* ack, this is incorrect but to do this correctly we would need an
- * alternative editmode/objectmode keymap, this copies the functionality
- * from 2.4x where Ctrl+Select in editmode does object select only */
+ * alternative edit-mode/object-mode keymap, this copies the functionality
+ * from 2.4x where Ctrl+Select in edit-mode does object select only. */
center = false;
}
@@ -2492,12 +2526,12 @@ void VIEW3D_OT_select(wmOperatorType *ot)
"center",
0,
"Center",
- "Use the object center when selecting, in editmode used to extend object selection");
+ "Use the object center when selecting, in edit-mode used to extend object selection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(
ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only)");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "object", 0, "Object", "Use object selection (editmode only)");
+ prop = RNA_def_boolean(ot->srna, "object", 0, "Object", "Use object selection (edit-mode only)");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_int_vector(ot->srna,
@@ -2600,7 +2634,7 @@ static bool do_paintvert_box_select(ViewContext *vc,
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX);
esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_rect(
- vc->depsgraph, vc->ar, vc->v3d, rect, NULL);
+ vc->depsgraph, vc->region, vc->v3d, rect, NULL);
}
if (esel->select_bitmap != NULL) {
changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op);
@@ -2655,7 +2689,7 @@ static bool do_paintface_box_select(ViewContext *vc,
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE);
esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_rect(
- vc->depsgraph, vc->ar, vc->v3d, rect, NULL);
+ vc->depsgraph, vc->region, vc->v3d, rect, NULL);
}
if (esel->select_bitmap != NULL) {
changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op);
@@ -2857,7 +2891,7 @@ static bool do_mesh_box_select(ViewContext *vc,
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode);
esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_rect(
- vc->depsgraph, vc->ar, vc->v3d, rect, NULL);
+ vc->depsgraph, vc->region, vc->v3d, rect, NULL);
}
}
@@ -3075,7 +3109,7 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
const int hits = view3d_opengl_select(
vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
- for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &vc->view_layer->object_bases) {
base->object->id.tag &= ~LIB_TAG_DOIT;
}
@@ -3091,7 +3125,7 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
goto finally;
}
- for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &vc->view_layer->object_bases) {
if (BASE_SELECTABLE(v3d, base)) {
if ((base->object->runtime.select_id & 0x0000FFFF) != 0) {
BLI_array_append(bases, base);
@@ -3103,9 +3137,9 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
- Bone *bone;
- Base *base = ED_armature_base_and_bone_from_select_buffer(
- bases, BLI_array_len(bases), *col, &bone);
+ bPoseChannel *pchan_dummy;
+ Base *base = ED_armature_base_and_pchan_from_select_buffer(
+ bases, BLI_array_len(bases), *col, &pchan_dummy);
if (base != NULL) {
base->object->id.tag |= LIB_TAG_DOIT;
}
@@ -3285,7 +3319,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
}
FOREACH_OBJECT_IN_MODE_END;
}
- else { /* no editmode, unified for bones and objects */
+ else { /* No edit-mode, unified for bones and objects. */
if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) {
/* XXX, this is not selection, could be it's own operator. */
changed_multi = ED_sculpt_mask_box_select(
@@ -3456,7 +3490,7 @@ static bool mesh_circle_select(ViewContext *vc,
if (use_zbuf) {
if (esel->select_bitmap == NULL) {
esel->select_bitmap = DRW_select_buffer_bitmap_from_circle(
- vc->depsgraph, vc->ar, vc->v3d, mval, (int)(rad + 1.0f), NULL);
+ vc->depsgraph, vc->region, vc->v3d, mval, (int)(rad + 1.0f), NULL);
}
}
@@ -3528,7 +3562,7 @@ static bool paint_facesel_circle_select(ViewContext *vc,
{
struct EditSelectBuf_Cache *esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_circle(
- vc->depsgraph, vc->ar, vc->v3d, mval, (int)(rad + 1.0f), NULL);
+ vc->depsgraph, vc->region, vc->v3d, mval, (int)(rad + 1.0f), NULL);
if (esel->select_bitmap != NULL) {
changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op);
MEM_freeN(esel->select_bitmap);
@@ -3583,7 +3617,7 @@ static bool paint_vertsel_circle_select(ViewContext *vc,
if (use_zbuf) {
struct EditSelectBuf_Cache *esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_circle(
- vc->depsgraph, vc->ar, vc->v3d, mval, (int)(rad + 1.0f), NULL);
+ vc->depsgraph, vc->region, vc->v3d, mval, (int)(rad + 1.0f), NULL);
if (esel->select_bitmap != NULL) {
changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op);
MEM_freeN(esel->select_bitmap);
@@ -3999,7 +4033,7 @@ static bool object_circle_select(ViewContext *vc,
for (base = FIRSTBASE(view_layer); base; base = base->next) {
if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) {
float screen_co[2];
- if (ED_view3d_project_float_global(vc->ar,
+ if (ED_view3d_project_float_global(vc->region,
base->object->obmat[3],
screen_co,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN |
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index f13f41779c2..437c0dd4035 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -26,9 +26,10 @@
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
+#include "BLI_array.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -51,10 +52,10 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "ED_object.h"
-#include "ED_transverts.h"
#include "ED_keyframing.h"
+#include "ED_object.h"
#include "ED_screen.h"
+#include "ED_transverts.h"
#include "view3d_intern.h"
@@ -188,16 +189,47 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
+ const bool use_transform_skip_children = (scene->toolsettings->transform_flag &
+ SCE_XFORM_SKIP_CHILDREN);
const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
SCE_XFORM_DATA_ORIGIN);
+ struct XFormObjectSkipChild_Container *xcs = NULL;
struct XFormObjectData_Container *xds = NULL;
+ /* Build object array. */
+ Object **objects_eval = NULL;
+ uint objects_eval_len;
+ {
+ BLI_array_declare(objects_eval);
+ FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
+ BLI_array_append(objects_eval, ob_eval);
+ }
+ FOREACH_SELECTED_EDITABLE_OBJECT_END;
+ objects_eval_len = BLI_array_len(objects_eval);
+ }
+
+ if (use_transform_skip_children) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ Object **objects = MEM_malloc_arrayN(objects_eval_len, sizeof(*objects), __func__);
+
+ for (int ob_index = 0; ob_index < objects_eval_len; ob_index++) {
+ Object *ob_eval = objects_eval[ob_index];
+ objects[ob_index] = DEG_get_original_object(ob_eval);
+ }
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+ xcs = ED_object_xform_skip_child_container_create();
+ ED_object_xform_skip_child_container_item_ensure_from_array(
+ xcs, view_layer, objects, objects_eval_len);
+ MEM_freeN(objects);
+ }
if (use_transform_data_origin) {
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
xds = ED_object_data_xform_container_create();
}
- FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
+ for (int ob_index = 0; ob_index < objects_eval_len; ob_index++) {
+ Object *ob_eval = objects_eval[ob_index];
Object *ob = DEG_get_original_object(ob_eval);
vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf);
vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf);
@@ -229,8 +261,15 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
- FOREACH_SELECTED_EDITABLE_OBJECT_END;
+ if (objects_eval) {
+ MEM_freeN(objects_eval);
+ }
+
+ if (use_transform_skip_children) {
+ ED_object_xform_skip_child_container_update_all(xcs, bmain, depsgraph);
+ ED_object_xform_skip_child_container_destroy(xcs);
+ }
if (use_transform_data_origin) {
ED_object_data_xform_container_update_all(xds, bmain, depsgraph);
ED_object_data_xform_container_destroy(xds);
@@ -427,41 +466,52 @@ static int snap_selected_to_location(bContext *C,
Main *bmain = CTX_data_main(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- ListBase ctx_data_list;
- CollectionPointerLink *ctx_ob;
- Object *ob;
-
- CTX_data_selected_editable_objects(C, &ctx_data_list);
-
- /* reset flags */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ /* Reset flags. */
+ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
ob->flag &= ~OB_DONE;
}
- /* tag objects we're transforming */
- for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
- ob = ctx_ob->ptr.data;
- ob->flag |= OB_DONE;
+ /* Build object array, tag objects we're transforming. */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object **objects = NULL;
+ uint objects_len;
+ {
+ BLI_array_declare(objects);
+ FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer, v3d, ob) {
+ BLI_array_append(objects, ob);
+ ob->flag |= OB_DONE;
+ }
+ FOREACH_SELECTED_EDITABLE_OBJECT_END;
+ objects_len = BLI_array_len(objects);
}
+ const bool use_transform_skip_children = (scene->toolsettings->transform_flag &
+ SCE_XFORM_SKIP_CHILDREN);
const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
SCE_XFORM_DATA_ORIGIN);
+ struct XFormObjectSkipChild_Container *xcs = NULL;
struct XFormObjectData_Container *xds = NULL;
+ if (use_transform_skip_children) {
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+ xcs = ED_object_xform_skip_child_container_create();
+ ED_object_xform_skip_child_container_item_ensure_from_array(
+ xcs, view_layer, objects, objects_len);
+ }
if (use_transform_data_origin) {
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
xds = ED_object_data_xform_container_create();
/* Initialize the transform data in a separate loop because the depsgraph
* may be evaluated while setting the locations. */
- for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
- ob = ctx_ob->ptr.data;
+ for (int ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
ED_object_data_xform_container_item_ensure(xds, ob);
}
}
- for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
- ob = ctx_ob->ptr.data;
+ for (int ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {
@@ -505,8 +555,14 @@ static int snap_selected_to_location(bContext *C,
}
}
- BLI_freelistN(&ctx_data_list);
+ if (objects) {
+ MEM_freeN(objects);
+ }
+ if (use_transform_skip_children) {
+ ED_object_xform_skip_child_container_update_all(xcs, bmain, depsgraph);
+ ED_object_xform_skip_child_container_destroy(xcs);
+ }
if (use_transform_data_origin) {
ED_object_data_xform_container_update_all(xds, bmain, depsgraph);
ED_object_data_xform_container_destroy(xds);
@@ -659,7 +715,7 @@ static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3])
copy_m4_m4(cammat, ob->obmat);
- BKE_tracking_get_camera_object_matrix(scene, ob, mat);
+ BKE_tracking_get_camera_object_matrix(ob, mat);
INIT_MINMAX(min, max);
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 1af94e3ade5..09e1dca3152 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -23,10 +23,10 @@
* 3D View checks and manipulation (no operators).
*/
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
@@ -44,8 +44,8 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_object.h"
-#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -181,21 +181,21 @@ bool ED_view3d_viewplane_get(Depsgraph *depsgraph,
void view3d_operator_needs_opengl(const bContext *C)
{
wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- view3d_region_operator_needs_opengl(win, ar);
+ view3d_region_operator_needs_opengl(win, region);
}
-void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *ar)
+void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *region)
{
/* for debugging purpose, context should always be OK */
- if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
+ if ((region == NULL) || (region->regiontype != RGN_TYPE_WINDOW)) {
printf("view3d_region_operator_needs_opengl error, wrong region\n");
}
else {
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
- wmViewport(&ar->winrct); // TODO: bad
+ wmViewport(&region->winrct); // TODO: bad
GPU_matrix_projection_set(rv3d->winmat);
GPU_matrix_set(rv3d->viewmat);
}
@@ -228,27 +228,27 @@ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
bool ED_view3d_context_activate(bContext *C)
{
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar;
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region;
- /* sa can be NULL when called from python */
- if (sa == NULL || sa->spacetype != SPACE_VIEW3D) {
- sa = BKE_screen_find_big_area(sc, SPACE_VIEW3D, 0);
+ /* area can be NULL when called from python */
+ if (area == NULL || area->spacetype != SPACE_VIEW3D) {
+ area = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0);
}
- if (sa == NULL) {
+ if (area == NULL) {
return false;
}
- ar = BKE_area_find_region_active_win(sa);
- if (ar == NULL) {
+ region = BKE_area_find_region_active_win(area);
+ if (region == NULL) {
return false;
}
/* bad context switch .. */
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
return true;
}
@@ -277,7 +277,7 @@ void ED_view3d_clipping_calc_from_boundbox(float clip[4][4],
}
void ED_view3d_clipping_calc(
- BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
+ BoundBox *bb, float planes[4][4], const ARegion *region, const Object *ob, const rcti *rect)
{
/* init in case unproject fails */
memset(bb->vec, 0, sizeof(bb->vec));
@@ -288,8 +288,8 @@ void ED_view3d_clipping_calc(
float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
- ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]);
- ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]);
+ ED_view3d_unproject(region, xs, ys, 0.0, bb->vec[val]);
+ ED_view3d_unproject(region, xs, ys, 1.0, bb->vec[4 + val]);
}
/* optionally transform to object space */
@@ -398,7 +398,7 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
{
- return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
+ return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_center_cursor || v3d->ob_center);
}
/**
@@ -408,6 +408,7 @@ void ED_view3d_lastview_store(RegionView3D *rv3d)
{
copy_qt_qt(rv3d->lviewquat, rv3d->viewquat);
rv3d->lview = rv3d->view;
+ rv3d->lview_axis_roll = rv3d->view_axis_roll;
if (rv3d->persp != RV3D_CAMOB) {
rv3d->lpersp = rv3d->persp;
}
@@ -415,9 +416,10 @@ void ED_view3d_lastview_store(RegionView3D *rv3d)
void ED_view3d_lock_clear(View3D *v3d)
{
- v3d->ob_centre = NULL;
- v3d->ob_centre_bone[0] = '\0';
- v3d->ob_centre_cursor = false;
+ v3d->ob_center = NULL;
+ v3d->ob_center_bone[0] = '\0';
+ v3d->ob_center_cursor = false;
+
v3d->flag2 &= ~V3D_LOCK_CAMERA;
}
@@ -452,12 +454,12 @@ void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph,
*
* shared with NDOF.
*/
-bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *ar)
+bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *region)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
- BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
+ BLI_assert((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0);
if (ED_view3d_camera_lock_check(v3d, rv3d)) {
return false;
@@ -585,8 +587,11 @@ bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionV
}
}
-bool ED_view3d_camera_autokey(
- Scene *scene, ID *id_key, struct bContext *C, const bool do_rotate, const bool do_translate)
+bool ED_view3d_camera_autokey(const Scene *scene,
+ ID *id_key,
+ struct bContext *C,
+ const bool do_rotate,
+ const bool do_translate)
{
if (autokeyframe_cfra_can_key(scene, id_key)) {
const float cfra = (float)CFRA;
@@ -661,30 +666,30 @@ bool ED_view3d_camera_lock_autokey(View3D *v3d,
* Use with quad-split so each view is clipped by the bounds of each view axis.
* \{ */
-static void view3d_boxview_clip(ScrArea *sa)
+static void view3d_boxview_clip(ScrArea *area)
{
- ARegion *ar;
+ ARegion *region;
BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb");
float clip[6][4];
float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f};
int val;
/* create bounding box */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
- if (rv3d->viewlock & RV3D_BOXCLIP) {
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) {
if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
- if (ar->winx > ar->winy) {
+ if (region->winx > region->winy) {
x1 = rv3d->dist;
}
else {
- x1 = ar->winx * rv3d->dist / ar->winy;
+ x1 = region->winx * rv3d->dist / region->winy;
}
- if (ar->winx > ar->winy) {
- y1 = ar->winy * rv3d->dist / ar->winx;
+ if (region->winx > region->winy) {
+ y1 = region->winy * rv3d->dist / region->winx;
}
else {
y1 = rv3d->dist;
@@ -694,8 +699,8 @@ static void view3d_boxview_clip(ScrArea *sa)
else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
ofs[2] = rv3d->ofs[2];
- if (ar->winx > ar->winy) {
- z1 = ar->winy * rv3d->dist / ar->winx;
+ if (region->winx > region->winy) {
+ z1 = region->winy * rv3d->dist / region->winx;
}
else {
z1 = rv3d->dist;
@@ -742,11 +747,11 @@ static void view3d_boxview_clip(ScrArea *sa)
}
/* create bounding box */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
- if (rv3d->viewlock & RV3D_BOXCLIP) {
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) {
rv3d->rflag |= RV3D_CLIPPING;
memcpy(rv3d->clip, clip, sizeof(clip));
if (rv3d->clipbb) {
@@ -781,14 +786,16 @@ static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_
int i;
/* we could use rv3d->viewinv, but better not depend on view matrix being updated */
- if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, viewinv) == false)) {
+ if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, rv3d_src->view_axis_roll, viewinv) ==
+ false)) {
return;
}
invert_qt_normalized(viewinv);
mul_qt_v3(viewinv, view_src_x);
mul_qt_v3(viewinv, view_src_y);
- if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, viewinv) == false)) {
+ if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, rv3d_dst->view_axis_roll, viewinv) ==
+ false)) {
return;
}
invert_qt_normalized(viewinv);
@@ -805,20 +812,20 @@ static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_
}
/* sync center/zoom view of region to others, for view transforms */
-void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
+void view3d_boxview_sync(ScrArea *area, ARegion *region)
{
ARegion *artest;
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
short clip = 0;
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
- if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
+ for (artest = area->regionbase.first; artest; artest = artest->next) {
+ if (artest != region && artest->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3dtest = artest->regiondata;
- if (rv3dtest->viewlock & RV3D_LOCKED) {
+ if (RV3D_LOCK_FLAGS(rv3dtest) & RV3D_LOCK_ROTATION) {
rv3dtest->dist = rv3d->dist;
view3d_boxview_sync_axis(rv3dtest, rv3d);
- clip |= rv3dtest->viewlock & RV3D_BOXCLIP;
+ clip |= RV3D_LOCK_FLAGS(rv3dtest) & RV3D_BOXCLIP;
ED_region_tag_redraw(artest);
}
@@ -826,48 +833,48 @@ void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
}
if (clip) {
- view3d_boxview_clip(sa);
+ view3d_boxview_clip(area);
}
}
/* for home, center etc */
-void view3d_boxview_copy(ScrArea *sa, ARegion *ar)
+void view3d_boxview_copy(ScrArea *area, ARegion *region)
{
ARegion *artest;
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
bool clip = false;
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
- if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
+ for (artest = area->regionbase.first; artest; artest = artest->next) {
+ if (artest != region && artest->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3dtest = artest->regiondata;
- if (rv3dtest->viewlock) {
+ if (RV3D_LOCK_FLAGS(rv3dtest)) {
rv3dtest->dist = rv3d->dist;
copy_v3_v3(rv3dtest->ofs, rv3d->ofs);
ED_region_tag_redraw(artest);
- clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0);
+ clip |= ((RV3D_LOCK_FLAGS(rv3dtest) & RV3D_BOXCLIP) != 0);
}
}
}
if (clip) {
- view3d_boxview_clip(sa);
+ view3d_boxview_clip(area);
}
}
/* 'clip' is used to know if our clip setting has changed */
-void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
+void ED_view3d_quadview_update(ScrArea *area, ARegion *region, bool do_clip)
{
- ARegion *ar_sync = NULL;
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region_sync = NULL;
+ RegionView3D *rv3d = region->regiondata;
short viewlock;
/* this function copies flags from the first of the 3 other quadview
* regions to the 2 other, so it assumes this is the region whose
* properties are always being edited, weak */
viewlock = rv3d->viewlock;
- if ((viewlock & RV3D_LOCKED) == 0) {
+ if ((viewlock & RV3D_LOCK_ROTATION) == 0) {
do_clip = (viewlock & RV3D_BOXCLIP) != 0;
viewlock = 0;
}
@@ -876,35 +883,36 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
viewlock &= ~RV3D_BOXCLIP;
}
- for (; ar; ar = ar->prev) {
- if (ar->alignment == RGN_ALIGN_QSPLIT) {
- rv3d = ar->regiondata;
+ for (; region; region = region->prev) {
+ if (region->alignment == RGN_ALIGN_QSPLIT) {
+ rv3d = region->regiondata;
rv3d->viewlock = viewlock;
if (do_clip && (viewlock & RV3D_BOXCLIP) == 0) {
rv3d->rflag &= ~RV3D_BOXCLIP;
}
- /* use ar_sync so we sync with one of the aligned views below
+ /* use region_sync so we sync with one of the aligned views below
* else the view jumps on changing view settings like 'clip'
* since it copies from the perspective view */
- ar_sync = ar;
+ region_sync = region;
}
}
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last);
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(area, region_sync ? region_sync : area->regionbase.last);
}
/* ensure locked regions have an axis, locked user views don't make much sense */
- if (viewlock & RV3D_LOCKED) {
+ if (viewlock & RV3D_LOCK_ROTATION) {
int index_qsplit = 0;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->alignment == RGN_ALIGN_QSPLIT) {
- rv3d = ar->regiondata;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->alignment == RGN_ALIGN_QSPLIT) {
+ rv3d = region->regiondata;
if (rv3d->viewlock) {
- if (!RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ if (!RV3D_VIEW_IS_AXIS(rv3d->view) || (rv3d->view_axis_roll != RV3D_VIEW_AXIS_ROLL_0)) {
rv3d->view = ED_view3d_lock_view_from_index(index_qsplit);
+ rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
rv3d->persp = RV3D_ORTHO;
ED_view3d_lock(rv3d);
}
@@ -914,7 +922,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
}
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
/** \} */
@@ -923,7 +931,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
/** \name View Auto-Depth Utilities
* \{ */
-static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int margin)
+static float view_autodist_depth_margin(ARegion *region, const int mval[2], int margin)
{
ViewDepths depth_temp = {0};
rcti rect;
@@ -940,7 +948,7 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
BLI_rcti_init_pt_radius(&rect, mval, margin);
}
- view3d_update_depths_rect(ar, &depth_temp, &rect);
+ view3d_update_depths_rect(region, &depth_temp, &rect);
depth_close = view3d_depth_near(&depth_temp);
MEM_SAFE_FREE(depth_temp.depths);
return depth_close;
@@ -954,7 +962,7 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
* \param fallback_depth_pt: Use this points depth when no depth can be found.
*/
bool ED_view3d_autodist(Depsgraph *depsgraph,
- ARegion *ar,
+ ARegion *region,
View3D *v3d,
const int mval[2],
float mouse_worldloc[3],
@@ -967,12 +975,12 @@ bool ED_view3d_autodist(Depsgraph *depsgraph,
bool depth_ok = false;
/* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(depsgraph, ar, v3d, alphaoverride);
+ ED_view3d_draw_depth(depsgraph, region, v3d, alphaoverride);
/* Attempt with low margin's first */
i = 0;
do {
- depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize);
+ depth_close = view_autodist_depth_margin(region, mval, margin_arr[i++] * U.pixelsize);
depth_ok = (depth_close != FLT_MAX);
} while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
@@ -980,13 +988,13 @@ bool ED_view3d_autodist(Depsgraph *depsgraph,
float centx = (float)mval[0] + 0.5f;
float centy = (float)mval[1] + 0.5f;
- if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) {
+ if (ED_view3d_unproject(region, centx, centy, depth_close, mouse_worldloc)) {
return true;
}
}
if (fallback_depth_pt) {
- ED_view3d_win_to_3d_int(v3d, ar, fallback_depth_pt, mval, mouse_worldloc);
+ ED_view3d_win_to_3d_int(v3d, region, fallback_depth_pt, mval, mouse_worldloc);
return true;
}
else {
@@ -994,16 +1002,16 @@ bool ED_view3d_autodist(Depsgraph *depsgraph,
}
}
-void ED_view3d_autodist_init(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, int mode)
+void ED_view3d_autodist_init(Depsgraph *depsgraph, ARegion *region, View3D *v3d, int mode)
{
/* Get Z Depths, needed for perspective, nice for ortho */
switch (mode) {
case 0:
- ED_view3d_draw_depth(depsgraph, ar, v3d, true);
+ ED_view3d_draw_depth(depsgraph, region, v3d, true);
break;
case 1: {
Scene *scene = DEG_get_evaluated_scene(depsgraph);
- ED_view3d_draw_depth_gpencil(depsgraph, scene, ar, v3d);
+ ED_view3d_draw_depth_gpencil(depsgraph, scene, region, v3d);
break;
}
}
@@ -1011,7 +1019,7 @@ void ED_view3d_autodist_init(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, int
/* no 4x4 sampling, run #ED_view3d_autodist_init first */
bool ED_view3d_autodist_simple(
- ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth)
+ ARegion *region, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth)
{
float depth;
@@ -1020,7 +1028,7 @@ bool ED_view3d_autodist_simple(
depth = *force_depth;
}
else {
- depth = view_autodist_depth_margin(ar, mval, margin);
+ depth = view_autodist_depth_margin(region, mval, margin);
}
if (depth == FLT_MAX) {
@@ -1029,12 +1037,12 @@ bool ED_view3d_autodist_simple(
float centx = (float)mval[0] + 0.5f;
float centy = (float)mval[1] + 0.5f;
- return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
+ return ED_view3d_unproject(region, centx, centy, depth, mouse_worldloc);
}
-bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
+bool ED_view3d_autodist_depth(ARegion *region, const int mval[2], int margin, float *depth)
{
- *depth = view_autodist_depth_margin(ar, mval, margin);
+ *depth = view_autodist_depth_margin(region, mval, margin);
return (*depth != FLT_MAX);
}
@@ -1042,7 +1050,7 @@ bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float
static bool depth_segment_cb(int x, int y, void *userData)
{
struct {
- ARegion *ar;
+ ARegion *region;
int margin;
float depth;
} *data = userData;
@@ -1052,7 +1060,7 @@ static bool depth_segment_cb(int x, int y, void *userData)
mval[0] = x;
mval[1] = y;
- depth = view_autodist_depth_margin(data->ar, mval, data->margin);
+ depth = view_autodist_depth_margin(data->region, mval, data->margin);
if (depth != FLT_MAX) {
data->depth = depth;
@@ -1064,17 +1072,17 @@ static bool depth_segment_cb(int x, int y, void *userData)
}
bool ED_view3d_autodist_depth_seg(
- ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth)
+ ARegion *region, const int mval_sta[2], const int mval_end[2], int margin, float *depth)
{
struct {
- ARegion *ar;
+ ARegion *region;
int margin;
float depth;
} data = {NULL};
int p1[2];
int p2[2];
- data.ar = ar;
+ data.region = region;
data.margin = margin;
data.depth = FLT_MAX;
@@ -1125,14 +1133,14 @@ float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
* +
* </pre>
*
- * \param ar: Can be NULL if \a use_aspect is false.
+ * \param region: Can be NULL if \a use_aspect is false.
* \param persp: Allow the caller to tell what kind of perspective to use (ortho/view/camera)
* \param use_aspect: Increase the distance to account for non 1:1 view aspect.
* \param radius: The radius will be fitted exactly,
* typically pre-scaled by a margin (#VIEW3D_MARGIN).
*/
float ED_view3d_radius_to_dist(const View3D *v3d,
- const ARegion *ar,
+ const ARegion *region,
const struct Depsgraph *depsgraph,
const char persp,
const bool use_aspect,
@@ -1180,18 +1188,18 @@ float ED_view3d_radius_to_dist(const View3D *v3d,
}
if (use_aspect) {
- const RegionView3D *rv3d = ar->regiondata;
+ const RegionView3D *rv3d = region->regiondata;
float winx, winy;
if (persp == RV3D_CAMOB) {
/* camera frame x/y in pixels */
- winx = ar->winx / rv3d->viewcamtexcofac[0];
- winy = ar->winy / rv3d->viewcamtexcofac[1];
+ winx = region->winx / rv3d->viewcamtexcofac[0];
+ winy = region->winy / rv3d->viewcamtexcofac[1];
}
else {
- winx = ar->winx;
- winy = ar->winy;
+ winx = region->winx;
+ winy = region->winy;
}
if (winx && winy) {
@@ -1304,19 +1312,62 @@ bool ED_view3d_distance_set_from_location(RegionView3D *rv3d,
/* -------------------------------------------------------------------- */
/** \name View Axis Utilities
* \{ */
-static float view3d_quat_axis[6][4] = {
- {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, /* RV3D_VIEW_FRONT */
- {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, /* RV3D_VIEW_BACK */
- {0.5f, -0.5f, 0.5f, 0.5f}, /* RV3D_VIEW_LEFT */
- {0.5f, -0.5f, -0.5f, -0.5f}, /* RV3D_VIEW_RIGHT */
- {1.0f, 0.0f, 0.0f, 0.0f}, /* RV3D_VIEW_TOP */
- {0.0f, -1.0f, 0.0f, 0.0f}, /* RV3D_VIEW_BOTTOM */
+
+/**
+ * Lookup by axis-view, axis-roll.
+ */
+static float view3d_quat_axis[6][4][4] = {
+ /* RV3D_VIEW_FRONT */
+ {
+ {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f},
+ {0.5f, -0.5f, -0.5f, 0.5f},
+ {0, 0, -M_SQRT1_2, M_SQRT1_2},
+ {-0.5f, 0.5f, -0.5f, 0.5f},
+ },
+ /* RV3D_VIEW_BACK */
+ {
+ {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2},
+ {0.5f, 0.5f, -0.5f, -0.5f},
+ {M_SQRT1_2, M_SQRT1_2, 0, 0},
+ {0.5f, 0.5f, 0.5f, 0.5f},
+ },
+ /* RV3D_VIEW_LEFT */
+ {
+ {0.5f, -0.5f, 0.5f, 0.5f},
+ {0, -M_SQRT1_2, 0.0f, M_SQRT1_2},
+ {-0.5f, -0.5f, -0.5f, 0.5f},
+ {-M_SQRT1_2, 0, -M_SQRT1_2, 0},
+ },
+
+ /* RV3D_VIEW_RIGHT */
+ {
+ {0.5f, -0.5f, -0.5f, -0.5f},
+ {M_SQRT1_2, 0, -M_SQRT1_2, 0},
+ {0.5f, 0.5f, -0.5f, 0.5f},
+ {0, M_SQRT1_2, 0, M_SQRT1_2},
+ },
+ /* RV3D_VIEW_TOP */
+ {
+ {1.0f, 0.0f, 0.0f, 0.0f},
+ {M_SQRT1_2, 0, 0, M_SQRT1_2},
+ {0, 0, 0, 1},
+ {-M_SQRT1_2, 0, 0, M_SQRT1_2},
+ },
+ /* RV3D_VIEW_BOTTOM */
+ {
+ {0.0f, -1.0f, 0.0f, 0.0f},
+ {0, -M_SQRT1_2, -M_SQRT1_2, 0},
+ {0, 0, -1, 0},
+ {0, M_SQRT1_2, -M_SQRT1_2, 0},
+ },
+
};
-bool ED_view3d_quat_from_axis_view(const char view, float quat[4])
+bool ED_view3d_quat_from_axis_view(const char view, const char view_axis_roll, float quat[4])
{
+ BLI_assert(view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270);
if (RV3D_VIEW_IS_AXIS(view)) {
- copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]);
+ copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT][view_axis_roll]);
return true;
}
else {
@@ -1324,19 +1375,28 @@ bool ED_view3d_quat_from_axis_view(const char view, float quat[4])
}
}
-char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon)
+bool ED_view3d_quat_to_axis_view(const float quat[4],
+ const float epsilon,
+ char *r_view,
+ char *r_view_axis_roll)
{
- /* quat values are all unit length */
-
- char view;
+ *r_view = RV3D_VIEW_USER;
+ *r_view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
- for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) {
- if (fabsf(angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT])) < epsilon) {
- return view;
+ /* quat values are all unit length */
+ for (int view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) {
+ for (int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270;
+ view_axis_roll++) {
+ if (fabsf(angle_signed_qtqt(
+ quat, view3d_quat_axis[view - RV3D_VIEW_FRONT][view_axis_roll])) < epsilon) {
+ *r_view = view;
+ *r_view_axis_roll = view_axis_roll;
+ return true;
+ }
}
}
- return RV3D_VIEW_USER;
+ return false;
}
char ED_view3d_lock_view_from_index(int index)
@@ -1375,7 +1435,7 @@ char ED_view3d_axis_view_opposite(char view)
bool ED_view3d_lock(RegionView3D *rv3d)
{
- return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat);
+ return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, rv3d->viewquat);
}
/** \} */
@@ -1512,7 +1572,7 @@ bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
bool depths_valid[9] = {false};
float coords[9][3] = {{0}};
- ARegion *ar = vc->ar;
+ ARegion *region = vc->region;
const ViewDepths *depths = vc->rv3d->depths;
for (int x = 0, i = 0; x < 2; x++) {
@@ -1521,7 +1581,7 @@ bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs);
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) {
+ if (ED_view3d_depth_unproject(region, mval_ofs, depth, coords[i])) {
depths_valid[i] = true;
}
}
@@ -1558,14 +1618,14 @@ bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
}
}
-bool ED_view3d_depth_unproject(const ARegion *ar,
+bool ED_view3d_depth_unproject(const ARegion *region,
const int mval[2],
const double depth,
float r_location_world[3])
{
float centx = (float)mval[0] + 0.5f;
float centy = (float)mval[1] + 0.5f;
- return ED_view3d_unproject(ar, centx, centy, depth, r_location_world);
+ return ED_view3d_unproject(region, centx, centy, depth, r_location_world);
}
void ED_view3d_depth_tag_update(RegionView3D *rv3d)
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 8b4012d6547..fe77ca05a04 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -22,25 +22,26 @@
*/
#include "DNA_camera_types.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
+#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
-#include "BLI_linklist.h"
#include "BKE_action.h"
#include "BKE_camera.h"
#include "BKE_context.h"
-#include "BKE_object.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -50,8 +51,8 @@
#include "UI_resources.h"
#include "GPU_glew.h"
-#include "GPU_select.h"
#include "GPU_matrix.h"
+#include "GPU_select.h"
#include "GPU_state.h"
#include "WM_api.h"
@@ -127,13 +128,13 @@ void ED_view3d_smooth_view_ex(
const Depsgraph *depsgraph,
wmWindowManager *wm,
wmWindow *win,
- ScrArea *sa,
+ ScrArea *area,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
const int smooth_viewtx,
const V3D_SmoothParams *sview)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
struct SmoothView3DStore sms = {{0}};
bool ok = false;
@@ -228,7 +229,7 @@ void ED_view3d_smooth_view_ex(
ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
}
/* grid draw as floor */
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
/* use existing if exists, means multiple calls to smooth view
* wont loose the original 'view' setting */
rv3d->view = RV3D_VIEW_USER;
@@ -291,32 +292,32 @@ void ED_view3d_smooth_view_ex(
ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
}
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_copy(sa, ar);
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_copy(area, region);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
void ED_view3d_smooth_view(bContext *C,
View3D *v3d,
- ARegion *ar,
+ ARegion *region,
const int smooth_viewtx,
const struct V3D_SmoothParams *sview)
{
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- ED_view3d_smooth_view_ex(depsgraph, wm, win, sa, v3d, ar, smooth_viewtx, sview);
+ ED_view3d_smooth_view_ex(depsgraph, wm, win, area, v3d, region, smooth_viewtx, sview);
}
/* only meant for timer usage */
-static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool sync_boxview)
+static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, bool sync_boxview)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
struct SmoothView3DStore *sms = rv3d->sms;
float step, step_inv;
@@ -344,7 +345,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
}
- if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
rv3d->view = sms->org_view;
}
@@ -381,11 +382,11 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
}
/* Event handling won't know if a UI item has been moved under the pointer. */
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
}
- if (sync_boxview && (rv3d->viewlock & RV3D_BOXVIEW)) {
- view3d_boxview_copy(CTX_wm_area(C), ar);
+ if (sync_boxview && (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW)) {
+ view3d_boxview_copy(CTX_wm_area(C), region);
}
/* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636,
@@ -397,22 +398,22 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
}
else {
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(region);
}
}
static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
/* escape if not our timer */
if (rv3d->smooth_timer == NULL || rv3d->smooth_timer != event->customdata) {
return OPERATOR_PASS_THROUGH;
}
- view3d_smoothview_apply(C, v3d, ar, true);
+ view3d_smoothview_apply(C, v3d, region, true);
return OPERATOR_FINISHED;
}
@@ -421,19 +422,19 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
* Apply the smoothview immediately, use when we need to start a new view operation.
* (so we don't end up half-applying a view operation when pressing keys quickly).
*/
-void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *ar)
+void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *region)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
if (rv3d && rv3d->sms) {
rv3d->sms->time_allowed = 0.0; /* force finishing */
- view3d_smoothview_apply(C, v3d, ar, false);
+ view3d_smoothview_apply(C, v3d, region, false);
/* force update of view matrix so tools that run immediately after
* can use them without redrawing first */
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL, false);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, region, NULL, NULL, NULL, false);
}
}
@@ -462,13 +463,13 @@ static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
{
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
RegionView3D *rv3d;
ObjectTfmProtectedChannels obtfm;
- ED_view3d_context_user_region(C, &v3d, &ar);
- rv3d = ar->regiondata;
+ ED_view3d_context_user_region(C, &v3d, &region);
+ rv3d = region->regiondata;
ED_view3d_lastview_store(rv3d);
@@ -489,12 +490,12 @@ static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
static bool view3d_camera_to_view_poll(bContext *C)
{
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
- if (ED_view3d_context_user_region(C, &v3d, &ar)) {
- RegionView3D *rv3d = ar->regiondata;
+ if (ED_view3d_context_user_region(C, &v3d, &region)) {
+ RegionView3D *rv3d = region->regiondata;
if (v3d && v3d->camera && !ID_IS_LINKED(v3d->camera)) {
- if (rv3d && (rv3d->viewlock & RV3D_LOCKED) == 0) {
+ if (rv3d && (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
if (rv3d->persp != RV3D_CAMOB) {
return 1;
}
@@ -614,17 +615,18 @@ static void sync_viewport_camera_smoothview(bContext *C,
if (v3d->scenelock) {
ListBase *lb = (space_link == area->spacedata.first) ? &area->regionbase :
&space_link->regionbase;
- for (ARegion *other_ar = lb->first; other_ar != NULL; other_ar = other_ar->next) {
- if (other_ar->regiontype == RGN_TYPE_WINDOW) {
- if (other_ar->regiondata) {
- RegionView3D *other_rv3d = other_ar->regiondata;
+ for (ARegion *other_region = lb->first; other_region != NULL;
+ other_region = other_region->next) {
+ if (other_region->regiontype == RGN_TYPE_WINDOW) {
+ if (other_region->regiondata) {
+ RegionView3D *other_rv3d = other_region->regiondata;
if (other_rv3d->persp == RV3D_CAMOB) {
Object *other_camera_old = other_v3d->camera;
other_v3d->camera = ob;
ED_view3d_lastview_store(other_rv3d);
ED_view3d_smooth_view(C,
other_v3d,
- other_ar,
+ other_region,
smooth_viewtx,
&(const V3D_SmoothParams){
.camera_old = other_camera_old,
@@ -651,7 +653,7 @@ static void sync_viewport_camera_smoothview(bContext *C,
static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
{
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
RegionView3D *rv3d;
Scene *scene = CTX_data_scene(C);
@@ -660,8 +662,8 @@ static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &ar);
- rv3d = ar->regiondata;
+ ED_view3d_context_user_region(C, &v3d, &region);
+ rv3d = region->regiondata;
if (ob) {
Object *camera_old = (rv3d->persp == RV3D_CAMOB) ? V3D_CAMERA_SCENE(scene, v3d) : NULL;
@@ -678,7 +680,7 @@ static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
ED_view3d_smooth_view(C,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.camera_old = camera_old,
@@ -703,9 +705,9 @@ static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
bool ED_operator_rv3d_user_region_poll(bContext *C)
{
View3D *v3d_dummy;
- ARegion *ar_dummy;
+ ARegion *region_dummy;
- return ED_view3d_context_user_region(C, &v3d_dummy, &ar_dummy);
+ return ED_view3d_context_user_region(C, &v3d_dummy, &region_dummy);
}
void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
@@ -732,15 +734,18 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
/**
* \param rect: optional for picking (can be NULL).
*/
-void view3d_winmatrix_set(Depsgraph *depsgraph, ARegion *ar, const View3D *v3d, const rcti *rect)
+void view3d_winmatrix_set(Depsgraph *depsgraph,
+ ARegion *region,
+ const View3D *v3d,
+ const rcti *rect)
{
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
rctf viewplane;
float clipsta, clipend;
bool is_ortho;
is_ortho = ED_view3d_viewplane_get(
- depsgraph, v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL);
+ depsgraph, v3d, rv3d, region->winx, region->winy, &viewplane, &clipsta, &clipend, NULL);
rv3d->is_persp = !is_ortho;
#if 0
@@ -758,10 +763,10 @@ void view3d_winmatrix_set(Depsgraph *depsgraph, ARegion *ar, const View3D *v3d,
if (rect) { /* picking */
rctf r;
- r.xmin = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmin / (float)ar->winx));
- r.ymin = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymin / (float)ar->winy));
- r.xmax = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmax / (float)ar->winx));
- r.ymax = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymax / (float)ar->winy));
+ r.xmin = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmin / (float)region->winx));
+ r.ymin = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymin / (float)region->winy));
+ r.xmax = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmax / (float)region->winx));
+ r.ymax = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymax / (float)region->winy));
viewplane = r;
}
@@ -804,7 +809,7 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
* \note don't set windows active in here, is used by renderwin too.
*/
void view3d_viewmatrix_set(Depsgraph *depsgraph,
- Scene *scene,
+ const Scene *scene,
const View3D *v3d,
RegionView3D *rv3d,
const float rect_scale[2])
@@ -823,7 +828,7 @@ void view3d_viewmatrix_set(Depsgraph *depsgraph,
bool use_lock_ofs = false;
/* should be moved to better initialize later on XXX */
- if (rv3d->viewlock & RV3D_LOCKED) {
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) {
ED_view3d_lock(rv3d);
}
@@ -831,13 +836,13 @@ void view3d_viewmatrix_set(Depsgraph *depsgraph,
if (rv3d->persp == RV3D_PERSP) {
rv3d->viewmat[3][2] -= rv3d->dist;
}
- if (v3d->ob_centre) {
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, v3d->ob_centre);
+ if (v3d->ob_center) {
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, v3d->ob_center);
float vec[3];
copy_v3_v3(vec, ob_eval->obmat[3]);
- if (ob_eval->type == OB_ARMATURE && v3d->ob_centre_bone[0]) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, v3d->ob_centre_bone);
+ if (ob_eval->type == OB_ARMATURE && v3d->ob_center_bone[0]) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, v3d->ob_center_bone);
if (pchan) {
copy_v3_v3(vec, pchan->pose_mat[3]);
mul_m4_v3(ob_eval->obmat, vec);
@@ -846,7 +851,7 @@ void view3d_viewmatrix_set(Depsgraph *depsgraph,
translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
use_lock_ofs = true;
}
- else if (v3d->ob_centre_cursor) {
+ else if (v3d->ob_center_cursor) {
float vec[3];
copy_v3_v3(vec, scene->cursor.location);
translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
@@ -988,10 +993,11 @@ int view3d_opengl_select(ViewContext *vc,
eV3DSelectObjectFilter select_filter)
{
struct bThemeState theme_state;
+ const wmWindowManager *wm = CTX_wm_manager(vc->C);
Depsgraph *depsgraph = vc->depsgraph;
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
- ARegion *ar = vc->ar;
+ ARegion *region = vc->region;
rcti rect;
int hits = 0;
const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) &&
@@ -1056,7 +1062,7 @@ int view3d_opengl_select(ViewContext *vc,
* 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);
+ const ModifierData *md = BKE_modifiers_get_virtual_modifierlist(obact, &virtualModifierData);
for (; md; md = md->next) {
if (md->type == eModifierType_Armature) {
ArmatureModifierData *amd = (ArmatureModifierData *)md;
@@ -1093,7 +1099,8 @@ int view3d_opengl_select(ViewContext *vc,
/* Important we use the 'viewmat' and don't re-calculate since
* the object & bone view locking takes 'rect' into account, see: T51629. */
- ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
+ ED_view3d_draw_setup_view(
+ wm, vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, NULL, &rect);
if (!XRAY_ACTIVE(v3d)) {
GPU_depth_test(true);
@@ -1117,7 +1124,7 @@ int view3d_opengl_select(ViewContext *vc,
};
draw_surface = false;
DRW_draw_select_loop(depsgraph,
- ar,
+ region,
v3d,
use_obedit_skip,
draw_surface,
@@ -1147,7 +1154,7 @@ int view3d_opengl_select(ViewContext *vc,
/* If are not in wireframe mode, we need to use the mesh surfaces to check for hits */
draw_surface = (v3d->shading.type > OB_WIRE) || !XRAY_ENABLED(v3d);
DRW_draw_select_loop(depsgraph,
- ar,
+ region,
v3d,
use_obedit_skip,
draw_surface,
@@ -1161,7 +1168,8 @@ int view3d_opengl_select(ViewContext *vc,
}
G.f &= ~G_FLAG_PICKSEL;
- ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
+ ED_view3d_draw_setup_view(
+ wm, vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, NULL, NULL);
if (!XRAY_ACTIVE(v3d)) {
GPU_depth_test(false);
@@ -1192,16 +1200,16 @@ finally:
static uint free_localview_bit(Main *bmain)
{
- ScrArea *sa;
- bScreen *sc;
+ ScrArea *area;
+ bScreen *screen;
ushort local_view_bits = 0;
/* sometimes we loose a localview: when an area is closed */
/* check all areas: which localviews are in use? */
- for (sc = bmain->screens.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl = sa->spacedata.first;
+ for (screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ SpaceLink *sl = area->spacedata.first;
for (; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
@@ -1227,12 +1235,12 @@ static bool view3d_localview_init(const Depsgraph *depsgraph,
wmWindow *win,
Main *bmain,
ViewLayer *view_layer,
- ScrArea *sa,
+ ScrArea *area,
const bool frame_selected,
const int smooth_viewtx,
ReportList *reports)
{
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
Base *base;
float min[3], max[3], box[3];
float size = 0.0f;
@@ -1287,16 +1295,16 @@ static bool view3d_localview_init(const Depsgraph *depsgraph,
return false;
}
- ARegion *ar;
+ ARegion *region;
v3d->localvd = MEM_mallocN(sizeof(View3D), "localview");
memcpy(v3d->localvd, v3d, sizeof(View3D));
v3d->local_view_uuid = local_view_bit;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
bool ok_dist = true;
/* New view values. */
@@ -1324,7 +1332,7 @@ static bool view3d_localview_init(const Depsgraph *depsgraph,
if (ok_dist) {
dist_new = ED_view3d_radius_to_dist(
- v3d, ar, depsgraph, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
+ v3d, region, depsgraph, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
if (rv3d->persp == RV3D_PERSP) {
/* Don't zoom closer than the near clipping plane. */
@@ -1335,9 +1343,9 @@ static bool view3d_localview_init(const Depsgraph *depsgraph,
ED_view3d_smooth_view_ex(depsgraph,
wm,
win,
- sa,
+ area,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.camera_old = camera_old,
@@ -1357,11 +1365,11 @@ static void view3d_localview_exit(const Depsgraph *depsgraph,
wmWindowManager *wm,
wmWindow *win,
ViewLayer *view_layer,
- ScrArea *sa,
+ ScrArea *area,
const bool frame_selected,
const int smooth_viewtx)
{
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
if (v3d->localvd == NULL) {
return;
@@ -1382,9 +1390,9 @@ static void view3d_localview_exit(const Depsgraph *depsgraph,
MEM_freeN(v3d->localvd);
v3d->localvd = NULL;
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
if (rv3d->localvd == NULL) {
continue;
@@ -1403,9 +1411,9 @@ static void view3d_localview_exit(const Depsgraph *depsgraph,
ED_view3d_smooth_view_ex(depsgraph,
wm,
win,
- sa,
+ area,
v3d,
- ar,
+ region,
smooth_viewtx,
&(const V3D_SmoothParams){
.camera_old = camera_old_rv3d,
@@ -1431,23 +1439,23 @@ static int localview_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
View3D *v3d = CTX_wm_view3d(C);
bool frame_selected = RNA_boolean_get(op->ptr, "frame_selected");
bool changed;
if (v3d->localvd) {
- view3d_localview_exit(depsgraph, wm, win, view_layer, sa, frame_selected, smooth_viewtx);
+ view3d_localview_exit(depsgraph, wm, win, view_layer, area, frame_selected, smooth_viewtx);
changed = true;
}
else {
changed = view3d_localview_init(
- depsgraph, wm, win, bmain, view_layer, sa, frame_selected, smooth_viewtx, op->reports);
+ depsgraph, wm, win, bmain, view_layer, area, frame_selected, smooth_viewtx, op->reports);
}
if (changed) {
DEG_id_type_tag(bmain, ID_OB);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
/* Unselected objects become selected when exiting. */
if (v3d->localvd == NULL) {
@@ -1548,19 +1556,17 @@ void VIEW3D_OT_localview_remove_from(wmOperatorType *ot)
/** \name Local Collections
* \{ */
-static uint free_localcollection_bit(Main *bmain,
- unsigned short local_collections_uuid,
- bool *reset)
+static uint free_localcollection_bit(Main *bmain, ushort local_collections_uuid, bool *r_reset)
{
- ScrArea *sa;
- bScreen *sc;
+ ScrArea *area;
+ bScreen *screen;
ushort local_view_bits = 0;
/* Check all areas: which localviews are in use? */
- for (sc = bmain->screens.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl = sa->spacedata.first;
+ for (screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ SpaceLink *sl = area->spacedata.first;
for (; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
@@ -1580,7 +1586,7 @@ static uint free_localcollection_bit(Main *bmain,
/* Otherwise get the first free available. */
for (int i = 0; i < 16; i++) {
if ((local_view_bits & (1 << i)) == 0) {
- *reset = true;
+ *r_reset = true;
return (1 << i);
}
}
@@ -1589,7 +1595,7 @@ static uint free_localcollection_bit(Main *bmain,
}
static void local_collections_reset_uuid(LayerCollection *layer_collection,
- const unsigned short local_view_bit)
+ const ushort local_view_bit)
{
if (layer_collection->flag & LAYER_COLLECTION_HIDE) {
layer_collection->local_collections_bits &= ~local_view_bit;
@@ -1680,3 +1686,83 @@ void ED_view3d_local_collections_reset(struct bContext *C, const bool reset_all)
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name XR Functionality
+ * \{ */
+
+#ifdef WITH_XR_OPENXR
+
+static void view3d_xr_mirror_begin(RegionView3D *rv3d)
+{
+ /* If there is no session yet, changes below should not be applied! */
+ BLI_assert(WM_xr_session_exists(&((wmWindowManager *)G_MAIN->wm.first)->xr));
+
+ rv3d->runtime_viewlock |= RV3D_LOCK_ANY_TRANSFORM;
+ /* Force perspective view. This isn't reset but that's not really an issue. */
+ rv3d->persp = RV3D_PERSP;
+}
+
+static void view3d_xr_mirror_end(RegionView3D *rv3d)
+{
+ rv3d->runtime_viewlock &= ~RV3D_LOCK_ANY_TRANSFORM;
+}
+
+void ED_view3d_xr_mirror_update(const ScrArea *area, const View3D *v3d, const bool enable)
+{
+ ARegion *region_rv3d;
+
+ BLI_assert(v3d->spacetype == SPACE_VIEW3D);
+
+ if (ED_view3d_area_user_region(area, v3d, &region_rv3d)) {
+ if (enable) {
+ view3d_xr_mirror_begin(region_rv3d->regiondata);
+ }
+ else {
+ view3d_xr_mirror_end(region_rv3d->regiondata);
+ }
+ }
+}
+
+void ED_view3d_xr_shading_update(wmWindowManager *wm, const View3D *v3d, const Scene *scene)
+{
+ if (v3d->runtime.flag & V3D_RUNTIME_XR_SESSION_ROOT) {
+ View3DShading *xr_shading = &wm->xr.session_settings.shading;
+
+ BLI_assert(WM_xr_session_exists(&wm->xr));
+
+ if (v3d->shading.type == OB_RENDER) {
+ if (!(BKE_scene_uses_blender_workbench(scene) || BKE_scene_uses_blender_eevee(scene))) {
+ /* Keep old shading while using Cycles or another engine, they are typically not usable in
+ * VR. */
+ return;
+ }
+ }
+
+ if (xr_shading->prop) {
+ IDP_FreeProperty(xr_shading->prop);
+ xr_shading->prop = NULL;
+ }
+
+ /* Copy shading from View3D to VR view. */
+ *xr_shading = v3d->shading;
+ if (v3d->shading.prop) {
+ xr_shading->prop = IDP_CopyProperty(xr_shading->prop);
+ }
+ }
+}
+
+bool ED_view3d_is_region_xr_mirror_active(const wmWindowManager *wm,
+ const View3D *v3d,
+ const ARegion *region)
+{
+ return (v3d->flag & V3D_XR_SESSION_MIRROR) &&
+ /* The free region (e.g. the camera region in quad-view) is always the last in the list
+ base. We don't want any other to be affected. */
+ !region->next && //
+ WM_xr_session_is_ready(&wm->xr);
+}
+
+#endif
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 34470896fb9..8ee52756f27 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -20,14 +20,14 @@
/* defines VIEW3D_OT_navigate - walk modal operator */
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_kdopbvh.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -160,14 +160,14 @@ void walk_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Walk Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Walk Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Walk Modal", modal_items);
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk");
@@ -187,7 +187,7 @@ typedef struct WalkInfo {
/* context stuff */
RegionView3D *rv3d;
View3D *v3d;
- ARegion *ar;
+ ARegion *region;
struct Depsgraph *depsgraph;
Scene *scene;
@@ -290,7 +290,7 @@ static void walkApply_ndof(bContext *C, WalkInfo *walk, bool is_confirm);
static int walkApply(bContext *C, struct WalkInfo *walk, bool force_autokey);
static float getVelocityZeroTime(const float gravity, const float velocity);
-static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *arg)
+static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *region, void *arg)
{
/* draws an aim/cross in the center */
WalkInfo *walk = arg;
@@ -302,13 +302,13 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a
if (ED_view3d_cameracontrol_object_get(walk->v3d_camera_control)) {
ED_view3d_calc_camera_border(
- walk->scene, walk->depsgraph, ar, walk->v3d, walk->rv3d, &viewborder, false);
+ walk->scene, walk->depsgraph, region, walk->v3d, walk->rv3d, &viewborder, false);
xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f;
yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f;
}
else {
- xoff = walk->ar->winx / 2;
- yoff = walk->ar->winy / 2;
+ xoff = walk->region->winx / 2;
+ yoff = walk->region->winy / 2;
}
GPUVertFormat *format = immVertexFormat();
@@ -316,7 +316,7 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor3(TH_VIEW_OVERLAY);
immBegin(GPU_PRIM_LINES, 8);
@@ -375,6 +375,7 @@ static bool walk_floor_distance_get(RegionView3D *rv3d,
add_v3_v3(ray_start, dvec_tmp);
ret = ED_transform_snap_object_project_ray(walk->snap_context,
+ walk->depsgraph,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
},
@@ -413,6 +414,7 @@ static bool walk_ray_cast(RegionView3D *rv3d,
normalize_v3(ray_normal);
ret = ED_transform_snap_object_project_ray(walk->snap_context,
+ walk->depsgraph,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
},
@@ -452,7 +454,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d = CTX_wm_region_view3d(C);
walk->v3d = CTX_wm_view3d(C);
- walk->ar = CTX_wm_region(C);
+ walk->region = CTX_wm_region(C);
walk->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
walk->scene = CTX_data_scene(C);
@@ -546,12 +548,12 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->time_lastdraw = PIL_check_seconds_timer();
walk->draw_handle_pixel = ED_region_draw_cb_activate(
- walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL);
+ walk->region->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL);
walk->rv3d->rflag |= RV3D_NAVIGATING;
walk->snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, walk->scene, CTX_data_ensure_evaluated_depsgraph(C), 0, walk->ar, walk->v3d);
+ bmain, walk->scene, 0, walk->region, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
walk->depsgraph,
@@ -561,24 +563,24 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
/* center the mouse */
- walk->center_mval[0] = walk->ar->winx * 0.5f;
- walk->center_mval[1] = walk->ar->winy * 0.5f;
+ walk->center_mval[0] = walk->region->winx * 0.5f;
+ walk->center_mval[1] = walk->region->winy * 0.5f;
#ifdef USE_PIXELSIZE_NATIVE_SUPPORT
- walk->center_mval[0] += walk->ar->winrct.xmin;
- walk->center_mval[1] += walk->ar->winrct.ymin;
+ walk->center_mval[0] += walk->region->winrct.xmin;
+ walk->center_mval[1] += walk->region->winrct.ymin;
WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]);
- walk->center_mval[0] -= walk->ar->winrct.xmin;
- walk->center_mval[1] -= walk->ar->winrct.ymin;
+ walk->center_mval[0] -= walk->region->winrct.xmin;
+ walk->center_mval[1] -= walk->region->winrct.ymin;
#endif
copy_v2_v2_int(walk->prev_mval, walk->center_mval);
WM_cursor_warp(win,
- walk->ar->winrct.xmin + walk->center_mval[0],
- walk->ar->winrct.ymin + walk->center_mval[1]);
+ walk->region->winrct.xmin + walk->center_mval[0],
+ walk->region->winrct.ymin + walk->center_mval[1]);
/* remove the mouse cursor temporarily */
WM_cursor_modal_set(win, WM_CURSOR_NONE);
@@ -616,7 +618,7 @@ static int walkEnd(bContext *C, WalkInfo *walk)
WM_event_remove_timer(CTX_wm_manager(C), win, walk->timer);
- ED_region_draw_cb_exit(walk->ar->type, walk->draw_handle_pixel);
+ ED_region_draw_cb_exit(walk->region->type, walk->draw_handle_pixel);
ED_transform_snap_object_context_destroy(walk->snap_context);
@@ -639,8 +641,8 @@ static int walkEnd(bContext *C, WalkInfo *walk)
{
/* center the mouse */
WM_cursor_warp(win,
- walk->ar->winrct.xmin + walk->center_mval[0],
- walk->ar->winrct.ymin + walk->center_mval[1]);
+ walk->region->winrct.xmin + walk->center_mval[0],
+ walk->region->winrct.ymin + walk->center_mval[1]);
}
if (walk->state == WALK_CONFIRM) {
@@ -670,8 +672,8 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event)
* ideally we shouldn't have to worry about this, see: T45361 */
wmWindow *win = CTX_wm_window(C);
WM_cursor_warp(win,
- walk->ar->winrct.xmin + walk->center_mval[0],
- walk->ar->winrct.ymin + walk->center_mval[1]);
+ walk->region->winrct.xmin + walk->center_mval[0],
+ walk->region->winrct.ymin + walk->center_mval[1]);
}
return;
}
@@ -708,8 +710,8 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event)
#endif
{
WM_cursor_warp(win,
- walk->ar->winrct.xmin + walk->center_mval[0],
- walk->ar->winrct.ymin + walk->center_mval[1]);
+ walk->region->winrct.xmin + walk->center_mval[0],
+ walk->region->winrct.ymin + walk->center_mval[1]);
copy_v2_v2_int(walk->prev_mval, walk->center_mval);
}
}
@@ -964,7 +966,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
* a walk loop where the user can move move the view as if they are in a walk game
*/
RegionView3D *rv3d = walk->rv3d;
- ARegion *ar = walk->ar;
+ ARegion *region = walk->region;
/* 3x3 copy of the view matrix so we can move along the view axis */
float mat[3][3];
@@ -1032,7 +1034,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
float y;
/* relative offset */
- y = (float)moffset[1] / ar->winy;
+ y = (float)moffset[1] / region->winy;
/* speed factor */
y *= WALK_ROTATE_FAC;
@@ -1072,7 +1074,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
}
/* relative offset */
- x = (float)moffset[0] / ar->winx;
+ x = (float)moffset[0] / region->winx;
/* speed factor */
x *= WALK_ROTATE_FAC;
@@ -1345,7 +1347,7 @@ static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
WalkInfo *walk;
- if (rv3d->viewlock & RV3D_LOCKED) {
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index 6f39a8c3b9c..afa7b02a1f6 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -65,14 +65,47 @@ set(SRC
transform_gizmo_3d.c
transform_gizmo_extrude_3d.c
transform_input.c
+ transform_mode.c
+ transform_mode_align.c
+ transform_mode_baketime.c
+ transform_mode_bbone_resize.c
+ transform_mode_bend.c
+ transform_mode_boneenvelope.c
+ transform_mode_boneroll.c
+ transform_mode_curveshrinkfatten.c
+ transform_mode_edge_bevelweight.c
+ transform_mode_edge_crease.c
+ transform_mode_edge_rotate_normal.c
+ transform_mode_edge_seq_slide.c
+ transform_mode_edge_slide.c
+ transform_mode_gpopacity.c
+ transform_mode_gpshrinkfatten.c
+ transform_mode_maskshrinkfatten.c
+ transform_mode_mirror.c
+ transform_mode_push_pull.c
+ transform_mode_resize.c
+ transform_mode_rotate.c
+ transform_mode_shear.c
+ transform_mode_shrink_fatten.c
+ transform_mode_skin_resize.c
+ transform_mode_tilt.c
+ transform_mode_timescale.c
+ transform_mode_timeslide.c
+ transform_mode_timetranslate.c
+ transform_mode_tosphere.c
+ transform_mode_trackball.c
+ transform_mode_translate.c
+ transform_mode_vert_slide.c
transform_ops.c
transform_orientations.c
transform_snap.c
transform_snap_object.c
transform.h
+ transform_constraints.h
transform_convert.h
transform_draw_cursors.h
+ transform_mode.h
transform_snap.h
)
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index ec39b457082..8e3ad55bae1 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -22,220 +22,70 @@
*/
#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <float.h>
#include "MEM_guardedalloc.h"
-#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_constraint_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_mask_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_scene_types.h" /* PET modes */
-#include "DNA_workspace_types.h"
-#include "DNA_gpencil_types.h"
-#include "BLI_alloca.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_listbase.h"
-#include "BLI_string.h"
-#include "BLI_ghash.h"
-#include "BLI_utildefines_stack.h"
-#include "BLI_memarena.h"
-#include "BKE_nla.h"
-#include "BKE_editmesh.h"
-#include "BKE_editmesh_bvh.h"
#include "BKE_context.h"
-#include "BKE_constraint.h"
-#include "BKE_particle.h"
-#include "BKE_unit.h"
-#include "BKE_scene.h"
+#include "BKE_editmesh.h"
#include "BKE_mask.h"
-#include "BKE_mesh.h"
-#include "BKE_report.h"
-#include "BKE_workspace.h"
-
-#include "DEG_depsgraph.h"
+#include "BKE_scene.h"
-#include "GPU_immediate.h"
-#include "GPU_matrix.h"
#include "GPU_state.h"
+#include "ED_clip.h"
+#include "ED_gpencil.h"
#include "ED_image.h"
#include "ED_keyframing.h"
-#include "ED_screen.h"
-#include "ED_space_api.h"
-#include "ED_view3d.h"
-#include "ED_mesh.h"
-#include "ED_clip.h"
#include "ED_node.h"
-#include "ED_gpencil.h"
+#include "ED_screen.h"
#include "ED_sculpt.h"
+#include "ED_space_api.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
-#include "UI_view2d.h"
-#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "RNA_access.h"
-#include "RNA_define.h"
#include "BLF_api.h"
#include "BLT_translation.h"
#include "transform.h"
+#include "transform_constraints.h"
#include "transform_convert.h"
#include "transform_draw_cursors.h"
+#include "transform_mode.h"
#include "transform_snap.h"
/* Disabling, since when you type you know what you are doing,
* and being able to set it to zero is handy. */
// #define USE_NUM_NO_ZERO
-static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg);
-static void doEdgeSlide(TransInfo *t, float perc);
-static void doVertSlide(TransInfo *t, float perc);
-
-static void drawEdgeSlide(TransInfo *t);
-static void drawVertSlide(TransInfo *t);
-static void postInputRotation(TransInfo *t, float values[3]);
+static void drawTransformApply(const struct bContext *C, ARegion *region, void *arg);
-static void ElementRotation(
- TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around);
static void initSnapSpatial(TransInfo *t, float r_snap[3]);
-static void storeCustomLNorValue(TransDataContainer *t, BMesh *bm);
-
-/* Transform Callbacks */
-static void initBend(TransInfo *t);
-static eRedrawFlag handleEventBend(TransInfo *t, const struct wmEvent *event);
-static void Bend(TransInfo *t, const int mval[2]);
-
-static void initShear(TransInfo *t);
-static eRedrawFlag handleEventShear(TransInfo *t, const struct wmEvent *event);
-static void applyShear(TransInfo *t, const int mval[2]);
-
-static void initResize(TransInfo *t);
-static void applyResize(TransInfo *t, const int mval[2]);
-
-static void initSkinResize(TransInfo *t);
-static void applySkinResize(TransInfo *t, const int mval[2]);
-
-static void initTranslation(TransInfo *t);
-static void applyTranslation(TransInfo *t, const int mval[2]);
-
-static void initToSphere(TransInfo *t);
-static void applyToSphere(TransInfo *t, const int mval[2]);
-
-static void initRotation(TransInfo *t);
-static void applyRotation(TransInfo *t, const int mval[2]);
-
-static void initNormalRotation(TransInfo *t);
-static void applyNormalRotation(TransInfo *t, const int mval[2]);
-
-static void initShrinkFatten(TransInfo *t);
-static void applyShrinkFatten(TransInfo *t, const int mval[2]);
-
-static void initTilt(TransInfo *t);
-static void applyTilt(TransInfo *t, const int mval[2]);
-
-static void initCurveShrinkFatten(TransInfo *t);
-static void applyCurveShrinkFatten(TransInfo *t, const int mval[2]);
-
-static void initMaskShrinkFatten(TransInfo *t);
-static void applyMaskShrinkFatten(TransInfo *t, const int mval[2]);
-
-static void initGPShrinkFatten(TransInfo *t);
-static void applyGPShrinkFatten(TransInfo *t, const int mval[2]);
-
-static void initTrackball(TransInfo *t);
-static void applyTrackball(TransInfo *t, const int mval[2]);
-
-static void initPushPull(TransInfo *t);
-static void applyPushPull(TransInfo *t, const int mval[2]);
-
-static void initBevelWeight(TransInfo *t);
-static void applyBevelWeight(TransInfo *t, const int mval[2]);
-
-static void initCrease(TransInfo *t);
-static void applyCrease(TransInfo *t, const int mval[2]);
-
-static void initBoneSize(TransInfo *t);
-static void applyBoneSize(TransInfo *t, const int mval[2]);
-
-static void initBoneEnvelope(TransInfo *t);
-static void applyBoneEnvelope(TransInfo *t, const int mval[2]);
-
-static void initBoneRoll(TransInfo *t);
-static void applyBoneRoll(TransInfo *t, const int mval[2]);
-
-static void initEdgeSlide_ex(
- TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp);
-static void initEdgeSlide(TransInfo *t);
-static eRedrawFlag handleEventEdgeSlide(TransInfo *t, const struct wmEvent *event);
-static void applyEdgeSlide(TransInfo *t, const int mval[2]);
-
-static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp);
-static void initVertSlide(TransInfo *t);
-static eRedrawFlag handleEventVertSlide(TransInfo *t, const struct wmEvent *event);
-static void applyVertSlide(TransInfo *t, const int mval[2]);
-
-static void initTimeTranslate(TransInfo *t);
-static void applyTimeTranslate(TransInfo *t, const int mval[2]);
-
-static void initTimeSlide(TransInfo *t);
-static void applyTimeSlide(TransInfo *t, const int mval[2]);
-
-static void initTimeScale(TransInfo *t);
-static void applyTimeScale(TransInfo *t, const int mval[2]);
-
-static void initBakeTime(TransInfo *t);
-static void applyBakeTime(TransInfo *t, const int mval[2]);
-
-static void initMirror(TransInfo *t);
-static void applyMirror(TransInfo *t, const int mval[2]);
-
-static void initAlign(TransInfo *t);
-static void applyAlign(TransInfo *t, const int mval[2]);
-
-static void initSeqSlide(TransInfo *t);
-static void applySeqSlide(TransInfo *t, const int mval[2]);
-
-static void initGPOpacity(TransInfo *t);
-static void applyGPOpacity(TransInfo *t, const int mval[2]);
-/* end transform callbacks */
-
-static bool transdata_check_local_center(TransInfo *t, short around)
-{
- return ((around == V3D_AROUND_LOCAL_ORIGINS) &&
- ((t->flag & (T_OBJECT | T_POSE)) ||
- /* implicit: (t->flag & T_EDIT) */
- (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) ||
- (t->spacetype == SPACE_GRAPH) ||
- (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE))));
-}
-
bool transdata_check_local_islands(TransInfo *t, short around)
{
- return ((around == V3D_AROUND_LOCAL_ORIGINS) && ((ELEM(t->obedit_type, OB_MESH))));
+ return ((around == V3D_AROUND_LOCAL_ORIGINS) && ((ELEM(t->obedit_type, OB_MESH, OB_GPENCIL))));
}
/* ************************** SPACE DEPENDENT CODE **************************** */
void setTransformViewMatrices(TransInfo *t)
{
- if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = t->ar->regiondata;
+ if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = t->region->regiondata;
copy_m4_m4(t->viewmat, rv3d->viewmat);
copy_m4_m4(t->viewinv, rv3d->viewinv);
@@ -260,7 +110,7 @@ void setTransformViewAspect(TransInfo *t, float r_aspect[3])
copy_v3_fl(r_aspect, 1.0f);
if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = t->sa->spacedata.first;
+ SpaceImage *sima = t->area->spacedata.first;
if (t->options & CTX_MASK) {
ED_space_image_get_aspect(sima, &r_aspect[0], &r_aspect[1]);
@@ -273,7 +123,7 @@ void setTransformViewAspect(TransInfo *t, float r_aspect[3])
}
}
else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = t->sa->spacedata.first;
+ SpaceClip *sclip = t->area->spacedata.first;
if (t->options & CTX_MOVIECLIP) {
ED_space_clip_get_aspect_dimension_aware(sclip, &r_aspect[0], &r_aspect[1]);
@@ -324,14 +174,14 @@ static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy)
{
- if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
+ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
if (t->options & CTX_PAINT_CURVE) {
r_vec[0] = dx;
r_vec[1] = dy;
}
else {
const float mval_f[2] = {(float)dx, (float)dy};
- ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
+ ED_view3d_win_to_delta(t->region, mval_f, r_vec, t->zfac);
}
}
else if (t->spacetype == SPACE_IMAGE) {
@@ -353,7 +203,7 @@ void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy)
convertViewVec2D(t->view, r_vec, dx, dy);
}
else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
- convertViewVec2D(&t->ar->v2d, r_vec, dx, dy);
+ convertViewVec2D(&t->region->v2d, r_vec, dx, dy);
}
else if (t->spacetype == SPACE_CLIP) {
if (t->options & CTX_MASK) {
@@ -375,8 +225,8 @@ void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy)
void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag)
{
if (t->spacetype == SPACE_VIEW3D) {
- if (t->ar->regiontype == RGN_TYPE_WINDOW) {
- if (ED_view3d_project_int_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
+ if (t->region->regiontype == RGN_TYPE_WINDOW) {
+ if (ED_view3d_project_int_global(t->region, vec, adr, flag) != V3D_PROJ_RET_OK) {
/* this is what was done in 2.64, perhaps we can be smarter? */
adr[0] = (int)2140000000.0f;
adr[1] = (int)2140000000.0f;
@@ -384,7 +234,7 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
}
}
else if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = t->sa->spacedata.first;
+ SpaceImage *sima = t->area->spacedata.first;
if (t->options & CTX_MASK) {
float v[2];
@@ -394,7 +244,7 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v);
- ED_image_point_pos__reverse(sima, t->ar, v, v);
+ ED_image_point_pos__reverse(sima, t->region, v, v);
adr[0] = v[0];
adr[1] = v[1];
@@ -415,7 +265,7 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
else if (t->spacetype == SPACE_ACTION) {
int out[2] = {0, 0};
#if 0
- SpaceAction *sact = t->sa->spacedata.first;
+ SpaceAction *sact = t->area->spacedata.first;
if (sact->flag & SACTION_DRAWTIME) {
//vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base));
@@ -446,7 +296,7 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
adr[1] = out[1];
}
else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
+ SpaceClip *sc = t->area->spacedata.first;
if (t->options & CTX_MASK) {
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -459,7 +309,7 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
BKE_mask_coord_to_movieclip(sc->clip, &sc->user, v, v);
- ED_clip_point_stable_pos__reverse(sc, t->ar, v, v);
+ ED_clip_point_stable_pos__reverse(sc, t->region, v, v);
adr[0] = v[0];
adr[1] = v[1];
@@ -498,12 +348,12 @@ void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV
adr[0] = vec[0];
adr[1] = vec[1];
}
- else if (t->ar->regiontype == RGN_TYPE_WINDOW) {
+ else if (t->region->regiontype == RGN_TYPE_WINDOW) {
/* allow points behind the view [#33643] */
- if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_global(t->region, vec, adr, flag) != V3D_PROJ_RET_OK) {
/* XXX, 2.64 and prior did this, weak! */
- adr[0] = t->ar->winx / 2.0f;
- adr[1] = t->ar->winy / 2.0f;
+ adr[0] = t->region->winx / 2.0f;
+ adr[1] = t->region->winy / 2.0f;
}
return;
}
@@ -527,7 +377,7 @@ void applyAspectRatio(TransInfo *t, float vec[2])
{
if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) &&
!(t->options & CTX_PAINT_CURVE)) {
- SpaceImage *sima = t->sa->spacedata.first;
+ SpaceImage *sima = t->area->spacedata.first;
if ((sima->flag & SI_COORDFLOATS) == 0) {
int width, height;
@@ -551,7 +401,7 @@ void applyAspectRatio(TransInfo *t, float vec[2])
void removeAspectRatio(TransInfo *t, float vec[2])
{
if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
- SpaceImage *sima = t->sa->spacedata.first;
+ SpaceImage *sima = t->area->spacedata.first;
if ((sima->flag & SI_COORDFLOATS) == 0) {
int width, height;
@@ -584,7 +434,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
else if (t->spacetype == SPACE_VIEW3D) {
if (t->options & CTX_PAINT_CURVE) {
wmWindow *window = CTX_wm_window(C);
- WM_paint_cursor_tag_redraw(window, t->ar);
+ WM_paint_cursor_tag_redraw(window, t->region);
}
else {
/* Do we need more refined tags? */
@@ -603,18 +453,18 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
}
}
else if (t->spacetype == SPACE_ACTION) {
- // SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+ // SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
else if (t->spacetype == SPACE_GRAPH) {
- // SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ // SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
else if (t->spacetype == SPACE_NLA) {
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
}
else if (t->spacetype == SPACE_NODE) {
- // ED_area_tag_redraw(t->sa);
+ // ED_area_tag_redraw(t->area);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
}
else if (t->spacetype == SPACE_SEQ) {
@@ -630,24 +480,24 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
}
else if (t->options & CTX_PAINT_CURVE) {
wmWindow *window = CTX_wm_window(C);
- WM_paint_cursor_tag_redraw(window, t->ar);
+ WM_paint_cursor_tag_redraw(window, t->region);
}
else if (t->flag & T_CURSOR) {
- ED_area_tag_redraw(t->sa);
+ ED_area_tag_redraw(t->area);
}
else {
// XXX how to deal with lock?
- SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
+ SpaceImage *sima = (SpaceImage *)t->area->spacedata.first;
if (sima->lock) {
WM_event_add_notifier(C, NC_GEOM | ND_DATA, OBEDIT_FROM_VIEW_LAYER(t->view_layer)->data);
}
else {
- ED_area_tag_redraw(t->sa);
+ ED_area_tag_redraw(t->area);
}
}
}
else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = (SpaceClip *)t->sa->spacedata.first;
+ SpaceClip *sc = (SpaceClip *)t->area->spacedata.first;
if (ED_space_clip_check_show_trackedit(sc)) {
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -667,7 +517,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
static void viewRedrawPost(bContext *C, TransInfo *t)
{
- ED_area_status_text(t->sa, NULL);
+ ED_area_status_text(t->area, NULL);
if (t->spacetype == SPACE_VIEW3D) {
/* if autokeying is enabled, send notifiers that keyframes were added */
@@ -709,7 +559,7 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
/* ************************** TRANSFORMATIONS **************************** */
-static void view_editmove(unsigned short UNUSED(event))
+static void view_editmove(ushort UNUSED(event))
{
#if 0 // TRANSFORM_FIX_ME
int refresh = 0;
@@ -797,42 +647,6 @@ static void view_editmove(unsigned short UNUSED(event))
/* ************************************************* */
-/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
-enum {
- TFM_MODAL_CANCEL = 1,
- TFM_MODAL_CONFIRM = 2,
- TFM_MODAL_TRANSLATE = 3,
- TFM_MODAL_ROTATE = 4,
- TFM_MODAL_RESIZE = 5,
- TFM_MODAL_SNAP_INV_ON = 6,
- TFM_MODAL_SNAP_INV_OFF = 7,
- TFM_MODAL_SNAP_TOGGLE = 8,
- TFM_MODAL_AXIS_X = 9,
- TFM_MODAL_AXIS_Y = 10,
- TFM_MODAL_AXIS_Z = 11,
- TFM_MODAL_PLANE_X = 12,
- TFM_MODAL_PLANE_Y = 13,
- TFM_MODAL_PLANE_Z = 14,
- TFM_MODAL_CONS_OFF = 15,
- TFM_MODAL_ADD_SNAP = 16,
- TFM_MODAL_REMOVE_SNAP = 17,
-
- /* 18 and 19 used by numinput, defined in transform.h */
-
- TFM_MODAL_PROPSIZE_UP = 20,
- TFM_MODAL_PROPSIZE_DOWN = 21,
- TFM_MODAL_AUTOIK_LEN_INC = 22,
- TFM_MODAL_AUTOIK_LEN_DEC = 23,
-
- TFM_MODAL_EDGESLIDE_UP = 24,
- TFM_MODAL_EDGESLIDE_DOWN = 25,
-
- /* for analog input, like trackpad */
- TFM_MODAL_PROPSIZE = 26,
- /* node editor insert offset (aka auto-offset) direction toggle */
- TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27,
-};
-
static bool transform_modal_item_poll(const wmOperator *op, int value)
{
const TransInfo *t = op->customdata;
@@ -956,17 +770,18 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Transform Modal Map");
- keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "Transform Modal Map", modal_items);
keymap->poll_modal_item = transform_modal_item_poll;
return keymap;
}
-static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cmode, bool is_plane)
+static void transform_event_xyz_constraint(TransInfo *t, short key_type, bool is_plane)
{
if (!(t->flag & T_NO_CONSTRAINT)) {
+ char cmode = constraintModeToChar(t);
int constraint_axis, constraint_plane;
const bool edit_2d = (t->flag & T_2D_EDIT) != 0;
const char *msg1 = "", *msg2 = "", *msg3 = "";
@@ -974,21 +789,21 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
/* Initialize */
switch (key_type) {
- case XKEY:
+ case EVT_XKEY:
msg1 = TIP_("along X");
msg2 = TIP_("along %s X");
msg3 = TIP_("locking %s X");
axis = 'X';
constraint_axis = CON_AXIS0;
break;
- case YKEY:
+ case EVT_YKEY:
msg1 = TIP_("along Y");
msg2 = TIP_("along %s Y");
msg3 = TIP_("locking %s Y");
axis = 'Y';
constraint_axis = CON_AXIS1;
break;
- case ZKEY:
+ case EVT_ZKEY:
msg1 = TIP_("along Z");
msg2 = TIP_("along %s Z");
msg3 = TIP_("locking %s Z");
@@ -1001,7 +816,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
}
constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis));
- if (edit_2d && (key_type != ZKEY)) {
+ if (edit_2d && (key_type != EVT_ZKEY)) {
if (cmode == axis) {
stopConstraint(t);
}
@@ -1010,34 +825,22 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
}
}
else if (!edit_2d) {
- if (cmode != axis) {
- /* First press, constraint to an axis. */
- t->orientation.index = 0;
- const short *orientation_ptr = t->orientation.types[t->orientation.index];
- const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL;
- if (is_plane == false) {
- setUserConstraint(t, orientation, constraint_axis, msg2);
- }
- else {
- setUserConstraint(t, orientation, constraint_plane, msg3);
- }
- }
- else {
+ if (t->orientation.index == 0 || ELEM(cmode, '\0', axis)) {
/* Successive presses on existing axis, cycle orientation modes. */
t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types);
+ initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]);
+ }
- if (t->orientation.index == 0) {
- stopConstraint(t);
+ if (t->orientation.index == 0) {
+ stopConstraint(t);
+ }
+ else {
+ const short orientation = t->orientation.types[t->orientation.index];
+ if (is_plane == false) {
+ setUserConstraint(t, orientation, constraint_axis, msg2);
}
else {
- const short *orientation_ptr = t->orientation.types[t->orientation.index];
- const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL;
- if (is_plane == false) {
- setUserConstraint(t, orientation, constraint_axis, msg2);
- }
- else {
- setUserConstraint(t, orientation, constraint_plane, msg3);
- }
+ setUserConstraint(t, orientation, constraint_plane, msg3);
}
}
}
@@ -1047,7 +850,6 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
int transformEvent(TransInfo *t, const wmEvent *event)
{
- char cmode = constraintModeToChar(t);
bool handled = false;
const int modifiers_prev = t->modifiers;
const int mode_prev = t->mode;
@@ -1103,7 +905,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- initTranslation(t);
+ transform_mode_init(t, NULL, TFM_TRANSLATION);
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
handled = true;
@@ -1121,21 +923,20 @@ int transformEvent(TransInfo *t, const wmEvent *event)
resetTransRestrictions(t);
/* first try edge slide */
- initEdgeSlide(t);
+ transform_mode_init(t, NULL, TFM_EDGE_SLIDE);
/* if that fails, do vertex slide */
if (t->state == TRANS_CANCEL) {
resetTransModal(t);
t->state = TRANS_STARTING;
- initVertSlide(t);
+ transform_mode_init(t, NULL, TFM_VERT_SLIDE);
}
/* vert slide can fail on unconnected vertices (rare but possible) */
if (t->state == TRANS_CANCEL) {
resetTransModal(t);
- t->mode = TFM_TRANSLATION;
t->state = TRANS_STARTING;
restoreTransObjects(t);
resetTransRestrictions(t);
- initTranslation(t);
+ transform_mode_init(t, NULL, TFM_TRANSLATION);
}
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
@@ -1168,10 +969,10 @@ int transformEvent(TransInfo *t, const wmEvent *event)
resetTransRestrictions(t);
if (t->mode == TFM_ROTATION) {
- initTrackball(t);
+ transform_mode_init(t, NULL, TFM_TRACKBALL);
}
else {
- initRotation(t);
+ transform_mode_init(t, NULL, TFM_ROTATION);
}
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
@@ -1196,7 +997,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- initResize(t);
+ transform_mode_init(t, NULL, TFM_RESIZE);
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
handled = true;
@@ -1234,42 +1035,42 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_AXIS_X:
if (!(t->flag & T_NO_CONSTRAINT)) {
- transform_event_xyz_constraint(t, XKEY, cmode, false);
+ transform_event_xyz_constraint(t, EVT_XKEY, false);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
case TFM_MODAL_AXIS_Y:
if ((t->flag & T_NO_CONSTRAINT) == 0) {
- transform_event_xyz_constraint(t, YKEY, cmode, false);
+ transform_event_xyz_constraint(t, EVT_YKEY, false);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
case TFM_MODAL_AXIS_Z:
if ((t->flag & (T_NO_CONSTRAINT)) == 0) {
- transform_event_xyz_constraint(t, ZKEY, cmode, false);
+ transform_event_xyz_constraint(t, EVT_ZKEY, false);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
case TFM_MODAL_PLANE_X:
if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
- transform_event_xyz_constraint(t, XKEY, cmode, true);
+ transform_event_xyz_constraint(t, EVT_XKEY, true);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
case TFM_MODAL_PLANE_Y:
if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
- transform_event_xyz_constraint(t, YKEY, cmode, true);
+ transform_event_xyz_constraint(t, EVT_YKEY, true);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
case TFM_MODAL_PLANE_Z:
if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
- transform_event_xyz_constraint(t, ZKEY, cmode, true);
+ transform_event_xyz_constraint(t, EVT_ZKEY, true);
t->redraw |= TREDRAW_HARD;
handled = true;
}
@@ -1347,9 +1148,9 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
if (t->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+ SpaceNode *snode = (SpaceNode *)t->area->spacedata.first;
- BLI_assert(t->sa->spacetype == t->spacetype);
+ BLI_assert(t->area->spacetype == t->spacetype);
if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) {
snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT;
@@ -1374,23 +1175,29 @@ int transformEvent(TransInfo *t, const wmEvent *event)
/* else do non-mapped events */
else if (event->val == KM_PRESS) {
switch (event->type) {
+ case EVT_ESCKEY:
case RIGHTMOUSE:
t->state = TRANS_CANCEL;
handled = true;
break;
- /* enforce redraw of transform when modifiers are used */
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- t->modifiers |= MOD_CONSTRAINT_PLANE;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case SPACEKEY:
+ case EVT_SPACEKEY:
+ case EVT_PADENTER:
+ case EVT_RETKEY:
+ if (event->is_repeat) {
+ break;
+ }
t->state = TRANS_CONFIRM;
handled = true;
break;
+ /* enforce redraw of transform when modifiers are used */
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
+ t->modifiers |= MOD_CONSTRAINT_PLANE;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
case MIDDLEMOUSE:
if ((t->flag & T_NO_CONSTRAINT) == 0) {
/* exception for switching to dolly, or trackball, in camera view */
@@ -1400,7 +1207,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
else if (t->mode == TFM_ROTATION) {
restoreTransObjects(t);
- initTrackball(t);
+ transform_mode_init(t, NULL, TFM_TRACKBALL);
}
}
else {
@@ -1409,17 +1216,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
stopConstraint(t);
}
else {
- if (event->shift) {
- /* bit hackish... but it prevents mmb select to print the
- * orientation from menu */
- float mati[3][3];
- strcpy(t->spacename, "global");
- unit_m3(mati);
- initSelectConstraint(t, mati);
- }
- else {
- initSelectConstraint(t, t->spacemtx);
- }
+ initSelectConstraint(t, event->shift);
postSelectConstraint(t);
}
}
@@ -1427,40 +1224,40 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
- case ESCKEY:
- t->state = TRANS_CANCEL;
- handled = true;
- break;
- case PADENTER:
- case RETKEY:
- t->state = TRANS_CONFIRM;
- handled = true;
- break;
- case GKEY:
+ case EVT_GKEY:
+ if (event->is_repeat) {
+ break;
+ }
/* only switch when... */
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- initTranslation(t);
+ transform_mode_init(t, NULL, TFM_TRANSLATION);
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
- case SKEY:
+ case EVT_SKEY:
+ if (event->is_repeat) {
+ break;
+ }
/* only switch when... */
if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) {
restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- initResize(t);
+ transform_mode_init(t, NULL, TFM_RESIZE);
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
- case RKEY:
+ case EVT_RKEY:
+ if (event->is_repeat) {
+ break;
+ }
/* only switch when... */
if (!(t->options & CTX_TEXTURE)) {
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) {
@@ -1469,10 +1266,10 @@ int transformEvent(TransInfo *t, const wmEvent *event)
resetTransRestrictions(t);
if (t->mode == TFM_ROTATION) {
- initTrackball(t);
+ transform_mode_init(t, NULL, TFM_TRACKBALL);
}
else {
- initRotation(t);
+ transform_mode_init(t, NULL, TFM_ROTATION);
}
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
@@ -1480,7 +1277,10 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
}
break;
- case CKEY:
+ case EVT_CKEY:
+ if (event->is_repeat) {
+ break;
+ }
if (event->alt) {
if (!(t->options & CTX_NO_PET)) {
t->flag ^= T_PROP_CONNECTED;
@@ -1491,7 +1291,10 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
}
break;
- case OKEY:
+ case EVT_OKEY:
+ if (event->is_repeat) {
+ break;
+ }
if (t->flag & T_PROP_EDIT && event->shift) {
t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX;
calculatePropRatio(t);
@@ -1499,7 +1302,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
- case PADPLUSKEY:
+ case EVT_PADPLUSKEY:
if (event->alt && t->flag & T_PROP_EDIT) {
t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
@@ -1510,7 +1313,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
- case PAGEUPKEY:
+ case EVT_PAGEUPKEY:
case WHEELDOWNMOUSE:
if (t->flag & T_AUTOIK) {
transform_autoik_update(t, 1);
@@ -1521,7 +1324,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
t->redraw = TREDRAW_HARD;
handled = true;
break;
- case PADMINUS:
+ case EVT_PADMINUS:
if (event->alt && t->flag & T_PROP_EDIT) {
t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
calculatePropRatio(t);
@@ -1529,7 +1332,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
- case PAGEDOWNKEY:
+ case EVT_PAGEDOWNKEY:
case WHEELUPMOUSE:
if (t->flag & T_AUTOIK) {
transform_autoik_update(t, -1);
@@ -1540,21 +1343,24 @@ int transformEvent(TransInfo *t, const wmEvent *event)
t->redraw = TREDRAW_HARD;
handled = true;
break;
- case LEFTALTKEY:
- case RIGHTALTKEY:
+ case EVT_LEFTALTKEY:
+ case EVT_RIGHTALTKEY:
if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
t->flag |= T_ALT_TRANSFORM;
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
- case NKEY:
+ case EVT_NKEY:
+ if (event->is_repeat) {
+ break;
+ }
if (ELEM(t->mode, TFM_ROTATION)) {
if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
- initNormalRotation(t);
+ transform_mode_init(t, NULL, TFM_NORMAL_ROTATION);
t->redraw = TREDRAW_HARD;
handled = true;
}
@@ -1569,8 +1375,8 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
else if (event->val == KM_RELEASE) {
switch (event->type) {
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
t->modifiers &= ~MOD_CONSTRAINT_PLANE;
t->redraw |= TREDRAW_HARD;
handled = true;
@@ -1584,8 +1390,8 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
- case LEFTALTKEY:
- case RIGHTALTKEY:
+ case EVT_LEFTALTKEY:
+ case EVT_RIGHTALTKEY:
if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
t->flag &= ~T_ALT_TRANSFORM;
t->redraw |= TREDRAW_HARD;
@@ -1685,17 +1491,17 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa
return success;
}
-static bool transinfo_show_overlay(const struct bContext *C, TransInfo *t, ARegion *ar)
+static bool transinfo_show_overlay(const struct bContext *C, TransInfo *t, ARegion *region)
{
/* Don't show overlays when not the active view and when overlay is disabled: T57139 */
bool ok = false;
- if (ar == t->ar) {
+ if (region == t->region) {
ok = true;
}
else {
- ScrArea *sa = CTX_wm_area(C);
- if (sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
+ ScrArea *area = CTX_wm_area(C);
+ if (area->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = area->spacedata.first;
if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) {
ok = true;
}
@@ -1704,11 +1510,11 @@ static bool transinfo_show_overlay(const struct bContext *C, TransInfo *t, ARegi
return ok;
}
-static void drawTransformView(const struct bContext *C, ARegion *ar, void *arg)
+static void drawTransformView(const struct bContext *C, ARegion *region, void *arg)
{
TransInfo *t = arg;
- if (!transinfo_show_overlay(C, t, ar)) {
+ if (!transinfo_show_overlay(C, t, region)) {
return;
}
@@ -1718,7 +1524,7 @@ static void drawTransformView(const struct bContext *C, ARegion *ar, void *arg)
drawPropCircle(C, t);
drawSnapping(C, t);
- if (ar == t->ar) {
+ if (region == t->region) {
/* edge slide, vert slide */
drawEdgeSlide(t);
drawVertSlide(t);
@@ -1730,13 +1536,13 @@ static void drawTransformView(const struct bContext *C, ARegion *ar, void *arg)
/* just draw a little warning message in the top-right corner of the viewport
* to warn that autokeying is enabled */
-static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
+static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *region)
{
const char *printable = IFACE_("Auto Keying On");
float printable_size[2];
int xco, yco;
- const rcti *rect = ED_region_visible_rect(ar);
+ const rcti *rect = ED_region_visible_rect(region);
const int font_id = BLF_default();
BLF_width_and_height(
@@ -1748,7 +1554,7 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
/* warning text (to clarify meaning of overlays)
* - original color was red to match the icon, but that clashes badly with a less nasty border
*/
- unsigned char color[3];
+ uchar color[3];
UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color);
BLF_color3ubv(font_id, color);
#ifdef WITH_INTERNATIONAL
@@ -1770,15 +1576,15 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
GPU_blend(false);
}
-static void drawTransformPixel(const struct bContext *C, ARegion *ar, void *arg)
+static void drawTransformPixel(const struct bContext *C, ARegion *region, void *arg)
{
TransInfo *t = arg;
- if (!transinfo_show_overlay(C, t, ar)) {
+ if (!transinfo_show_overlay(C, t, region)) {
return;
}
- if (ar == t->ar) {
+ if (region == t->region) {
Scene *scene = t->scene;
ViewLayer *view_layer = t->view_layer;
Object *ob = OBACT(view_layer);
@@ -1789,10 +1595,10 @@ static void drawTransformPixel(const struct bContext *C, ARegion *ar, void *arg)
* AND only for the active region (as showing all is too overwhelming)
*/
if ((U.autokey_flag & AUTOKEY_FLAG_NOWARNING) == 0) {
- if (ar == t->ar) {
+ if (region == t->region) {
if (t->flag & (T_OBJECT | T_POSE)) {
if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) {
- drawAutoKeyWarning(t, ar);
+ drawAutoKeyWarning(t, region);
}
}
}
@@ -1871,18 +1677,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
ts->prop_mode = t->prop_mode;
}
}
-
- if (t->spacetype == SPACE_VIEW3D) {
- if ((prop = RNA_struct_find_property(op->ptr, "orient_type")) &&
- !RNA_property_is_set(op->ptr, prop) &&
- (t->orientation.user != V3D_ORIENT_CUSTOM_MATRIX)) {
- TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
- orient_slot->type = t->orientation.user;
- BLI_assert(((orient_slot->index_custom == -1) && (t->orientation.custom == NULL)) ||
- (BKE_scene_transform_orientation_get_index(t->scene, t->orientation.custom) ==
- orient_slot->index_custom));
- }
- }
}
if (t->flag & T_MODAL) {
@@ -1909,33 +1703,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0);
}
- /* Orientation used for redo. */
- const bool use_orient_axis = (t->orient_matrix_is_set &&
- (RNA_struct_find_property(op->ptr, "orient_axis") != NULL));
- short orientation;
- if (t->con.mode & CON_APPLY) {
- orientation = t->con.orientation;
- if (orientation == V3D_ORIENT_CUSTOM) {
- const int orientation_index_custom = BKE_scene_transform_orientation_get_index(
- t->scene, t->orientation.custom);
- /* Maybe we need a t->con.custom_orientation?
- * Seems like it would always match t->orientation.custom. */
- orientation = V3D_ORIENT_CUSTOM + orientation_index_custom;
- BLI_assert(orientation >= V3D_ORIENT_CUSTOM);
- }
- }
- else if ((t->orientation.user == V3D_ORIENT_CUSTOM_MATRIX) &&
- (prop = RNA_struct_find_property(op->ptr, "orient_matrix_type"))) {
- orientation = RNA_property_enum_get(op->ptr, prop);
- }
- else if (use_orient_axis) {
- /* We're not using an orientation, use the fallback. */
- orientation = t->orientation.unset;
- }
- else {
- orientation = V3D_ORIENT_GLOBAL;
- }
-
if ((prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
if (t->flag & T_MODAL) {
if (t->con.mode & CON_APPLY) {
@@ -1955,56 +1722,40 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
- if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix"))) {
- if (t->flag & T_MODAL) {
- if (orientation != V3D_ORIENT_CUSTOM_MATRIX) {
- if (t->flag & T_MODAL) {
- RNA_enum_set(op->ptr, "orient_matrix_type", orientation);
- }
- }
- if (t->con.mode & CON_APPLY) {
- RNA_float_set_array(op->ptr, "orient_matrix", &t->con.mtx[0][0]);
- }
- else if (use_orient_axis) {
- RNA_float_set_array(op->ptr, "orient_matrix", &t->orient_matrix[0][0]);
- }
- else {
- RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]);
- }
- }
- }
-
if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) {
- /* constraint orientation can be global, even if user selects something else
- * so use the orientation in the constraint if set */
+ short orient_set, orient_cur;
+ orient_set = RNA_property_is_set(op->ptr, prop) ? RNA_property_enum_get(op->ptr, prop) : -1;
+ orient_cur = t->orientation.types[t->orientation.index];
- /* Use 'orient_matrix' instead. */
- if (t->flag & T_MODAL) {
- if (orientation != V3D_ORIENT_CUSTOM_MATRIX) {
- RNA_property_enum_set(op->ptr, prop, orientation);
- }
+ if (!ELEM(orient_cur, orient_set, V3D_ORIENT_CUSTOM_MATRIX)) {
+ RNA_property_enum_set(op->ptr, prop, orient_cur);
+ orient_set = orient_cur;
+ }
+
+ if (((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) &&
+ !RNA_property_is_set(op->ptr, prop))) {
+ /* Set the first time to register on redo. */
+ RNA_property_enum_set(op->ptr, prop, orient_set);
+ RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]);
}
}
if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
bool constraint_axis[3] = {false, false, false};
- if (t->flag & T_MODAL) {
- /* Only set if needed, so we can hide in the UI when nothing is set.
- * See 'transform_poll_property'. */
- if (t->con.mode & CON_APPLY) {
- if (t->con.mode & CON_AXIS0) {
- constraint_axis[0] = true;
- }
- if (t->con.mode & CON_AXIS1) {
- constraint_axis[1] = true;
- }
- if (t->con.mode & CON_AXIS2) {
- constraint_axis[2] = true;
- }
+ if (t->con.mode & CON_APPLY) {
+ if (t->con.mode & CON_AXIS0) {
+ constraint_axis[0] = true;
}
- if (ELEM(true, UNPACK3(constraint_axis))) {
- RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
+ if (t->con.mode & CON_AXIS1) {
+ constraint_axis[1] = true;
}
+ if (t->con.mode & CON_AXIS2) {
+ constraint_axis[2] = true;
+ }
+ RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
+ }
+ else {
+ RNA_property_unset(op->ptr, prop);
}
}
@@ -2031,6 +1782,43 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
+static void initSnapSpatial(TransInfo *t, float r_snap[3])
+{
+ if (t->spacetype == SPACE_VIEW3D) {
+ RegionView3D *rv3d = t->region->regiondata;
+
+ if (rv3d) {
+ View3D *v3d = t->area->spacedata.first;
+ r_snap[0] = 0.0f;
+ r_snap[1] = ED_view3d_grid_view_scale(t->scene, v3d, rv3d, NULL) * 1.0f;
+ r_snap[2] = r_snap[1] * 0.1f;
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 0.0625f;
+ r_snap[2] = 0.03125f;
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 0.125f;
+ r_snap[2] = 0.0625f;
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = r_snap[2] = ED_node_grid_size();
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 1.0;
+ r_snap[2] = 0.1f;
+ }
+ else {
+ r_snap[0] = 0.0f;
+ r_snap[1] = r_snap[2] = 1.0f;
+ }
+}
+
/**
* \note caller needs to free 't' on a 0 return
* \warning \a event might be NULL (when tweaking from redo panel)
@@ -2093,15 +1881,21 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
unit_m3(t->spacemtx);
initTransInfo(C, t, op, event);
- initTransformOrientation(C, t);
+
+ /* Use the custom orientation when it is set. */
+ short orientation = t->orientation.types[0] == V3D_ORIENT_CUSTOM_MATRIX ?
+ V3D_ORIENT_CUSTOM_MATRIX :
+ t->orientation.types[t->orientation.index];
+
+ initTransformOrientation(C, t, orientation);
if (t->spacetype == SPACE_VIEW3D) {
t->draw_handle_apply = ED_region_draw_cb_activate(
- t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);
+ t->region->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);
t->draw_handle_view = ED_region_draw_cb_activate(
- t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_pixel = ED_region_draw_cb_activate(
- t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
+ t->region->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
SPACE_TYPE_ANY,
RGN_TYPE_ANY,
@@ -2111,7 +1905,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
else if (t->spacetype == SPACE_IMAGE) {
t->draw_handle_view = ED_region_draw_cb_activate(
- t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
SPACE_TYPE_ANY,
RGN_TYPE_ANY,
@@ -2121,7 +1915,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
else if (t->spacetype == SPACE_CLIP) {
t->draw_handle_view = ED_region_draw_cb_activate(
- t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
SPACE_TYPE_ANY,
RGN_TYPE_ANY,
@@ -2131,7 +1925,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
else if (t->spacetype == SPACE_NODE) {
t->draw_handle_view = ED_region_draw_cb_activate(
- t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
SPACE_TYPE_ANY,
RGN_TYPE_ANY,
@@ -2141,7 +1935,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
else if (t->spacetype == SPACE_GRAPH) {
t->draw_handle_view = ED_region_draw_cb_activate(
- t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
SPACE_TYPE_ANY,
RGN_TYPE_ANY,
@@ -2151,7 +1945,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
else if (t->spacetype == SPACE_ACTION) {
t->draw_handle_view = ED_region_draw_cb_activate(
- t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
SPACE_TYPE_ANY,
RGN_TYPE_ANY,
@@ -2190,10 +1984,10 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
if (kmi->propvalue == TFM_MODAL_SNAP_INV_ON && kmi->val == KM_PRESS) {
- if ((ELEM(kmi->type, LEFTCTRLKEY, RIGHTCTRLKEY) && event->ctrl) ||
- (ELEM(kmi->type, LEFTSHIFTKEY, RIGHTSHIFTKEY) && event->shift) ||
- (ELEM(kmi->type, LEFTALTKEY, RIGHTALTKEY) && event->alt) ||
- ((kmi->type == OSKEY) && event->oskey)) {
+ if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && event->ctrl) ||
+ (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && event->shift) ||
+ (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && event->alt) ||
+ ((kmi->type == EVT_OSKEY) && event->oskey)) {
t->modifiers |= MOD_SNAP_INVERT;
}
break;
@@ -2218,33 +2012,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
calculatePropRatio(t);
calculateCenter(t);
- /* Overwrite initial values if operator supplied a non-null vector.
- *
- * Run before init functions so 'values_modal_offset' can be applied on mouse input.
- */
- BLI_assert(is_zero_v4(t->values_modal_offset));
- if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) {
- float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */
-
- if (RNA_property_array_check(prop)) {
- RNA_float_get_array(op->ptr, "value", values);
- }
- else {
- values[0] = RNA_float_get(op->ptr, "value");
- }
-
- copy_v4_v4(t->values, values);
-
- if (t->flag & T_MODAL) {
- copy_v4_v4(t->values_modal_offset, values);
- t->redraw = TREDRAW_HARD;
- }
- else {
- copy_v4_v4(t->values, values);
- t->flag |= T_INPUT_IS_VALUES_FINAL;
- }
- }
-
if (event) {
/* Initialize accurate transform to settings requested by keymap. */
bool use_accurate = false;
@@ -2257,145 +2024,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate);
}
- switch (mode) {
- case TFM_TRANSLATION:
- initTranslation(t);
- break;
- case TFM_ROTATION:
- initRotation(t);
- break;
- case TFM_RESIZE:
- initResize(t);
- break;
- case TFM_SKIN_RESIZE:
- initSkinResize(t);
- break;
- case TFM_TOSPHERE:
- initToSphere(t);
- break;
- case TFM_SHEAR:
- initShear(t);
- break;
- case TFM_BEND:
- initBend(t);
- break;
- case TFM_SHRINKFATTEN:
- initShrinkFatten(t);
- break;
- case TFM_TILT:
- initTilt(t);
- break;
- case TFM_CURVE_SHRINKFATTEN:
- initCurveShrinkFatten(t);
- break;
- case TFM_MASK_SHRINKFATTEN:
- initMaskShrinkFatten(t);
- break;
- case TFM_GPENCIL_SHRINKFATTEN:
- initGPShrinkFatten(t);
- break;
- case TFM_TRACKBALL:
- initTrackball(t);
- break;
- case TFM_PUSHPULL:
- initPushPull(t);
- break;
- case TFM_CREASE:
- initCrease(t);
- break;
- case TFM_BONESIZE: { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */
- /* Note: we have to pick one, use the active object. */
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
- bArmature *arm = tc->poseobj->data;
- if (arm->drawtype == ARM_ENVELOPE) {
- initBoneEnvelope(t);
- t->mode = TFM_BONE_ENVELOPE_DIST;
- }
- else {
- initBoneSize(t);
- }
- break;
- }
- case TFM_BONE_ENVELOPE:
- initBoneEnvelope(t);
- break;
- case TFM_BONE_ENVELOPE_DIST:
- initBoneEnvelope(t);
- t->mode = TFM_BONE_ENVELOPE_DIST;
- break;
- case TFM_EDGE_SLIDE:
- case TFM_VERT_SLIDE: {
- const bool use_even = (op ? RNA_boolean_get(op->ptr, "use_even") : false);
- const bool flipped = (op ? RNA_boolean_get(op->ptr, "flipped") : false);
- const bool use_clamp = (op ? RNA_boolean_get(op->ptr, "use_clamp") : true);
- if (mode == TFM_EDGE_SLIDE) {
- const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true);
- initEdgeSlide_ex(t, use_double_side, use_even, flipped, use_clamp);
- }
- else {
- initVertSlide_ex(t, use_even, flipped, use_clamp);
- }
- break;
- }
- case TFM_BONE_ROLL:
- initBoneRoll(t);
- break;
- case TFM_TIME_TRANSLATE:
- initTimeTranslate(t);
- break;
- case TFM_TIME_SLIDE:
- initTimeSlide(t);
- break;
- case TFM_TIME_SCALE:
- initTimeScale(t);
- break;
- case TFM_TIME_DUPLICATE:
- /* same as TFM_TIME_EXTEND, but we need the mode info for later
- * so that duplicate-culling will work properly
- */
- if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
- initTranslation(t);
- }
- else {
- initTimeTranslate(t);
- }
- t->mode = mode;
- break;
- case TFM_TIME_EXTEND:
- /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation
- * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION
- * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement)
- * depending on which editor this was called from
- */
- if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
- initTranslation(t);
- }
- else {
- initTimeTranslate(t);
- }
- break;
- case TFM_BAKE_TIME:
- initBakeTime(t);
- break;
- case TFM_MIRROR:
- initMirror(t);
- break;
- case TFM_BWEIGHT:
- initBevelWeight(t);
- break;
- case TFM_ALIGN:
- initAlign(t);
- break;
- case TFM_SEQ_SLIDE:
- initSeqSlide(t);
- break;
- case TFM_NORMAL_ROTATION:
- initNormalRotation(t);
- break;
- case TFM_GPENCIL_OPACITY:
- initGPOpacity(t);
- break;
- }
+ transform_mode_init(t, op, mode);
if (t->state == TRANS_CANCEL) {
postTrans(C, t);
@@ -2413,38 +2042,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
/* Constraint init from operator */
- if ((t->flag & T_MODAL) ||
- /* For mirror operator the constraint axes are effectively the values. */
- (RNA_struct_find_property(op->ptr, "value") == NULL)) {
- if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) &&
- RNA_property_is_set(op->ptr, prop)) {
- bool constraint_axis[3];
-
- RNA_property_boolean_get_array(op->ptr, prop, constraint_axis);
-
- if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) {
- t->con.mode |= CON_APPLY;
-
- if (constraint_axis[0]) {
- t->con.mode |= CON_AXIS0;
- }
- if (constraint_axis[1]) {
- t->con.mode |= CON_AXIS1;
- }
- if (constraint_axis[2]) {
- t->con.mode |= CON_AXIS2;
- }
-
- setUserConstraint(t, t->orientation.user, t->con.mode, "%s");
- }
- }
- }
- else {
- /* So we can adjust in non global orientation. */
- if (t->orientation.user != V3D_ORIENT_GLOBAL) {
- t->con.mode |= CON_APPLY | CON_AXIS0 | CON_AXIS1 | CON_AXIS2;
- setUserConstraint(t, t->orientation.user, t->con.mode, "%s");
- }
+ if (t->con.mode & CON_APPLY) {
+ setUserConstraint(t, t->orientation.types[t->orientation.index], t->con.mode, "%s");
}
/* Don't write into the values when non-modal because they are already set from operator redo
@@ -2518,7 +2117,7 @@ void transformApply(bContext *C, TransInfo *t)
t->context = NULL;
}
-static void drawTransformApply(const bContext *C, ARegion *UNUSED(ar), void *arg)
+static void drawTransformApply(const bContext *C, ARegion *UNUSED(region), void *arg)
{
TransInfo *t = arg;
@@ -2575,6597 +2174,6 @@ int transformEnd(bContext *C, TransInfo *t)
return exit_code;
}
-/* ************************** TRANSFORM LOCKS **************************** */
-
-static void protectedTransBits(short protectflag, float vec[3])
-{
- if (protectflag & OB_LOCK_LOCX) {
- vec[0] = 0.0f;
- }
- if (protectflag & OB_LOCK_LOCY) {
- vec[1] = 0.0f;
- }
- if (protectflag & OB_LOCK_LOCZ) {
- vec[2] = 0.0f;
- }
-}
-
-static void protectedSizeBits(short protectflag, float size[3])
-{
- if (protectflag & OB_LOCK_SCALEX) {
- size[0] = 1.0f;
- }
- if (protectflag & OB_LOCK_SCALEY) {
- size[1] = 1.0f;
- }
- if (protectflag & OB_LOCK_SCALEZ) {
- size[2] = 1.0f;
- }
-}
-
-static void protectedRotateBits(short protectflag, float eul[3], const float oldeul[3])
-{
- if (protectflag & OB_LOCK_ROTX) {
- eul[0] = oldeul[0];
- }
- if (protectflag & OB_LOCK_ROTY) {
- eul[1] = oldeul[1];
- }
- if (protectflag & OB_LOCK_ROTZ) {
- eul[2] = oldeul[2];
- }
-}
-
-/* this function only does the delta rotation */
-/* axis-angle is usually internally stored as quats... */
-static void protectedAxisAngleBits(
- short protectflag, float axis[3], float *angle, float oldAxis[3], float oldAngle)
-{
- /* check that protection flags are set */
- if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) {
- return;
- }
-
- if (protectflag & OB_LOCK_ROT4D) {
- /* axis-angle getting limited as 4D entities that they are... */
- if (protectflag & OB_LOCK_ROTW) {
- *angle = oldAngle;
- }
- if (protectflag & OB_LOCK_ROTX) {
- axis[0] = oldAxis[0];
- }
- if (protectflag & OB_LOCK_ROTY) {
- axis[1] = oldAxis[1];
- }
- if (protectflag & OB_LOCK_ROTZ) {
- axis[2] = oldAxis[2];
- }
- }
- else {
- /* axis-angle get limited with euler... */
- float eul[3], oldeul[3];
-
- axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, axis, *angle);
- axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, oldAxis, oldAngle);
-
- if (protectflag & OB_LOCK_ROTX) {
- eul[0] = oldeul[0];
- }
- if (protectflag & OB_LOCK_ROTY) {
- eul[1] = oldeul[1];
- }
- if (protectflag & OB_LOCK_ROTZ) {
- eul[2] = oldeul[2];
- }
-
- eulO_to_axis_angle(axis, angle, eul, EULER_ORDER_DEFAULT);
-
- /* When converting to axis-angle,
- * we need a special exception for the case when there is no axis. */
- if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) {
- /* for now, rotate around y-axis then (so that it simply becomes the roll) */
- axis[1] = 1.0f;
- }
- }
-}
-
-/* this function only does the delta rotation */
-static void protectedQuaternionBits(short protectflag, float quat[4], const float oldquat[4])
-{
- /* check that protection flags are set */
- if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) {
- return;
- }
-
- if (protectflag & OB_LOCK_ROT4D) {
- /* quaternions getting limited as 4D entities that they are... */
- if (protectflag & OB_LOCK_ROTW) {
- quat[0] = oldquat[0];
- }
- if (protectflag & OB_LOCK_ROTX) {
- quat[1] = oldquat[1];
- }
- if (protectflag & OB_LOCK_ROTY) {
- quat[2] = oldquat[2];
- }
- if (protectflag & OB_LOCK_ROTZ) {
- quat[3] = oldquat[3];
- }
- }
- else {
- /* quaternions get limited with euler... (compatibility mode) */
- float eul[3], oldeul[3], nquat[4], noldquat[4];
- float qlen;
-
- qlen = normalize_qt_qt(nquat, quat);
- normalize_qt_qt(noldquat, oldquat);
-
- quat_to_eul(eul, nquat);
- quat_to_eul(oldeul, noldquat);
-
- if (protectflag & OB_LOCK_ROTX) {
- eul[0] = oldeul[0];
- }
- if (protectflag & OB_LOCK_ROTY) {
- eul[1] = oldeul[1];
- }
- if (protectflag & OB_LOCK_ROTZ) {
- eul[2] = oldeul[2];
- }
-
- eul_to_quat(quat, eul);
-
- /* restore original quat size */
- mul_qt_fl(quat, qlen);
-
- /* quaternions flip w sign to accumulate rotations correctly */
- if ((nquat[0] < 0.0f && quat[0] > 0.0f) || (nquat[0] > 0.0f && quat[0] < 0.0f)) {
- mul_qt_fl(quat, -1.0f);
- }
- }
-}
-
-/* ******************* TRANSFORM LIMITS ********************** */
-
-static void constraintTransLim(TransInfo *t, TransData *td)
-{
- if (td->con) {
- const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(
- CONSTRAINT_TYPE_LOCLIMIT);
- const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(
- CONSTRAINT_TYPE_DISTLIMIT);
-
- bConstraintOb cob = {NULL};
- bConstraint *con;
- float ctime = (float)(t->scene->r.cfra);
-
- /* Make a temporary bConstraintOb for using these limit constraints
- * - they only care that cob->matrix is correctly set ;-)
- * - current space should be local
- */
- unit_m4(cob.matrix);
- copy_v3_v3(cob.matrix[3], td->loc);
-
- /* Evaluate valid constraints */
- for (con = td->con; con; con = con->next) {
- const bConstraintTypeInfo *cti = NULL;
- ListBase targets = {NULL, NULL};
-
- /* only consider constraint if enabled */
- if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
- continue;
- }
- if (con->enforce == 0.0f) {
- continue;
- }
-
- /* only use it if it's tagged for this purpose (and the right type) */
- if (con->type == CONSTRAINT_TYPE_LOCLIMIT) {
- bLocLimitConstraint *data = con->data;
-
- if ((data->flag2 & LIMIT_TRANSFORM) == 0) {
- continue;
- }
- cti = ctiLoc;
- }
- else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) {
- bDistLimitConstraint *data = con->data;
-
- if ((data->flag & LIMITDIST_TRANSFORM) == 0) {
- continue;
- }
- cti = ctiDist;
- }
-
- if (cti) {
- /* do space conversions */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->mtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
- }
- else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
- /* skip... incompatible spacetype */
- continue;
- }
-
- /* get constraint targets if needed */
- BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime);
-
- /* do constraint */
- cti->evaluate_constraint(con, &cob, &targets);
-
- /* convert spaces again */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->smtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
- }
-
- /* free targets list */
- BLI_freelistN(&targets);
- }
- }
-
- /* copy results from cob->matrix */
- copy_v3_v3(td->loc, cob.matrix[3]);
- }
-}
-
-static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
-{
- /* Make a temporary bConstraintOb for use by limit constraints
- * - they only care that cob->matrix is correctly set ;-)
- * - current space should be local
- */
- memset(cob, 0, sizeof(bConstraintOb));
- if (td->ext) {
- if (td->ext->rotOrder == ROT_MODE_QUAT) {
- /* quats */
- /* objects and bones do normalization first too, otherwise
- * we don't necessarily end up with a rotation matrix, and
- * then conversion back to quat gives a different result */
- float quat[4];
- normalize_qt_qt(quat, td->ext->quat);
- quat_to_mat4(cob->matrix, quat);
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- /* axis angle */
- axis_angle_to_mat4(cob->matrix, td->ext->rotAxis, *td->ext->rotAngle);
- }
- else {
- /* eulers */
- eulO_to_mat4(cob->matrix, td->ext->rot, td->ext->rotOrder);
- }
- }
-}
-
-static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
-{
- if (td->con) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT);
- bConstraintOb cob;
- bConstraint *con;
- bool do_limit = false;
-
- /* Evaluate valid constraints */
- for (con = td->con; con; con = con->next) {
- /* only consider constraint if enabled */
- if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
- continue;
- }
- if (con->enforce == 0.0f) {
- continue;
- }
-
- /* we're only interested in Limit-Rotation constraints */
- if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
- bRotLimitConstraint *data = con->data;
-
- /* only use it if it's tagged for this purpose */
- if ((data->flag2 & LIMIT_TRANSFORM) == 0) {
- continue;
- }
-
- /* skip incompatible spacetypes */
- if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) {
- continue;
- }
-
- /* only do conversion if necessary, to preserve quats and eulers */
- if (do_limit == false) {
- constraintob_from_transdata(&cob, td);
- do_limit = true;
- }
-
- /* do space conversions */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->mtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
- }
-
- /* do constraint */
- cti->evaluate_constraint(con, &cob, NULL);
-
- /* convert spaces again */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->smtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
- }
- }
- }
-
- if (do_limit) {
- /* copy results from cob->matrix */
- if (td->ext->rotOrder == ROT_MODE_QUAT) {
- /* quats */
- mat4_to_quat(td->ext->quat, cob.matrix);
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- /* axis angle */
- mat4_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, cob.matrix);
- }
- else {
- /* eulers */
- mat4_to_eulO(td->ext->rot, td->ext->rotOrder, cob.matrix);
- }
- }
- }
-}
-
-static void constraintSizeLim(TransInfo *t, TransData *td)
-{
- if (td->con && td->ext) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
- bConstraintOb cob = {NULL};
- bConstraint *con;
- float size_sign[3], size_abs[3];
- int i;
-
- /* Make a temporary bConstraintOb for using these limit constraints
- * - they only care that cob->matrix is correctly set ;-)
- * - current space should be local
- */
- if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
- /* scale val and reset size */
- return; // TODO: fix this case
- }
- else {
- /* Reset val if SINGLESIZE but using a constraint */
- if (td->flag & TD_SINGLESIZE) {
- return;
- }
-
- /* separate out sign to apply back later */
- for (i = 0; i < 3; i++) {
- size_sign[i] = signf(td->ext->size[i]);
- size_abs[i] = fabsf(td->ext->size[i]);
- }
-
- size_to_mat4(cob.matrix, size_abs);
- }
-
- /* Evaluate valid constraints */
- for (con = td->con; con; con = con->next) {
- /* only consider constraint if enabled */
- if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
- continue;
- }
- if (con->enforce == 0.0f) {
- continue;
- }
-
- /* we're only interested in Limit-Scale constraints */
- if (con->type == CONSTRAINT_TYPE_SIZELIMIT) {
- bSizeLimitConstraint *data = con->data;
-
- /* only use it if it's tagged for this purpose */
- if ((data->flag2 & LIMIT_TRANSFORM) == 0) {
- continue;
- }
-
- /* do space conversions */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->mtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
- }
- else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
- /* skip... incompatible spacetype */
- continue;
- }
-
- /* do constraint */
- cti->evaluate_constraint(con, &cob, NULL);
-
- /* convert spaces again */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->smtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
- }
- }
- }
-
- /* copy results from cob->matrix */
- if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
- /* scale val and reset size */
- return; // TODO: fix this case
- }
- else {
- /* Reset val if SINGLESIZE but using a constraint */
- if (td->flag & TD_SINGLESIZE) {
- return;
- }
-
- /* extrace scale from matrix and apply back sign */
- mat4_to_size(td->ext->size, cob.matrix);
- mul_v3_v3(td->ext->size, size_sign);
- }
- }
-}
-
-/* -------------------------------------------------------------------- */
-/* Transform (Bend) */
-
-/** \name Transform Bend
- * \{ */
-
-struct BendCustomData {
- /* All values are in global space. */
- float warp_sta[3];
- float warp_end[3];
-
- float warp_nor[3];
- float warp_tan[3];
-
- /* for applying the mouse distance */
- float warp_init_dist;
-};
-
-static void initBend(TransInfo *t)
-{
- const float mval_fl[2] = {UNPACK2(t->mval)};
- const float *curs;
- float tvec[3];
- struct BendCustomData *data;
-
- t->mode = TFM_BEND;
- t->transform = Bend;
- t->handleEvent = handleEventBend;
-
- setInputPostFct(&t->mouse, postInputRotation);
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING);
-
- t->idx_max = 1;
- t->num.idx_max = 1;
- t->snap[0] = 0.0f;
- t->snap[1] = SNAP_INCREMENTAL_ANGLE;
- t->snap[2] = t->snap[1] * 0.2;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
- t->num.unit_type[1] = B_UNIT_LENGTH;
-
- t->flag |= T_NO_CONSTRAINT;
-
- // copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
- if ((t->flag & T_OVERRIDE_CENTER) == 0) {
- calculateCenterCursor(t, t->center_global);
- }
- calculateCenterLocal(t, t->center_global);
-
- t->val = 0.0f;
-
- data = MEM_callocN(sizeof(*data), __func__);
-
- curs = t->scene->cursor.location;
- copy_v3_v3(data->warp_sta, curs);
- ED_view3d_win_to_3d(t->sa->spacedata.first, t->ar, curs, mval_fl, data->warp_end);
-
- copy_v3_v3(data->warp_nor, t->viewinv[2]);
- normalize_v3(data->warp_nor);
-
- /* tangent */
- sub_v3_v3v3(tvec, data->warp_end, data->warp_sta);
- cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor);
- normalize_v3(data->warp_tan);
-
- data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
-
- t->custom.mode.data = data;
- t->custom.mode.use_free = true;
-}
-
-static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event)
-{
- eRedrawFlag status = TREDRAW_NOTHING;
-
- if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
- status = TREDRAW_HARD;
- }
-
- return status;
-}
-
-static void Bend(TransInfo *t, const int UNUSED(mval[2]))
-{
- float vec[3];
- float pivot_global[3];
- float warp_end_radius_global[3];
- int i;
- char str[UI_MAX_DRAW_STR];
- const struct BendCustomData *data = t->custom.mode.data;
- const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0;
-
- union {
- struct {
- float angle, scale;
- };
- float vector[2];
- } values;
-
- /* amount of radians for bend */
- copy_v2_v2(values.vector, t->values);
-
-#if 0
- snapGrid(t, angle_rad);
-#else
- /* hrmf, snapping radius is using 'angle' steps, need to convert to something else
- * this isnt essential but nicer to give reasonable snapping values for radius */
- if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) {
- const float radius_snap = 0.1f;
- const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap;
- values.scale *= snap_hack;
- snapGridIncrement(t, values.vector);
- values.scale /= snap_hack;
- }
-#endif
-
- if (applyNumInput(&t->num, values.vector)) {
- values.scale = values.scale / data->warp_init_dist;
- }
-
- copy_v2_v2(t->values_final, values.vector);
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN * 2];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- BLI_snprintf(str,
- sizeof(str),
- TIP_("Bend Angle: %s Radius: %s Alt, Clamp %s"),
- &c[0],
- &c[NUM_STR_REP_LEN],
- WM_bool_as_string(is_clamp));
- }
- else {
- /* default header print */
- BLI_snprintf(str,
- sizeof(str),
- TIP_("Bend Angle: %.3f Radius: %.4f, Alt, Clamp %s"),
- RAD2DEGF(values.angle),
- values.scale * data->warp_init_dist,
- WM_bool_as_string(is_clamp));
- }
-
- values.angle *= -1.0f;
- values.scale *= data->warp_init_dist;
-
- /* calc 'data->warp_end' from 'data->warp_end_init' */
- copy_v3_v3(warp_end_radius_global, data->warp_end);
- dist_ensure_v3_v3fl(warp_end_radius_global, data->warp_sta, values.scale);
- /* done */
-
- /* calculate pivot */
- copy_v3_v3(pivot_global, data->warp_sta);
- if (values.angle > 0.0f) {
- madd_v3_v3fl(pivot_global,
- data->warp_tan,
- -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle));
- }
- else {
- madd_v3_v3fl(pivot_global,
- data->warp_tan,
- +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle));
- }
-
- /* TODO(campbell): xform, compensate object center. */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
-
- float warp_sta_local[3];
- float warp_end_local[3];
- float warp_end_radius_local[3];
- float pivot_local[3];
-
- if (tc->use_local_mat) {
- sub_v3_v3v3(warp_sta_local, data->warp_sta, tc->mat[3]);
- sub_v3_v3v3(warp_end_local, data->warp_end, tc->mat[3]);
- sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]);
- sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]);
- }
- else {
- copy_v3_v3(warp_sta_local, data->warp_sta);
- copy_v3_v3(warp_end_local, data->warp_end);
- copy_v3_v3(warp_end_radius_local, warp_end_radius_global);
- copy_v3_v3(pivot_local, pivot_global);
- }
-
- for (i = 0; i < tc->data_len; i++, td++) {
- float mat[3][3];
- float delta[3];
- float fac, fac_scaled;
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (UNLIKELY(values.angle == 0.0f)) {
- copy_v3_v3(td->loc, td->iloc);
- continue;
- }
-
- copy_v3_v3(vec, td->iloc);
- mul_m3_v3(td->mtx, vec);
-
- fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local);
- if (is_clamp) {
- CLAMP(fac, 0.0f, 1.0f);
- }
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* grease pencil multiframe falloff */
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- if (gps != NULL) {
- fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff;
- }
- else {
- fac_scaled = fac * td->factor;
- }
- }
- else {
- fac_scaled = fac * td->factor;
- }
-
- axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled);
- interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled);
- sub_v3_v3(delta, warp_sta_local);
-
- /* delta is subtracted, rotation adds back this offset */
- sub_v3_v3(vec, delta);
-
- sub_v3_v3(vec, pivot_local);
- mul_m3_v3(mat, vec);
- add_v3_v3(vec, pivot_local);
-
- mul_m3_v3(td->smtx, vec);
-
- /* rotation */
- if ((t->flag & T_POINTS) == 0) {
- ElementRotation(t, tc, td, mat, V3D_AROUND_LOCAL_ORIGINS);
- }
-
- /* location */
- copy_v3_v3(td->loc, vec);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Shear) */
-
-/** \name Transform Shear
- * \{ */
-
-static void initShear_mouseInputMode(TransInfo *t)
-{
- float dir[3];
- bool dir_flip = false;
- copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]);
-
- /* Needed for axis aligned view gizmo. */
- if (t->orientation.user == V3D_ORIENT_VIEW) {
- if (t->orient_axis_ortho == 0) {
- if (t->center2d[1] > t->mouse.imval[1]) {
- dir_flip = !dir_flip;
- }
- }
- else if (t->orient_axis_ortho == 1) {
- if (t->center2d[0] > t->mouse.imval[0]) {
- dir_flip = !dir_flip;
- }
- }
- }
-
- /* Without this, half the gizmo handles move in the opposite direction. */
- if ((t->orient_axis_ortho + 1) % 3 != t->orient_axis) {
- dir_flip = !dir_flip;
- }
-
- if (dir_flip) {
- negate_v3(dir);
- }
-
- mul_mat3_m4_v3(t->viewmat, dir);
- if (normalize_v2(dir) == 0.0f) {
- dir[0] = 1.0f;
- }
- setCustomPointsFromDirection(t, &t->mouse, dir);
-
- initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
-}
-
-static void initShear(TransInfo *t)
-{
- t->mode = TFM_SHEAR;
- t->transform = applyShear;
- t->handleEvent = handleEventShear;
-
- if (t->orient_axis == t->orient_axis_ortho) {
- t->orient_axis = 2;
- t->orient_axis_ortho = 1;
- }
-
- initShear_mouseInputMode(t);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE; /* Don't think we have any unit here? */
-
- t->flag |= T_NO_CONSTRAINT;
-}
-
-static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event)
-{
- eRedrawFlag status = TREDRAW_NOTHING;
-
- if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
- /* Use custom.mode.data pointer to signal Shear direction */
- do {
- t->orient_axis_ortho = (t->orient_axis_ortho + 1) % 3;
- } while (t->orient_axis_ortho == t->orient_axis);
-
- initShear_mouseInputMode(t);
-
- status = TREDRAW_HARD;
- }
- else if (event->type == XKEY && event->val == KM_PRESS) {
- t->orient_axis_ortho = (t->orient_axis + 1) % 3;
- initShear_mouseInputMode(t);
-
- status = TREDRAW_HARD;
- }
- else if (event->type == YKEY && event->val == KM_PRESS) {
- t->orient_axis_ortho = (t->orient_axis + 2) % 3;
- initShear_mouseInputMode(t);
-
- status = TREDRAW_HARD;
- }
-
- return status;
-}
-
-static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
-{
- float vec[3];
- float smat[3][3], tmat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3];
- float value;
- int i;
- char str[UI_MAX_DRAW_STR];
- const bool is_local_center = transdata_check_local_center(t, t->around);
-
- value = t->values[0];
-
- snapGridIncrement(t, &value);
-
- applyNumInput(&t->num, &value);
-
- t->values_final[0] = value;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- BLI_snprintf(str, sizeof(str), TIP_("Shear: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- BLI_snprintf(str,
- sizeof(str),
- TIP_("Shear: %.3f %s (Press X or Y to set shear axis)"),
- value,
- t->proptext);
- }
-
- unit_m3(smat);
- smat[1][0] = value;
-
- copy_v3_v3(axismat_inv[0], t->orient_matrix[t->orient_axis_ortho]);
- copy_v3_v3(axismat_inv[2], t->orient_matrix[t->orient_axis]);
- cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]);
- invert_m3_m3(axismat, axismat_inv);
-
- mul_m3_series(totmat, axismat_inv, smat, axismat);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- const float *center, *co;
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (t->flag & T_EDIT) {
- mul_m3_series(tmat, td->smtx, totmat, td->mtx);
- }
- else {
- copy_m3_m3(tmat, totmat);
- }
-
- if (is_local_center) {
- center = td->center;
- co = td->loc;
- }
- else {
- center = tc->center_local;
- co = td->center;
- }
-
- sub_v3_v3v3(vec, co, center);
-
- mul_m3_v3(tmat, vec);
-
- add_v3_v3(vec, center);
- sub_v3_v3(vec, co);
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* grease pencil multiframe falloff */
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- if (gps != NULL) {
- mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
- }
- else {
- mul_v3_fl(vec, td->factor);
- }
- }
- else {
- mul_v3_fl(vec, td->factor);
- }
-
- add_v3_v3v3(td->loc, td->iloc, vec);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Resize) */
-
-/** \name Transform Resize
- * \{ */
-
-static void initResize(TransInfo *t)
-{
- t->mode = TFM_RESIZE;
- t->transform = applyResize;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
-
- t->flag |= T_NULL_ONE;
- t->num.val_flag[0] |= NUM_NULL_ONE;
- t->num.val_flag[1] |= NUM_NULL_ONE;
- t->num.val_flag[2] |= NUM_NULL_ONE;
- t->num.flag |= NUM_AFFECT_ALL;
- if ((t->flag & T_EDIT) == 0) {
- t->flag |= T_NO_ZERO;
-#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
- t->num.val_flag[1] |= NUM_NO_ZERO;
- t->num.val_flag[2] |= NUM_NO_ZERO;
-#endif
- }
-
- t->idx_max = 2;
- t->num.idx_max = 2;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
- t->num.unit_type[2] = B_UNIT_NONE;
-}
-
-static void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR])
-{
- char tvec[NUM_STR_REP_LEN * 3];
- size_t ofs = 0;
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
- }
-
- if (t->con.mode & CON_APPLY) {
- switch (t->num.idx_max) {
- case 0:
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- TIP_("Scale: %s%s %s"),
- &tvec[0],
- t->con.text,
- t->proptext);
- break;
- case 1:
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- TIP_("Scale: %s : %s%s %s"),
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- t->con.text,
- t->proptext);
- break;
- case 2:
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- TIP_("Scale: %s : %s : %s%s %s"),
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2],
- t->con.text,
- t->proptext);
- break;
- }
- }
- else {
- if (t->flag & T_2D_EDIT) {
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- TIP_("Scale X: %s Y: %s%s %s"),
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- t->con.text,
- t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- TIP_("Scale X: %s Y: %s Z: %s%s %s"),
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2],
- t->con.text,
- t->proptext);
- }
- }
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(
- str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
- }
-}
-
-/**
- * \a smat is reference matrix only.
- *
- * \note this is a tricky area, before making changes see: T29633, T42444
- */
-static void TransMat3ToSize(float mat[3][3], float smat[3][3], float size[3])
-{
- float rmat[3][3];
-
- mat3_to_rot_size(rmat, size, mat);
-
- /* first tried with dotproduct... but the sign flip is crucial */
- if (dot_v3v3(rmat[0], smat[0]) < 0.0f) {
- size[0] = -size[0];
- }
- if (dot_v3v3(rmat[1], smat[1]) < 0.0f) {
- size[1] = -size[1];
- }
- if (dot_v3v3(rmat[2], smat[2]) < 0.0f) {
- size[2] = -size[2];
- }
-}
-
-static void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3])
-{
- float tmat[3][3], smat[3][3], center[3];
- float vec[3];
-
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(smat, mat, td->mtx);
- mul_m3_m3m3(tmat, td->smtx, smat);
- }
- else {
- copy_m3_m3(tmat, mat);
- }
-
- if (t->con.applySize) {
- t->con.applySize(t, tc, td, tmat);
- }
-
- /* local constraint shouldn't alter center */
- if (transdata_check_local_center(t, t->around)) {
- copy_v3_v3(center, td->center);
- }
- else if (t->options & CTX_MOVIECLIP) {
- if (td->flag & TD_INDIVIDUAL_SCALE) {
- copy_v3_v3(center, td->center);
- }
- else {
- copy_v3_v3(center, tc->center_local);
- }
- }
- else {
- copy_v3_v3(center, tc->center_local);
- }
-
- /* Size checked needed since the 3D cursor only uses rotation fields. */
- if (td->ext && td->ext->size) {
- float fsize[3];
-
- if ((t->options & CTX_SCULPT) || t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) {
- float obsizemat[3][3];
- /* Reorient the size mat to fit the oriented object. */
- mul_m3_m3m3(obsizemat, tmat, td->axismtx);
- /* print_m3("obsizemat", obsizemat); */
- TransMat3ToSize(obsizemat, td->axismtx, fsize);
- /* print_v3("fsize", fsize); */
- }
- else {
- mat3_to_size(fsize, tmat);
- }
-
- protectedSizeBits(td->protectflag, fsize);
-
- if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */
- if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
- /* scale val and reset size */
- *td->val = td->ival * (1 + (fsize[0] - 1) * td->factor);
-
- td->ext->size[0] = td->ext->isize[0];
- td->ext->size[1] = td->ext->isize[1];
- td->ext->size[2] = td->ext->isize[2];
- }
- else {
- /* Reset val if SINGLESIZE but using a constraint */
- if (td->flag & TD_SINGLESIZE) {
- *td->val = td->ival;
- }
-
- td->ext->size[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor);
- td->ext->size[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor);
- td->ext->size[2] = td->ext->isize[2] * (1 + (fsize[2] - 1) * td->factor);
- }
- }
-
- constraintSizeLim(t, td);
- }
-
- /* For individual element center, Editmode need to use iloc */
- if (t->flag & T_POINTS) {
- sub_v3_v3v3(vec, td->iloc, center);
- }
- else {
- sub_v3_v3v3(vec, td->center, center);
- }
-
- mul_m3_v3(tmat, vec);
-
- add_v3_v3(vec, center);
- if (t->flag & T_POINTS) {
- sub_v3_v3(vec, td->iloc);
- }
- else {
- sub_v3_v3(vec, td->center);
- }
-
- /* grease pencil falloff */
- if (t->options & CTX_GPENCIL_STROKES) {
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
-
- /* scale stroke thickness */
- if (td->val) {
- snapGridIncrement(t, t->values_final);
- applyNumInput(&t->num, t->values_final);
-
- float ratio = t->values_final[0];
- *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff;
- CLAMP_MIN(*td->val, 0.001f);
- }
- }
- else {
- mul_v3_fl(vec, td->factor);
- }
-
- if (t->flag & (T_OBJECT | T_POSE)) {
- mul_m3_v3(td->smtx, vec);
- }
-
- protectedTransBits(td->protectflag, vec);
- if (td->loc) {
- add_v3_v3v3(td->loc, td->iloc, vec);
- }
-
- constraintTransLim(t, td);
-}
-
-static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
-{
- float mat[3][3];
- int i;
- char str[UI_MAX_DRAW_STR];
-
- if (t->flag & T_INPUT_IS_VALUES_FINAL) {
- copy_v3_v3(t->values_final, t->values);
- }
- else {
- float ratio = t->values[0];
-
- copy_v3_fl(t->values_final, ratio);
-
- snapGridIncrement(t, t->values_final);
-
- if (applyNumInput(&t->num, t->values_final)) {
- constraintNumInput(t, t->values_final);
- }
-
- applySnapping(t, t->values_final);
- }
-
- size_to_mat3(mat, t->values_final);
- if (t->con.mode & CON_APPLY) {
- t->con.applySize(t, NULL, NULL, mat);
-
- /* Only so we have re-usable value with redo. */
- float pvec[3] = {0.0f, 0.0f, 0.0f};
- int j = 0;
- for (i = 0; i < 3; i++) {
- if (!(t->con.mode & (CON_AXIS0 << i))) {
- t->values_final[i] = 1.0f;
- }
- else {
- pvec[j++] = t->values_final[i];
- }
- }
- headerResize(t, pvec, str);
- }
- else {
- headerResize(t, t->values_final, str);
- }
-
- copy_m3_m3(t->mat, mat); // used in gizmo
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- ElementResize(t, tc, td, mat);
- }
- }
-
- /* evil hack - redo resize if cliping needed */
- if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values_final, 1)) {
- size_to_mat3(mat, t->values_final);
-
- if (t->con.mode & CON_APPLY) {
- t->con.applySize(t, NULL, NULL, mat);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- ElementResize(t, tc, td, mat);
- }
-
- /* In proportional edit it can happen that */
- /* vertices in the radius of the brush end */
- /* outside the clipping area */
- /* XXX HACK - dg */
- if (t->flag & T_PROP_EDIT_ALL) {
- clipUVData(t);
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Skin) */
-
-/** \name Transform Skin
- * \{ */
-
-static void initSkinResize(TransInfo *t)
-{
- t->mode = TFM_SKIN_RESIZE;
- t->transform = applySkinResize;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
-
- t->flag |= T_NULL_ONE;
- t->num.val_flag[0] |= NUM_NULL_ONE;
- t->num.val_flag[1] |= NUM_NULL_ONE;
- t->num.val_flag[2] |= NUM_NULL_ONE;
- t->num.flag |= NUM_AFFECT_ALL;
- if ((t->flag & T_EDIT) == 0) {
- t->flag |= T_NO_ZERO;
-#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
- t->num.val_flag[1] |= NUM_NO_ZERO;
- t->num.val_flag[2] |= NUM_NO_ZERO;
-#endif
- }
-
- t->idx_max = 2;
- t->num.idx_max = 2;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
- t->num.unit_type[2] = B_UNIT_NONE;
-}
-
-static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
-{
- float mat[3][3];
- int i;
- char str[UI_MAX_DRAW_STR];
-
- if (t->flag & T_INPUT_IS_VALUES_FINAL) {
- copy_v3_v3(t->values_final, t->values);
- }
- else {
- copy_v3_fl(t->values_final, t->values[0]);
-
- snapGridIncrement(t, t->values_final);
-
- if (applyNumInput(&t->num, t->values_final)) {
- constraintNumInput(t, t->values_final);
- }
-
- applySnapping(t, t->values_final);
- }
-
- size_to_mat3(mat, t->values_final);
-
- headerResize(t, t->values_final, str);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float tmat[3][3], smat[3][3];
- float fsize[3];
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(smat, mat, td->mtx);
- mul_m3_m3m3(tmat, td->smtx, smat);
- }
- else {
- copy_m3_m3(tmat, mat);
- }
-
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, tmat);
- }
-
- mat3_to_size(fsize, tmat);
- td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor);
- td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (ToSphere) */
-
-/** \name Transform ToSphere
- * \{ */
-
-static void initToSphere(TransInfo *t)
-{
- int i;
-
- t->mode = TFM_TOSPHERE;
- t->transform = applyToSphere;
-
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->num.val_flag[0] |= NUM_NULL_ONE | NUM_NO_NEGATIVE;
- t->flag |= T_NO_CONSTRAINT;
-
- // Calculate average radius
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- t->val += len_v3v3(tc->center_local, td->iloc);
- }
- }
-
- t->val /= (float)t->data_len_all;
-}
-
-static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
-{
- float vec[3];
- float ratio, radius;
- int i;
- char str[UI_MAX_DRAW_STR];
-
- ratio = t->values[0];
-
- snapGridIncrement(t, &ratio);
-
- applyNumInput(&t->num, &ratio);
-
- CLAMP(ratio, 0.0f, 1.0f);
-
- t->values_final[0] = ratio;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- BLI_snprintf(str, sizeof(str), TIP_("To Sphere: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- BLI_snprintf(str, sizeof(str), TIP_("To Sphere: %.4f %s"), ratio, t->proptext);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float tratio;
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- sub_v3_v3v3(vec, td->iloc, tc->center_local);
-
- radius = normalize_v3(vec);
-
- tratio = ratio * td->factor;
-
- mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio);
-
- add_v3_v3v3(td->loc, tc->center_local, vec);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Rotation) */
-
-/** \name Transform Rotation
- * \{ */
-
-static void postInputRotation(TransInfo *t, float values[3])
-{
- float axis_final[3];
- copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
- if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
- t->con.applyRot(t, NULL, NULL, axis_final, values);
- }
-}
-
-static void initRotation(TransInfo *t)
-{
- t->mode = TFM_ROTATION;
- t->transform = applyRotation;
-
- setInputPostFct(&t->mouse, postInputRotation);
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
-
- copy_v3_fl(t->num.val_inc, t->snap[2]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
-
- if (t->flag & T_2D_EDIT) {
- t->flag |= T_NO_CONSTRAINT;
- }
-}
-
-/* Used by Transform Rotation and Transform Normal Rotation */
-static void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final)
-{
- size_t ofs = 0;
-
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- ofs += BLI_snprintf(
- str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- TIP_("Rot: %.2f%s %s"),
- RAD2DEGF(final),
- t->con.text,
- t->proptext);
- }
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(
- str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
- }
-}
-
-/**
- * Applies values of rotation to `td->loc` and `td->ext->quat`
- * based on a rotation matrix (mat) and a pivot (center).
- *
- * Protected axis and other transform settings are taken into account.
- */
-static void ElementRotation_ex(TransInfo *t,
- TransDataContainer *tc,
- TransData *td,
- const float mat[3][3],
- const float *center)
-{
- float vec[3], totmat[3][3], smat[3][3];
- float eul[3], fmat[3][3], quat[4];
-
- if (t->flag & T_POINTS) {
- mul_m3_m3m3(totmat, mat, td->mtx);
- mul_m3_m3m3(smat, td->smtx, totmat);
-
- /* apply gpencil falloff */
- if (t->options & CTX_GPENCIL_STROKES) {
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- float sx = smat[0][0];
- float sy = smat[1][1];
- float sz = smat[2][2];
-
- mul_m3_fl(smat, gps->runtime.multi_frame_falloff);
- /* fix scale */
- smat[0][0] = sx;
- smat[1][1] = sy;
- smat[2][2] = sz;
- }
-
- sub_v3_v3v3(vec, td->iloc, center);
- mul_m3_v3(smat, vec);
-
- add_v3_v3v3(td->loc, vec, center);
-
- sub_v3_v3v3(vec, td->loc, td->iloc);
- protectedTransBits(td->protectflag, vec);
- add_v3_v3v3(td->loc, td->iloc, vec);
-
- if (td->flag & TD_USEQUAT) {
- mul_m3_series(fmat, td->smtx, mat, td->mtx);
- mat3_to_quat(quat, fmat); // Actual transform
-
- if (td->ext->quat) {
- mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
-
- /* is there a reason not to have this here? -jahka */
- protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
- }
- }
- }
- /**
- * HACK WARNING
- *
- * This is some VERY ugly special case to deal with pose mode.
- *
- * The problem is that mtx and smtx include each bone orientation.
- *
- * That is needed to rotate each bone properly, HOWEVER, to calculate
- * the translation component, we only need the actual armature object's
- * matrix (and inverse). That is not all though. Once the proper translation
- * has been computed, it has to be converted back into the bone's space.
- */
- else if (t->flag & T_POSE) {
- // Extract and invert armature object matrix
-
- if ((td->flag & TD_NO_LOC) == 0) {
- sub_v3_v3v3(vec, td->center, center);
-
- mul_m3_v3(tc->mat3, vec); // To Global space
- mul_m3_v3(mat, vec); // Applying rotation
- mul_m3_v3(tc->imat3, vec); // To Local space
-
- add_v3_v3(vec, center);
- /* vec now is the location where the object has to be */
-
- sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location
-
- /* special exception, see TD_PBONE_LOCAL_MTX definition comments */
- if (td->flag & TD_PBONE_LOCAL_MTX_P) {
- /* do nothing */
- }
- else if (td->flag & TD_PBONE_LOCAL_MTX_C) {
- mul_m3_v3(tc->mat3, vec); // To Global space
- mul_m3_v3(td->ext->l_smtx, vec); // To Pose space (Local Location)
- }
- else {
- mul_m3_v3(tc->mat3, vec); // To Global space
- mul_m3_v3(td->smtx, vec); // To Pose space
- }
-
- protectedTransBits(td->protectflag, vec);
-
- add_v3_v3v3(td->loc, td->iloc, vec);
-
- constraintTransLim(t, td);
- }
-
- /* rotation */
- /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same,
- * and ElementRotation() might be called in Translation context (with align snapping),
- * we need to be sure to actually use the *rotation* matrix here...
- * So no other way than storing it in some dedicated members of td->ext! */
- if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */
- /* euler or quaternion/axis-angle? */
- if (td->ext->rotOrder == ROT_MODE_QUAT) {
- mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
-
- mat3_to_quat(quat, fmat); /* Actual transform */
-
- mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
- /* this function works on end result */
- protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- /* calculate effect based on quats */
- float iquat[4], tquat[4];
-
- axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
-
- mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
- mat3_to_quat(quat, fmat); /* Actual transform */
- mul_qt_qtqt(tquat, quat, iquat);
-
- quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
-
- /* this function works on end result */
- protectedAxisAngleBits(td->protectflag,
- td->ext->rotAxis,
- td->ext->rotAngle,
- td->ext->irotAxis,
- td->ext->irotAngle);
- }
- else {
- float eulmat[3][3];
-
- mul_m3_m3m3(totmat, mat, td->ext->r_mtx);
- mul_m3_m3m3(smat, td->ext->r_smtx, totmat);
-
- /* calculate the total rotatation in eulers */
- copy_v3_v3(eul, td->ext->irot);
- eulO_to_mat3(eulmat, eul, td->ext->rotOrder);
-
- /* mat = transform, obmat = bone rotation */
- mul_m3_m3m3(fmat, smat, eulmat);
-
- mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
-
- /* and apply (to end result only) */
- protectedRotateBits(td->protectflag, eul, td->ext->irot);
- copy_v3_v3(td->ext->rot, eul);
- }
-
- constraintRotLim(t, td);
- }
- }
- else {
- if ((td->flag & TD_NO_LOC) == 0) {
- /* translation */
- sub_v3_v3v3(vec, td->center, center);
- mul_m3_v3(mat, vec);
- add_v3_v3(vec, center);
- /* vec now is the location where the object has to be */
- sub_v3_v3(vec, td->center);
- mul_m3_v3(td->smtx, vec);
-
- protectedTransBits(td->protectflag, vec);
-
- add_v3_v3v3(td->loc, td->iloc, vec);
- }
-
- constraintTransLim(t, td);
-
- /* rotation */
- if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself
- /* euler or quaternion? */
- if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
- /* can be called for texture space translate for example, then opt out */
- if (td->ext->quat) {
- mul_m3_series(fmat, td->smtx, mat, td->mtx);
- mat3_to_quat(quat, fmat); // Actual transform
-
- mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
- /* this function works on end result */
- protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
- }
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- /* calculate effect based on quats */
- float iquat[4], tquat[4];
-
- axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
-
- mul_m3_series(fmat, td->smtx, mat, td->mtx);
- mat3_to_quat(quat, fmat); // Actual transform
- mul_qt_qtqt(tquat, quat, iquat);
-
- quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
-
- /* this function works on end result */
- protectedAxisAngleBits(td->protectflag,
- td->ext->rotAxis,
- td->ext->rotAngle,
- td->ext->irotAxis,
- td->ext->irotAngle);
- }
- else {
- float obmat[3][3];
-
- mul_m3_m3m3(totmat, mat, td->mtx);
- mul_m3_m3m3(smat, td->smtx, totmat);
-
- /* calculate the total rotatation in eulers */
- add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */
- eulO_to_mat3(obmat, eul, td->ext->rotOrder);
- /* mat = transform, obmat = object rotation */
- mul_m3_m3m3(fmat, smat, obmat);
-
- mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
-
- /* correct back for delta rot */
- sub_v3_v3v3(eul, eul, td->ext->drot);
-
- /* and apply */
- protectedRotateBits(td->protectflag, eul, td->ext->irot);
- copy_v3_v3(td->ext->rot, eul);
- }
-
- constraintRotLim(t, td);
- }
- }
-}
-
-static void ElementRotation(
- TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around)
-{
- const float *center;
-
- /* local constraint shouldn't alter center */
- if (transdata_check_local_center(t, around)) {
- center = td->center;
- }
- else {
- center = tc->center_local;
- }
-
- ElementRotation_ex(t, tc, td, mat, center);
-}
-
-static float large_rotation_limit(float angle)
-{
- /* Limit rotation to 1001 turns max
- * (otherwise iterative handling of 'large' rotations would become too slow). */
- const float angle_max = (float)(M_PI * 2000.0);
- if (fabsf(angle) > angle_max) {
- const float angle_sign = angle < 0.0f ? -1.0f : 1.0f;
- angle = angle_sign * (fmodf(fabsf(angle), (float)(M_PI * 2.0)) + angle_max);
- }
- return angle;
-}
-
-static void applyRotationValue(TransInfo *t,
- float angle,
- float axis[3],
- const bool is_large_rotation)
-{
- float mat[3][3];
- int i;
-
- const float angle_sign = angle < 0.0f ? -1.0f : 1.0f;
- /* We cannot use something too close to 180°, or 'continuous' rotation may fail
- * due to computing error... */
- const float angle_step = angle_sign * (float)(0.9 * M_PI);
-
- if (is_large_rotation) {
- /* Just in case, calling code should have already done that in practice
- * (for UI feedback reasons). */
- angle = large_rotation_limit(angle);
- }
-
- axis_angle_normalized_to_mat3(mat, axis, angle);
- /* Counter for needed updates (when we need to update to non-default matrix,
- * we also need another update on next iteration to go back to default matrix,
- * hence the '2' value used here, instead of a mere boolean). */
- short do_update_matrix = 0;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- float angle_final = angle;
- if (t->con.applyRot) {
- t->con.applyRot(t, tc, td, axis, NULL);
- angle_final = angle * td->factor;
- /* Even though final angle might be identical to orig value,
- * we have to update the rotation matrix in that case... */
- do_update_matrix = 2;
- }
- else if (t->flag & T_PROP_EDIT) {
- angle_final = angle * td->factor;
- }
-
- /* Rotation is very likely to be above 180°, we need to do rotation by steps.
- * Note that this is only needed when doing 'absolute' rotation
- * (i.e. from initial rotation again, typically when using numinput).
- * regular incremental rotation (from mouse/widget/...) will be called often enough,
- * hence steps are small enough to be properly handled without that complicated trick.
- * Note that we can only do that kind of stepped rotation if we have initial rotation values
- * (and access to some actual rotation value storage).
- * Otherwise, just assume it's useless (e.g. in case of mesh/UV/etc. editing).
- * Also need to be in Euler rotation mode, the others never allow more than one turn anyway.
- */
- if (is_large_rotation && td->ext != NULL && td->ext->rotOrder == ROT_MODE_EUL) {
- copy_v3_v3(td->ext->rot, td->ext->irot);
- for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final);
- angle_progress += angle_step) {
- axis_angle_normalized_to_mat3(mat, axis, angle_progress);
- ElementRotation(t, tc, td, mat, t->around);
- }
- do_update_matrix = 2;
- }
- else if (angle_final != angle) {
- do_update_matrix = 2;
- }
-
- if (do_update_matrix > 0) {
- axis_angle_normalized_to_mat3(mat, axis, angle_final);
- do_update_matrix--;
- }
-
- ElementRotation(t, tc, td, mat, t->around);
- }
- }
-}
-
-static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
-{
- char str[UI_MAX_DRAW_STR];
-
- float final;
-
- final = t->values[0];
-
- snapGridIncrement(t, &final);
-
- float axis_final[3];
- copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
-
- if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
- t->con.applyRot(t, NULL, NULL, axis_final, NULL);
- }
-
- applySnapping(t, &final);
-
- if (applyNumInput(&t->num, &final)) {
- /* We have to limit the amount of turns to a reasonable number here,
- * to avoid things getting *very* slow, see how applyRotationValue() handles those... */
- final = large_rotation_limit(final);
- }
-
- t->values_final[0] = final;
-
- headerRotation(t, str, final);
-
- const bool is_large_rotation = hasNumInput(&t->num);
- applyRotationValue(t, final, axis_final, is_large_rotation);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Rotation - Trackball) */
-
-/** \name Transform Rotation - Trackball
- * \{ */
-
-static void initTrackball(TransInfo *t)
-{
- t->mode = TFM_TRACKBALL;
- t->transform = applyTrackball;
-
- initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL);
-
- t->idx_max = 1;
- t->num.idx_max = 1;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
-
- copy_v3_fl(t->num.val_inc, t->snap[2]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
- t->num.unit_type[1] = B_UNIT_ROTATION;
-
- t->flag |= T_NO_CONSTRAINT;
-}
-
-static void applyTrackballValue(TransInfo *t,
- const float axis1[3],
- const float axis2[3],
- const float angles[2])
-{
- float mat[3][3];
- float axis[3];
- float angle;
- int i;
-
- mul_v3_v3fl(axis, axis1, angles[0]);
- madd_v3_v3fl(axis, axis2, angles[1]);
- angle = normalize_v3(axis);
- axis_angle_normalized_to_mat3(mat, axis, angle);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (t->flag & T_PROP_EDIT) {
- axis_angle_normalized_to_mat3(mat, axis, td->factor * angle);
- }
-
- ElementRotation(t, tc, td, mat, t->around);
- }
- }
-}
-
-static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
-{
- char str[UI_MAX_DRAW_STR];
- size_t ofs = 0;
- float axis1[3], axis2[3];
-#if 0 /* UNUSED */
- float mat[3][3], totmat[3][3], smat[3][3];
-#endif
- float phi[2];
-
- copy_v3_v3(axis1, t->persinv[0]);
- copy_v3_v3(axis2, t->persinv[1]);
- normalize_v3(axis1);
- normalize_v3(axis2);
-
- copy_v2_v2(phi, t->values);
-
- snapGridIncrement(t, phi);
-
- applyNumInput(&t->num, phi);
-
- copy_v2_v2(t->values_final, phi);
-
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN * 2];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- ofs += BLI_snprintf(str + ofs,
- sizeof(str) - ofs,
- TIP_("Trackball: %s %s %s"),
- &c[0],
- &c[NUM_STR_REP_LEN],
- t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs,
- sizeof(str) - ofs,
- TIP_("Trackball: %.2f %.2f %s"),
- RAD2DEGF(phi[0]),
- RAD2DEGF(phi[1]),
- t->proptext);
- }
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(
- str + ofs, sizeof(str) - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
- }
-
-#if 0 /* UNUSED */
- axis_angle_normalized_to_mat3(smat, axis1, phi[0]);
- axis_angle_normalized_to_mat3(totmat, axis2, phi[1]);
-
- mul_m3_m3m3(mat, smat, totmat);
-
- // TRANSFORM_FIX_ME
- //copy_m3_m3(t->mat, mat); // used in gizmo
-#endif
-
- applyTrackballValue(t, axis1, axis2, phi);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Normal Rotation) */
-
-/** \name Transform Normal Rotation
- * \{ */
-
-static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm)
-{
- BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
- // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
-
- tc->custom.mode.data = lnors_ed_arr;
- tc->custom.mode.free_cb = freeCustomNormalArray;
-}
-
-void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
-{
- BMLoopNorEditDataArray *lnors_ed_arr = custom_data->data;
-
- if (t->state == TRANS_CANCEL) {
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
-
- /* Restore custom loop normal on cancel */
- 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], lnor_ed->niloc, lnor_ed->clnors_data);
- }
- }
-
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
-
- tc->custom.mode.data = NULL;
- tc->custom.mode.free_cb = NULL;
-}
-
-static void initNormalRotation(TransInfo *t)
-{
- t->mode = TFM_NORMAL_ROTATION;
- t->transform = applyNormalRotation;
-
- setInputPostFct(&t->mouse, postInputRotation);
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
-
- copy_v3_fl(t->num.val_inc, t->snap[2]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
-
- BKE_editmesh_ensure_autosmooth(em, tc->obedit->data);
- BKE_editmesh_lnorspace_update(em, tc->obedit->data);
-
- storeCustomLNorValue(tc, bm);
- }
-}
-
-/* Works by getting custom normal from clnor_data, transform, then store */
-static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2]))
-{
- char str[UI_MAX_DRAW_STR];
-
- float axis_final[3];
- copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
-
- if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
- t->con.applyRot(t, NULL, NULL, axis_final, NULL);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
-
- BMLoopNorEditDataArray *lnors_ed_arr = tc->custom.mode.data;
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
-
- float axis[3];
- float mat[3][3];
- float angle = t->values[0];
- copy_v3_v3(axis, axis_final);
-
- snapGridIncrement(t, &angle);
-
- applySnapping(t, &angle);
-
- applyNumInput(&t->num, &angle);
-
- headerRotation(t, str, angle);
-
- axis_angle_normalized_to_mat3(mat, axis, angle);
-
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- mul_v3_m3v3(lnor_ed->nloc, mat, 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);
- }
-
- t->values_final[0] = angle;
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Translation) */
-
-static void initSnapSpatial(TransInfo *t, float r_snap[3])
-{
- if (t->spacetype == SPACE_VIEW3D) {
- RegionView3D *rv3d = t->ar->regiondata;
-
- if (rv3d) {
- View3D *v3d = t->sa->spacedata.first;
- r_snap[0] = 0.0f;
- r_snap[1] = ED_view3d_grid_view_scale(t->scene, v3d, rv3d, NULL) * 1.0f;
- r_snap[2] = r_snap[1] * 0.1f;
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- r_snap[0] = 0.0f;
- r_snap[1] = 0.0625f;
- r_snap[2] = 0.03125f;
- }
- else if (t->spacetype == SPACE_CLIP) {
- r_snap[0] = 0.0f;
- r_snap[1] = 0.125f;
- r_snap[2] = 0.0625f;
- }
- else if (t->spacetype == SPACE_NODE) {
- r_snap[0] = 0.0f;
- r_snap[1] = r_snap[2] = ED_node_grid_size();
- }
- else if (t->spacetype == SPACE_GRAPH) {
- r_snap[0] = 0.0f;
- r_snap[1] = 1.0;
- r_snap[2] = 0.1f;
- }
- else {
- r_snap[0] = 0.0f;
- r_snap[1] = r_snap[2] = 1.0f;
- }
-}
-
-/** \name Transform Translation
- * \{ */
-
-static void initTranslation(TransInfo *t)
-{
- if (t->spacetype == SPACE_ACTION) {
- /* this space uses time translate */
- BKE_report(t->reports,
- RPT_ERROR,
- "Use 'Time_Translate' transform mode instead of 'Translation' mode "
- "for translating keyframes in Dope Sheet Editor");
- t->state = TRANS_CANCEL;
- }
-
- t->mode = TFM_TRANSLATION;
- t->transform = applyTranslation;
-
- initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
-
- t->idx_max = (t->flag & T_2D_EDIT) ? 1 : 2;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
-
- copy_v3_v3(t->snap, t->snap_spatial);
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- if (t->spacetype == SPACE_VIEW3D) {
- /* Handling units makes only sense in 3Dview... See T38877. */
- t->num.unit_type[0] = B_UNIT_LENGTH;
- t->num.unit_type[1] = B_UNIT_LENGTH;
- t->num.unit_type[2] = B_UNIT_LENGTH;
- }
- else {
- /* SPACE_GRAPH, SPACE_ACTION, etc. could use some time units, when we have them... */
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
- t->num.unit_type[2] = B_UNIT_NONE;
- }
-}
-
-static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR])
-{
- size_t ofs = 0;
- char tvec[NUM_STR_REP_LEN * 3];
- char distvec[NUM_STR_REP_LEN];
- char autoik[NUM_STR_REP_LEN];
- float dist;
-
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- dist = len_v3(t->num.val);
- }
- else {
- float dvec[3];
-
- copy_v3_v3(dvec, vec);
- applyAspectRatio(t, dvec);
-
- dist = len_v3(vec);
- if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
- int i;
-
- for (i = 0; i < 3; i++) {
- bUnit_AsString2(&tvec[NUM_STR_REP_LEN * i],
- NUM_STR_REP_LEN,
- dvec[i] * t->scene->unit.scale_length,
- 4,
- B_UNIT_LENGTH,
- &t->scene->unit,
- true);
- }
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]);
- }
- }
-
- if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
- bUnit_AsString2(distvec,
- sizeof(distvec),
- dist * t->scene->unit.scale_length,
- 4,
- B_UNIT_LENGTH,
- &t->scene->unit,
- false);
- }
- else if (dist > 1e10f || dist < -1e10f) {
- /* prevent string buffer overflow */
- BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist);
- }
- else {
- BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist);
- }
-
- if (t->flag & T_AUTOIK) {
- short chainlen = t->settings->autoik_chainlen;
-
- if (chainlen) {
- BLI_snprintf(autoik, NUM_STR_REP_LEN, TIP_("AutoIK-Len: %d"), chainlen);
- }
- else {
- autoik[0] = '\0';
- }
- }
- else {
- autoik[0] = '\0';
- }
-
- if (t->con.mode & CON_APPLY) {
- switch (t->num.idx_max) {
- case 0:
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- "D: %s (%s)%s %s %s",
- &tvec[0],
- distvec,
- t->con.text,
- t->proptext,
- autoik);
- break;
- case 1:
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- "D: %s D: %s (%s)%s %s %s",
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- distvec,
- t->con.text,
- t->proptext,
- autoik);
- break;
- case 2:
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- "D: %s D: %s D: %s (%s)%s %s %s",
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2],
- distvec,
- t->con.text,
- t->proptext,
- autoik);
- break;
- }
- }
- else {
- if (t->flag & T_2D_EDIT) {
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- "Dx: %s Dy: %s (%s)%s %s",
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- distvec,
- t->con.text,
- t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- "Dx: %s Dy: %s Dz: %s (%s)%s %s %s",
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2],
- distvec,
- t->con.text,
- t->proptext,
- autoik);
- }
- }
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(
- str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
- }
-
- if (t->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
-
- if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
- const char *str_old = BLI_strdup(str);
- const char *str_dir = (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) ? TIP_("right") :
- TIP_("left");
- char str_km[64];
-
- WM_modalkeymap_items_to_string(
- t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, str_km, sizeof(str_km));
-
- ofs += BLI_snprintf(str,
- UI_MAX_DRAW_STR,
- TIP_("Auto-offset set to %s - press %s to toggle direction | %s"),
- str_dir,
- str_km,
- str_old);
-
- MEM_freeN((void *)str_old);
- }
- }
-}
-
-static void applyTranslationValue(TransInfo *t, const float vec[3])
-{
- const bool apply_snap_align_rotation = usingSnappingNormal(
- t); // && (t->tsnap.status & POINT_INIT);
- float tvec[3];
-
- /* The ideal would be "apply_snap_align_rotation" only when a snap point is found
- * so, maybe inside this function is not the best place to apply this rotation.
- * but you need "handle snapping rotation before doing the translation" (really?) */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- float pivot[3];
- if (apply_snap_align_rotation) {
- copy_v3_v3(pivot, t->tsnap.snapTarget);
- /* The pivot has to be in local-space (see T49494) */
- if (tc->use_local_mat) {
- mul_m4_v3(tc->imat, pivot);
- }
- }
-
- TransData *td = tc->data;
- for (int i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- float rotate_offset[3] = {0};
- bool use_rotate_offset = false;
-
- /* handle snapping rotation before doing the translation */
- if (apply_snap_align_rotation) {
- float mat[3][3];
-
- if (validSnappingNormal(t)) {
- const float *original_normal;
-
- /* In pose mode, we want to align normals with Y axis of bones... */
- if (t->flag & T_POSE) {
- original_normal = td->axismtx[1];
- }
- else {
- original_normal = td->axismtx[2];
- }
-
- rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal);
- }
- else {
- unit_m3(mat);
- }
-
- ElementRotation_ex(t, tc, td, mat, pivot);
-
- if (td->loc) {
- use_rotate_offset = true;
- sub_v3_v3v3(rotate_offset, td->loc, td->iloc);
- }
- }
-
- if (t->con.applyVec) {
- float pvec[3];
- t->con.applyVec(t, tc, td, vec, tvec, pvec);
- }
- else {
- copy_v3_v3(tvec, vec);
- }
-
- mul_m3_v3(td->smtx, tvec);
-
- if (use_rotate_offset) {
- add_v3_v3(tvec, rotate_offset);
- }
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* grease pencil multiframe falloff */
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- if (gps != NULL) {
- mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff);
- }
- else {
- mul_v3_fl(tvec, td->factor);
- }
- }
- else {
- /* proportional editing falloff */
- mul_v3_fl(tvec, td->factor);
- }
-
- protectedTransBits(td->protectflag, tvec);
-
- if (td->loc) {
- add_v3_v3v3(td->loc, td->iloc, tvec);
- }
-
- constraintTransLim(t, td);
- }
- }
-}
-
-static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
-{
- char str[UI_MAX_DRAW_STR];
- float values_final[3];
-
- if (t->flag & T_INPUT_IS_VALUES_FINAL) {
- copy_v3_v3(t->values_final, t->values);
- }
- else {
- copy_v3_v3(t->values_final, t->values);
- if ((t->con.mode & CON_APPLY) == 0) {
- snapGridIncrement(t, t->values_final);
- }
-
- if (applyNumInput(&t->num, t->values_final)) {
- removeAspectRatio(t, t->values_final);
- }
-
- applySnapping(t, t->values_final);
- }
- copy_v3_v3(values_final, t->values_final);
-
- if (t->con.mode & CON_APPLY) {
- float pvec[3] = {0.0f, 0.0f, 0.0f};
- t->con.applyVec(t, NULL, NULL, t->values_final, values_final, pvec);
- headerTranslation(t, pvec, str);
-
- /* only so we have re-usable value with redo, see T46741. */
- mul_v3_m3v3(t->values_final, t->con.imtx, values_final);
- }
- else {
- headerTranslation(t, t->values_final, str);
- copy_v3_v3(values_final, t->values_final);
- }
-
- /* don't use 't->values' now on */
-
- applyTranslationValue(t, values_final);
-
- /* evil hack - redo translation if clipping needed */
- if (t->flag & T_CLIP_UV && clipUVTransform(t, values_final, 0)) {
- applyTranslationValue(t, values_final);
-
- /* In proportional edit it can happen that */
- /* vertices in the radius of the brush end */
- /* outside the clipping area */
- /* XXX HACK - dg */
- if (t->flag & T_PROP_EDIT_ALL) {
- clipUVData(t);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Shrink-Fatten) */
-
-/** \name Transform Shrink-Fatten
- * \{ */
-
-static void initShrinkFatten(TransInfo *t)
-{
- // If not in mesh edit mode, fallback to Resize
- if ((t->flag & T_EDIT) == 0 || (t->obedit_type != OB_MESH)) {
- initResize(t);
- }
- else {
- t->mode = TFM_SHRINKFATTEN;
- t->transform = applyShrinkFatten;
-
- initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 1.0f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_LENGTH;
-
- t->flag |= T_NO_CONSTRAINT;
- }
-}
-
-static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
-{
- float distance;
- int i;
- char str[UI_MAX_DRAW_STR];
- size_t ofs = 0;
-
- distance = -t->values[0];
-
- snapGridIncrement(t, &distance);
-
- applyNumInput(&t->num, &distance);
-
- t->values_final[0] = -distance;
-
- /* header print for NumInput */
- ofs += BLI_strncpy_rlen(str + ofs, TIP_("Shrink/Fatten:"), sizeof(str) - ofs);
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", c);
- }
- else {
- /* default header print */
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %.4f", distance);
- }
-
- if (t->proptext[0]) {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", t->proptext);
- }
- ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs);
-
- if (t->keymap) {
- wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE);
- if (kmi) {
- ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs);
- }
- }
- BLI_snprintf(str + ofs,
- sizeof(str) - ofs,
- TIP_(" or Alt) Even Thickness %s"),
- WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
- /* done with header string */
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float tdistance; /* temp dist */
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- /* get the final offset */
- tdistance = distance * td->factor;
- if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) {
- tdistance *= td->ext->isize[0]; /* shell factor */
- }
-
- madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Tilt) */
-
-/** \name Transform Tilt
- * \{ */
-
-static void initTilt(TransInfo *t)
-{
- t->mode = TFM_TILT;
- t->transform = applyTilt;
-
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
-
- copy_v3_fl(t->num.val_inc, t->snap[2]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
-
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
-}
-
-static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
-{
- int i;
- char str[UI_MAX_DRAW_STR];
-
- float final;
-
- final = t->values[0];
-
- snapGridIncrement(t, &final);
-
- applyNumInput(&t->num, &final);
-
- t->values_final[0] = final;
-
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- BLI_snprintf(str, sizeof(str), TIP_("Tilt: %s° %s"), &c[0], t->proptext);
-
- /* XXX For some reason, this seems needed for this op, else RNA prop is not updated... :/ */
- t->values_final[0] = final;
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->val) {
- *td->val = td->ival + final * td->factor;
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Curve Shrink/Fatten) */
-
-/** \name Transform Curve Shrink/Fatten
- * \{ */
-
-static void initCurveShrinkFatten(TransInfo *t)
-{
- t->mode = TFM_CURVE_SHRINKFATTEN;
- t->transform = applyCurveShrinkFatten;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->flag |= T_NO_ZERO;
-#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
-#endif
-
- t->flag |= T_NO_CONSTRAINT;
-}
-
-static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
-{
- float ratio;
- int i;
- char str[UI_MAX_DRAW_STR];
-
- ratio = t->values[0];
-
- snapGridIncrement(t, &ratio);
-
- applyNumInput(&t->num, &ratio);
-
- t->values_final[0] = ratio;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), TIP_("Shrink/Fatten: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Shrink/Fatten: %3f"), ratio);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->val) {
- *td->val = td->ival * ratio;
- /* apply PET */
- *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
- if (*td->val <= 0.0f) {
- *td->val = 0.001f;
- }
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Mask Shrink/Fatten) */
-
-/** \name Transform Mask Shrink/Fatten
- * \{ */
-
-static void initMaskShrinkFatten(TransInfo *t)
-{
- t->mode = TFM_MASK_SHRINKFATTEN;
- t->transform = applyMaskShrinkFatten;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->flag |= T_NO_ZERO;
-#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
-#endif
-
- t->flag |= T_NO_CONSTRAINT;
-}
-
-static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
-{
- float ratio;
- int i;
- bool initial_feather = false;
- char str[UI_MAX_DRAW_STR];
-
- ratio = t->values[0];
-
- snapGridIncrement(t, &ratio);
-
- applyNumInput(&t->num, &ratio);
-
- t->values_final[0] = ratio;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), TIP_("Feather Shrink/Fatten: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Feather Shrink/Fatten: %3f"), ratio);
- }
-
- /* detect if no points have feather yet */
- if (ratio > 1.0f) {
- initial_feather = true;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->ival >= 0.001f) {
- initial_feather = false;
- }
- }
- }
- }
-
- /* apply shrink/fatten */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (td = tc->data, i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->val) {
- if (initial_feather) {
- *td->val = td->ival + (ratio - 1.0f) * 0.01f;
- }
- else {
- *td->val = td->ival * ratio;
- }
-
- /* apply PET */
- *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
- if (*td->val <= 0.0f) {
- *td->val = 0.001f;
- }
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (GPencil Shrink/Fatten) */
-
-/** \name Transform GPencil Strokes Shrink/Fatten
- * \{ */
-
-static void initGPShrinkFatten(TransInfo *t)
-{
- t->mode = TFM_GPENCIL_SHRINKFATTEN;
- t->transform = applyGPShrinkFatten;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->flag |= T_NO_ZERO;
-#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
-#endif
-
- t->flag |= T_NO_CONSTRAINT;
-}
-
-static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
-{
- float ratio;
- int i;
- char str[UI_MAX_DRAW_STR];
-
- ratio = t->values[0];
-
- snapGridIncrement(t, &ratio);
-
- applyNumInput(&t->num, &ratio);
-
- t->values_final[0] = ratio;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), TIP_("Shrink/Fatten: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Shrink/Fatten: %3f"), ratio);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->val) {
- *td->val = td->ival * ratio;
- /* apply PET */
- *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
- if (*td->val <= 0.0f) {
- *td->val = 0.001f;
- }
- }
- }
- }
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (GPencil Opacity) */
-
-/** \name Transform GPencil Strokes Opacity
- * \{ */
-
-static void initGPOpacity(TransInfo *t)
-{
- t->mode = TFM_GPENCIL_OPACITY;
- t->transform = applyGPOpacity;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->flag |= T_NO_ZERO;
-#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
-#endif
-
- t->flag |= T_NO_CONSTRAINT;
-}
-
-static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2]))
-{
- float ratio;
- int i;
- char str[UI_MAX_DRAW_STR];
-
- ratio = t->values[0];
-
- snapGridIncrement(t, &ratio);
-
- applyNumInput(&t->num, &ratio);
-
- t->values_final[0] = ratio;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), TIP_("Opacity: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Opacity: %3f"), ratio);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->val) {
- *td->val = td->ival * ratio;
- /* apply PET */
- *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
- CLAMP(*td->val, 0.0f, 1.0f);
- }
- }
- }
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Push/Pull) */
-
-/** \name Transform Push/Pull
- * \{ */
-
-static void initPushPull(TransInfo *t)
-{
- t->mode = TFM_PUSHPULL;
- t->transform = applyPushPull;
-
- initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 1.0f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_LENGTH;
-}
-
-static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
-{
- float vec[3], axis_global[3];
- float distance;
- int i;
- char str[UI_MAX_DRAW_STR];
-
- distance = t->values[0];
-
- snapGridIncrement(t, &distance);
-
- applyNumInput(&t->num, &distance);
-
- t->values_final[0] = distance;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- BLI_snprintf(str, sizeof(str), TIP_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext);
- }
- else {
- /* default header print */
- BLI_snprintf(
- str, sizeof(str), TIP_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext);
- }
-
- if (t->con.applyRot && t->con.mode & CON_APPLY) {
- t->con.applyRot(t, NULL, NULL, axis_global, NULL);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- sub_v3_v3v3(vec, tc->center_local, td->center);
- if (t->con.applyRot && t->con.mode & CON_APPLY) {
- float axis[3];
- copy_v3_v3(axis, axis_global);
- t->con.applyRot(t, tc, td, axis, NULL);
-
- mul_m3_v3(td->smtx, axis);
- if (isLockConstraint(t)) {
- float dvec[3];
- project_v3_v3v3(dvec, vec, axis);
- sub_v3_v3(vec, dvec);
- }
- else {
- project_v3_v3v3(vec, vec, axis);
- }
- }
- normalize_v3_length(vec, distance * td->factor);
-
- add_v3_v3v3(td->loc, td->iloc, vec);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Bevel Weight) */
-
-/** \name Transform Bevel Weight
- * \{ */
-
-static void initBevelWeight(TransInfo *t)
-{
- t->mode = TFM_BWEIGHT;
- t->transform = applyBevelWeight;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
-}
-
-static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
-{
- float weight;
- int i;
- char str[UI_MAX_DRAW_STR];
-
- weight = t->values[0];
-
- CLAMP_MAX(weight, 1.0f);
-
- snapGridIncrement(t, &weight);
-
- applyNumInput(&t->num, &weight);
-
- t->values_final[0] = weight;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- if (weight >= 0.0f) {
- BLI_snprintf(str, sizeof(str), TIP_("Bevel Weight: +%s %s"), c, t->proptext);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Bevel Weight: %s %s"), c, t->proptext);
- }
- }
- else {
- /* default header print */
- if (weight >= 0.0f) {
- BLI_snprintf(str, sizeof(str), TIP_("Bevel Weight: +%.3f %s"), weight, t->proptext);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Bevel Weight: %.3f %s"), weight, t->proptext);
- }
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->val) {
- *td->val = td->ival + weight * td->factor;
- if (*td->val < 0.0f) {
- *td->val = 0.0f;
- }
- if (*td->val > 1.0f) {
- *td->val = 1.0f;
- }
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Crease) */
-
-/** \name Transform Crease
- * \{ */
-
-static void initCrease(TransInfo *t)
-{
- t->mode = TFM_CREASE;
- t->transform = applyCrease;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
-}
-
-static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
-{
- float crease;
- int i;
- char str[UI_MAX_DRAW_STR];
-
- crease = t->values[0];
-
- CLAMP_MAX(crease, 1.0f);
-
- snapGridIncrement(t, &crease);
-
- applyNumInput(&t->num, &crease);
-
- t->values_final[0] = crease;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- if (crease >= 0.0f) {
- BLI_snprintf(str, sizeof(str), TIP_("Crease: +%s %s"), c, t->proptext);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Crease: %s %s"), c, t->proptext);
- }
- }
- else {
- /* default header print */
- if (crease >= 0.0f) {
- BLI_snprintf(str, sizeof(str), TIP_("Crease: +%.3f %s"), crease, t->proptext);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Crease: %.3f %s"), crease, t->proptext);
- }
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->val) {
- *td->val = td->ival + crease * td->factor;
- if (*td->val < 0.0f) {
- *td->val = 0.0f;
- }
- if (*td->val > 1.0f) {
- *td->val = 1.0f;
- }
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (EditBone (B-bone) width scaling) */
-
-/** \name Transform B-bone width scaling
- * \{ */
-
-static void initBoneSize(TransInfo *t)
-{
- t->mode = TFM_BONESIZE;
- t->transform = applyBoneSize;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
-
- t->idx_max = 2;
- t->num.idx_max = 2;
- t->num.val_flag[0] |= NUM_NULL_ONE;
- t->num.val_flag[1] |= NUM_NULL_ONE;
- t->num.val_flag[2] |= NUM_NULL_ONE;
- t->num.flag |= NUM_AFFECT_ALL;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
- t->num.unit_type[2] = B_UNIT_NONE;
-}
-
-static void headerBoneSize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR])
-{
- char tvec[NUM_STR_REP_LEN * 3];
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
- }
-
- /* hmm... perhaps the y-axis values don't need to be shown? */
- if (t->con.mode & CON_APPLY) {
- if (t->num.idx_max == 0) {
- BLI_snprintf(
- str, UI_MAX_DRAW_STR, TIP_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext);
- }
- else {
- BLI_snprintf(str,
- UI_MAX_DRAW_STR,
- TIP_("ScaleB: %s : %s : %s%s %s"),
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2],
- t->con.text,
- t->proptext);
- }
- }
- else {
- BLI_snprintf(str,
- UI_MAX_DRAW_STR,
- TIP_("ScaleB X: %s Y: %s Z: %s%s %s"),
- &tvec[0],
- &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2],
- t->con.text,
- t->proptext);
- }
-}
-
-static void ElementBoneSize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3])
-{
- float tmat[3][3], smat[3][3], oldy;
- float sizemat[3][3];
-
- mul_m3_m3m3(smat, mat, td->mtx);
- mul_m3_m3m3(tmat, td->smtx, smat);
-
- if (t->con.applySize) {
- t->con.applySize(t, tc, td, tmat);
- }
-
- /* we've tucked the scale in loc */
- oldy = td->iloc[1];
- size_to_mat3(sizemat, td->iloc);
- mul_m3_m3m3(tmat, tmat, sizemat);
- mat3_to_size(td->loc, tmat);
- td->loc[1] = oldy;
-}
-
-static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
-{
- float size[3], mat[3][3];
- float ratio = t->values[0];
- int i;
- char str[UI_MAX_DRAW_STR];
-
- copy_v3_fl(size, ratio);
-
- snapGridIncrement(t, size);
-
- if (applyNumInput(&t->num, size)) {
- constraintNumInput(t, size);
- }
-
- copy_v3_v3(t->values_final, size);
-
- size_to_mat3(mat, size);
-
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, mat);
- }
-
- copy_m3_m3(t->mat, mat); // used in gizmo
-
- headerBoneSize(t, size, str);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- ElementBoneSize(t, tc, td, mat);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Bone Envelope) */
-
-/** \name Transform Bone Envelope
- * \{ */
-
-static void initBoneEnvelope(TransInfo *t)
-{
- t->mode = TFM_BONE_ENVELOPE;
- t->transform = applyBoneEnvelope;
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
-}
-
-static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
-{
- float ratio;
- int i;
- char str[UI_MAX_DRAW_STR];
-
- ratio = t->values[0];
-
- snapGridIncrement(t, &ratio);
-
- applyNumInput(&t->num, &ratio);
-
- t->values_final[0] = ratio;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), TIP_("Envelope: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Envelope: %3f"), ratio);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->val) {
- /* if the old/original value was 0.0f, then just use ratio */
- if (td->ival) {
- *td->val = td->ival * ratio;
- }
- else {
- *td->val = ratio;
- }
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Edge Slide) */
-
-/** \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 = edgeSlideFirstGet(t);
-
- setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
-
- /* setCustomPoints isn't normally changing as the mouse moves,
- * in this case apply mouse input immediately so we don't refresh
- * with the value from the previous points */
- applyMouseInput(t, &t->mouse, t->mval, t->values);
-}
-
-static BMEdge *get_other_edge(BMVert *v, BMEdge *e)
-{
- BMIter iter;
- BMEdge *e_iter;
-
- BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT) && e_iter != e) {
- return e_iter;
- }
- }
-
- return NULL;
-}
-
-/* interpoaltes along a line made up of 2 segments (used for edge slide) */
-static void interp_line_v3_v3v3v3(
- float p[3], const float v1[3], const float v2[3], const float v3[3], float t)
-{
- float t_mid, t_delta;
-
- /* could be pre-calculated */
- t_mid = line_point_factor_v3(v2, v1, v3);
-
- t_delta = t - t_mid;
- if (t_delta < 0.0f) {
- if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) {
- copy_v3_v3(p, v2);
- }
- else {
- interp_v3_v3v3(p, v1, v2, t / t_mid);
- }
- }
- else {
- t = t - t_mid;
- t_mid = 1.0f - t_mid;
-
- if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) {
- copy_v3_v3(p, v3);
- }
- else {
- interp_v3_v3v3(p, v2, v3, t / t_mid);
- }
- }
-}
-
-/**
- * Find the closest point on the ngon on the opposite side.
- * used to set the edge slide distance for ngons.
- */
-static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, const float plane_no[3], float r_co[3])
-{
- /* skip adjacent edges */
- BMLoop *l_first = l_tmp->next;
- BMLoop *l_last = l_tmp->prev;
- BMLoop *l_iter;
- float dist = FLT_MAX;
- bool found = false;
-
- l_iter = l_first;
- do {
- float tvec[3];
- if (isect_line_plane_v3(tvec, l_iter->v->co, l_iter->next->v->co, l_tmp->v->co, plane_no)) {
- const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co);
- /* allow some overlap to avoid missing the intersection because of float precision */
- if ((fac > -FLT_EPSILON) && (fac < 1.0f + FLT_EPSILON)) {
- /* likelihood of multiple intersections per ngon is quite low,
- * it would have to loop back on its self, but better support it
- * so check for the closest opposite edge */
- const float tdist = len_v3v3(l_tmp->v->co, tvec);
- if (tdist < dist) {
- copy_v3_v3(r_co, tvec);
- dist = tdist;
- found = true;
- }
- }
- }
- } while ((l_iter = l_iter->next) != l_last);
-
- return found;
-}
-
-/**
- * Given 2 edges and a loop, step over the loops
- * and calculate a direction to slide along.
- *
- * \param r_slide_vec: the direction to slide,
- * the length of the vector defines the slide distance.
- */
-static BMLoop *get_next_loop(
- BMVert *v, BMLoop *l, BMEdge *e_prev, BMEdge *e_next, float r_slide_vec[3])
-{
- BMLoop *l_first;
- float vec_accum[3] = {0.0f, 0.0f, 0.0f};
- float vec_accum_len = 0.0f;
- int i = 0;
-
- BLI_assert(BM_edge_share_vert(e_prev, e_next) == v);
- BLI_assert(BM_vert_in_edge(l->e, v));
-
- l_first = l;
- do {
- l = BM_loop_other_edge_loop(l, v);
-
- if (l->e == e_next) {
- if (i) {
- normalize_v3_length(vec_accum, vec_accum_len / (float)i);
- }
- else {
- /* When there is no edge to slide along,
- * we must slide along the vector defined by the face we're attach to */
- BMLoop *l_tmp = BM_face_vert_share_loop(l_first->f, v);
-
- BLI_assert(ELEM(l_tmp->e, e_prev, e_next) && ELEM(l_tmp->prev->e, e_prev, e_next));
-
- if (l_tmp->f->len == 4) {
- /* we could use code below, but in this case
- * sliding diagonally across the quad works well */
- sub_v3_v3v3(vec_accum, l_tmp->next->next->v->co, v->co);
- }
- else {
- float tdir[3];
- BM_loop_calc_face_direction(l_tmp, tdir);
- cross_v3_v3v3(vec_accum, l_tmp->f->no, tdir);
-#if 0
- /* rough guess, we can do better! */
- normalize_v3_length(vec_accum,
- (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f);
-#else
- /* be clever, check the opposite ngon edge to slide into.
- * this gives best results */
- {
- float tvec[3];
- float dist;
-
- if (bm_loop_calc_opposite_co(l_tmp, tdir, tvec)) {
- dist = len_v3v3(l_tmp->v->co, tvec);
- }
- else {
- dist = (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f;
- }
-
- normalize_v3_length(vec_accum, dist);
- }
-#endif
- }
- }
-
- copy_v3_v3(r_slide_vec, vec_accum);
- return l;
- }
- else {
- /* accumulate the normalized edge vector,
- * normalize so some edges don't skew the result */
- float tvec[3];
- sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co);
- vec_accum_len += normalize_v3(tvec);
- add_v3_v3(vec_accum, tvec);
- i += 1;
- }
-
- if (BM_loop_other_edge_loop(l, v)->e == e_next) {
- if (i) {
- normalize_v3_length(vec_accum, vec_accum_len / (float)i);
- }
-
- copy_v3_v3(r_slide_vec, vec_accum);
- return BM_loop_other_edge_loop(l, v);
- }
-
- } while ((l != l->radial_next) && ((l = l->radial_next) != l_first));
-
- if (i) {
- normalize_v3_length(vec_accum, vec_accum_len / (float)i);
- }
-
- copy_v3_v3(r_slide_vec, vec_accum);
-
- return NULL;
-}
-
-/**
- * Calculate screenspace `mval_start` / `mval_end`, optionally slide direction.
- */
-static void calcEdgeSlide_mval_range(TransInfo *t,
- TransDataContainer *tc,
- EdgeSlideData *sld,
- const int *sv_table,
- const int loop_nr,
- const float mval[2],
- const bool use_occlude_geometry,
- const bool use_calc_direction)
-{
- TransDataEdgeSlideVert *sv_array = sld->sv;
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- ARegion *ar = t->ar;
- View3D *v3d = NULL;
- RegionView3D *rv3d = NULL;
- float projectMat[4][4];
- BMBVHTree *bmbvh;
-
- /* only for use_calc_direction */
- float(*loop_dir)[3] = NULL, *loop_maxdist = NULL;
-
- float mval_start[2], mval_end[2];
- float mval_dir[3], dist_best_sq;
- BMIter iter;
- BMEdge *e;
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* background mode support */
- v3d = t->sa ? t->sa->spacedata.first : NULL;
- rv3d = t->ar ? t->ar->regiondata : NULL;
- }
-
- if (!rv3d) {
- /* ok, let's try to survive this */
- unit_m4(projectMat);
- }
- else {
- ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat);
- }
-
- if (use_occlude_geometry) {
- bmbvh = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false);
- }
- else {
- bmbvh = NULL;
- }
-
- /* find mouse vectors, the global one, and one per loop in case we have
- * multiple loops selected, in case they are oriented different */
- zero_v3(mval_dir);
- dist_best_sq = -1.0f;
-
- if (use_calc_direction) {
- loop_dir = MEM_callocN(sizeof(float[3]) * loop_nr, "sv loop_dir");
- loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist");
- copy_vn_fl(loop_maxdist, loop_nr, -1.0f);
- }
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- int i;
-
- /* search cross edges for visible edge to the mouse cursor,
- * then use the shared vertex to calculate screen vector*/
- for (i = 0; i < 2; i++) {
- BMIter iter_other;
- BMEdge *e_other;
-
- BMVert *v = i ? e->v1 : e->v2;
- BM_ITER_ELEM (e_other, &iter_other, v, BM_EDGES_OF_VERT) {
- /* screen-space coords */
- float sco_a[3], sco_b[3];
- float dist_sq;
- int j, l_nr;
-
- if (BM_elem_flag_test(e_other, BM_ELEM_SELECT)) {
- continue;
- }
-
- /* This test is only relevant if object is not wire-drawn! See [#32068]. */
- if (use_occlude_geometry &&
- !BMBVH_EdgeVisible(bmbvh, e_other, t->depsgraph, ar, v3d, tc->obedit)) {
- continue;
- }
-
- BLI_assert(sv_table[BM_elem_index_get(v)] != -1);
- j = sv_table[BM_elem_index_get(v)];
-
- if (sv_array[j].v_side[1]) {
- ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[1]->co, sco_b, projectMat);
- }
- else {
- add_v3_v3v3(sco_b, v->co, sv_array[j].dir_side[1]);
- ED_view3d_project_float_v3_m4(ar, sco_b, sco_b, projectMat);
- }
-
- if (sv_array[j].v_side[0]) {
- ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[0]->co, sco_a, projectMat);
- }
- else {
- add_v3_v3v3(sco_a, v->co, sv_array[j].dir_side[0]);
- ED_view3d_project_float_v3_m4(ar, sco_a, sco_a, projectMat);
- }
-
- /* global direction */
- dist_sq = dist_squared_to_line_segment_v2(mval, sco_b, sco_a);
- if ((dist_best_sq == -1.0f) ||
- /* intentionally use 2d size on 3d vector */
- (dist_sq < dist_best_sq && (len_squared_v2v2(sco_b, sco_a) > 0.1f))) {
- dist_best_sq = dist_sq;
- sub_v3_v3v3(mval_dir, sco_b, sco_a);
- }
-
- if (use_calc_direction) {
- /* per loop direction */
- l_nr = sv_array[j].loop_nr;
- if (loop_maxdist[l_nr] == -1.0f || dist_sq < loop_maxdist[l_nr]) {
- loop_maxdist[l_nr] = dist_sq;
- sub_v3_v3v3(loop_dir[l_nr], sco_b, sco_a);
- }
- }
- }
- }
- }
- }
-
- if (use_calc_direction) {
- int i;
- sv_array = sld->sv;
- for (i = 0; i < sld->totsv; i++, sv_array++) {
- /* switch a/b if loop direction is different from global direction */
- int l_nr = sv_array->loop_nr;
- if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) {
- swap_v3_v3(sv_array->dir_side[0], sv_array->dir_side[1]);
- SWAP(BMVert *, sv_array->v_side[0], sv_array->v_side[1]);
- }
- }
-
- MEM_freeN(loop_dir);
- MEM_freeN(loop_maxdist);
- }
-
- /* possible all of the edge loops are pointing directly at the view */
- if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) {
- mval_dir[0] = 0.0f;
- mval_dir[1] = 100.0f;
- }
-
- /* zero out start */
- zero_v2(mval_start);
-
- /* dir holds a vector along edge loop */
- copy_v2_v2(mval_end, mval_dir);
- mul_v2_fl(mval_end, 0.5f);
-
- sld->mval_start[0] = t->mval[0] + mval_start[0];
- sld->mval_start[1] = t->mval[1] + mval_start[1];
-
- sld->mval_end[0] = t->mval[0] + mval_end[0];
- sld->mval_end[1] = t->mval[1] + mval_end[1];
-
- if (bmbvh) {
- BKE_bmbvh_free(bmbvh);
- }
-}
-
-static void calcEdgeSlide_even(TransInfo *t,
- TransDataContainer *tc,
- EdgeSlideData *sld,
- const float mval[2])
-{
- TransDataEdgeSlideVert *sv = sld->sv;
-
- if (sld->totsv > 0) {
- ARegion *ar = t->ar;
- RegionView3D *rv3d = NULL;
- float projectMat[4][4];
-
- int i = 0;
-
- float v_proj[2];
- float dist_sq = 0;
- float dist_min_sq = FLT_MAX;
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* background mode support */
- rv3d = t->ar ? t->ar->regiondata : NULL;
- }
-
- if (!rv3d) {
- /* ok, let's try to survive this */
- unit_m4(projectMat);
- }
- else {
- ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat);
- }
-
- for (i = 0; i < sld->totsv; i++, sv++) {
- /* Set length */
- sv->edge_len = len_v3v3(sv->dir_side[0], sv->dir_side[1]);
-
- ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat);
- dist_sq = len_squared_v2v2(mval, v_proj);
- if (dist_sq < dist_min_sq) {
- dist_min_sq = dist_sq;
- sld->curr_sv_index = i;
- }
- }
- }
- else {
- sld->curr_sv_index = 0;
- }
-}
-
-static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *tc)
-{
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- BMIter iter;
- BMEdge *e;
- BMVert *v;
- TransDataEdgeSlideVert *sv_array;
- int sv_tot;
- int *sv_table; /* BMVert -> sv_array index */
- EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
- float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
- int numsel, i, loop_nr;
- bool use_occlude_geometry = false;
- View3D *v3d = NULL;
- RegionView3D *rv3d = NULL;
-
- sld->curr_sv_index = 0;
-
- /*ensure valid selection*/
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- BMIter iter2;
- numsel = 0;
- BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- /* BMESH_TODO: this is probably very evil,
- * set v->e to a selected edge*/
- v->e = e;
-
- numsel++;
- }
- }
-
- if (numsel == 0 || numsel > 2) {
- MEM_freeN(sld);
- return false; /* invalid edge selection */
- }
- }
- }
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- /* note, any edge with loops can work, but we won't get predictable results, so bail out */
- if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) {
- /* can edges with at least once face user */
- MEM_freeN(sld);
- return false;
- }
- }
- }
-
- sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__);
-
-#define INDEX_UNSET -1
-#define INDEX_INVALID -2
-
- {
- int j = 0;
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- sv_table[i] = INDEX_UNSET;
- j += 1;
- }
- else {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- sv_table[i] = INDEX_INVALID;
- }
- BM_elem_index_set(v, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- if (!j) {
- MEM_freeN(sld);
- MEM_freeN(sv_table);
- return false;
- }
- sv_tot = j;
- }
-
- sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * sv_tot, "sv_array");
- loop_nr = 0;
-
- STACK_DECLARE(sv_array);
- STACK_INIT(sv_array, sv_tot);
-
- while (1) {
- float vec_a[3], vec_b[3];
- BMLoop *l_a, *l_b;
- BMLoop *l_a_prev, *l_b_prev;
- BMVert *v_first;
- /* If this succeeds call get_next_loop()
- * which calculates the direction to slide based on clever checks.
- *
- * otherwise we simply use 'e_dir' as an edge-rail.
- * (which is better when the attached edge is a boundary, see: T40422)
- */
-#define EDGESLIDE_VERT_IS_INNER(v, e_dir) \
- ((BM_edge_is_boundary(e_dir) == false) && (BM_vert_edge_count_nonwire(v) == 2))
-
- v = NULL;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- break;
- }
- }
-
- if (!v) {
- break;
- }
-
- if (!v->e) {
- continue;
- }
-
- v_first = v;
-
- /*walk along the edge loop*/
- e = v->e;
-
- /*first, rewind*/
- do {
- e = get_other_edge(v, e);
- if (!e) {
- e = v->e;
- break;
- }
-
- if (!BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG)) {
- break;
- }
-
- v = BM_edge_other_vert(e, v);
- } while (e != v_first->e);
-
- BM_elem_flag_disable(v, BM_ELEM_TAG);
-
- l_a = e->l;
- l_b = e->l->radial_next;
-
- /* regarding e_next, use get_next_loop()'s improved interpolation where possible */
- {
- BMEdge *e_next = get_other_edge(v, e);
- if (e_next) {
- get_next_loop(v, l_a, e, e_next, vec_a);
- }
- else {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v);
- if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_a, e, l_tmp->e, vec_a);
- }
- else {
- sub_v3_v3v3(vec_a, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
- }
- }
- }
-
- /* !BM_edge_is_boundary(e); */
- if (l_b != l_a) {
- BMEdge *e_next = get_other_edge(v, e);
- if (e_next) {
- get_next_loop(v, l_b, e, e_next, vec_b);
- }
- else {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v);
- if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_b, e, l_tmp->e, vec_b);
- }
- else {
- sub_v3_v3v3(vec_b, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
- }
- }
- }
- else {
- l_b = NULL;
- }
-
- l_a_prev = NULL;
- l_b_prev = NULL;
-
-#define SV_FROM_VERT(v) \
- ((sv_table[BM_elem_index_get(v)] == INDEX_UNSET) ? \
- ((void)(sv_table[BM_elem_index_get(v)] = STACK_SIZE(sv_array)), \
- STACK_PUSH_RET_PTR(sv_array)) : \
- (&sv_array[sv_table[BM_elem_index_get(v)]]))
-
- /*iterate over the loop*/
- v_first = v;
- do {
- bool l_a_ok_prev;
- bool l_b_ok_prev;
- TransDataEdgeSlideVert *sv;
- BMVert *v_prev;
- BMEdge *e_prev;
-
- /* XXX, 'sv' will initialize multiple times, this is suspicious. see [#34024] */
- BLI_assert(v != NULL);
- BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID);
- sv = SV_FROM_VERT(v);
- sv->v = v;
- copy_v3_v3(sv->v_co_orig, v->co);
- sv->loop_nr = loop_nr;
-
- if (l_a || l_a_prev) {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_a ? l_a : l_a_prev, v);
- sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v);
- copy_v3_v3(sv->dir_side[0], vec_a);
- }
-
- if (l_b || l_b_prev) {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_b ? l_b : l_b_prev, v);
- sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v);
- copy_v3_v3(sv->dir_side[1], vec_b);
- }
-
- v_prev = v;
- v = BM_edge_other_vert(e, v);
-
- e_prev = e;
- e = get_other_edge(v, e);
-
- if (!e) {
- BLI_assert(v != NULL);
-
- BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID);
- sv = SV_FROM_VERT(v);
-
- sv->v = v;
- copy_v3_v3(sv->v_co_orig, v->co);
- sv->loop_nr = loop_nr;
-
- if (l_a) {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v);
- sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v);
- if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_side[0]);
- }
- else {
- sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co);
- }
- }
-
- if (l_b) {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v);
- sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v);
- if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_side[1]);
- }
- else {
- sub_v3_v3v3(sv->dir_side[1], sv->v_side[1]->co, v->co);
- }
- }
-
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- BM_elem_flag_disable(v_prev, BM_ELEM_TAG);
-
- break;
- }
- l_a_ok_prev = (l_a != NULL);
- l_b_ok_prev = (l_b != NULL);
-
- l_a_prev = l_a;
- l_b_prev = l_b;
-
- if (l_a) {
- l_a = get_next_loop(v, l_a, e_prev, e, vec_a);
- }
- else {
- zero_v3(vec_a);
- }
-
- if (l_b) {
- l_b = get_next_loop(v, l_b, e_prev, e, vec_b);
- }
- else {
- zero_v3(vec_b);
- }
-
- if (l_a && l_b) {
- /* pass */
- }
- else {
- if (l_a || l_b) {
- /* find the opposite loop if it was missing previously */
- if (l_a == NULL && l_b && (l_b->radial_next != l_b)) {
- l_a = l_b->radial_next;
- }
- else if (l_b == NULL && l_a && (l_a->radial_next != l_a)) {
- l_b = l_a->radial_next;
- }
- }
- else if (e->l != NULL) {
- /* if there are non-contiguous faces, we can still recover
- * the loops of the new edges faces */
-
- /* note!, the behavior in this case means edges may move in opposite directions,
- * this could be made to work more usefully. */
-
- if (l_a_ok_prev) {
- l_a = e->l;
- l_b = (l_a->radial_next != l_a) ? l_a->radial_next : NULL;
- }
- else if (l_b_ok_prev) {
- l_b = e->l;
- l_a = (l_b->radial_next != l_b) ? l_b->radial_next : NULL;
- }
- }
-
- if (!l_a_ok_prev && l_a) {
- get_next_loop(v, l_a, e, e_prev, vec_a);
- }
- if (!l_b_ok_prev && l_b) {
- get_next_loop(v, l_b, e, e_prev, vec_b);
- }
- }
-
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- BM_elem_flag_disable(v_prev, BM_ELEM_TAG);
- } while ((e != v_first->e) && (l_a || l_b));
-
-#undef SV_FROM_VERT
-#undef INDEX_UNSET
-#undef INDEX_INVALID
-
- loop_nr++;
-
-#undef EDGESLIDE_VERT_IS_INNER
- }
-
- /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
-
- BLI_assert(STACK_SIZE(sv_array) == sv_tot);
-
- sld->sv = sv_array;
- sld->totsv = sv_tot;
-
- /* use for visibility checks */
- if (t->spacetype == SPACE_VIEW3D) {
- v3d = t->sa ? t->sa->spacedata.first : NULL;
- rv3d = t->ar ? t->ar->regiondata : NULL;
- use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE &&
- !XRAY_ENABLED(v3d));
- }
-
- calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true);
-
- if (rv3d) {
- calcEdgeSlide_even(t, tc, sld, mval);
- }
-
- tc->custom.mode.data = sld;
-
- MEM_freeN(sv_table);
-
- return true;
-}
-
-/**
- * A simple version of #createEdgeSlideVerts_double_side
- * Which assumes the longest unselected.
- */
-static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *tc)
-{
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- BMIter iter;
- BMEdge *e;
- TransDataEdgeSlideVert *sv_array;
- int sv_tot;
- int *sv_table; /* BMVert -> sv_array index */
- EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
- float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
- int loop_nr;
- bool use_occlude_geometry = false;
- View3D *v3d = NULL;
- RegionView3D *rv3d = NULL;
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* background mode support */
- v3d = t->sa ? t->sa->spacedata.first : NULL;
- rv3d = t->ar ? t->ar->regiondata : NULL;
- }
-
- sld->curr_sv_index = 0;
- /* ensure valid selection */
- {
- int i = 0, j = 0;
- BMVert *v;
-
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- float len_sq_max = -1.0f;
- BMIter iter2;
- BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- float len_sq = BM_edge_calc_length_squared(e);
- if (len_sq > len_sq_max) {
- len_sq_max = len_sq;
- v->e = e;
- }
- }
- }
-
- if (len_sq_max != -1.0f) {
- j++;
- }
- }
- BM_elem_index_set(v, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- if (!j) {
- MEM_freeN(sld);
- return false;
- }
-
- sv_tot = j;
- }
-
- BLI_assert(sv_tot != 0);
- /* over alloc */
- sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * bm->totvertsel, "sv_array");
-
- /* same loop for all loops, weak but we dont connect loops in this case */
- loop_nr = 1;
-
- sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__);
-
- {
- int i = 0, j = 0;
- BMVert *v;
-
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- sv_table[i] = -1;
- if ((v->e != NULL) && (BM_elem_flag_test(v, BM_ELEM_SELECT))) {
- if (BM_elem_flag_test(v->e, BM_ELEM_SELECT) == 0) {
- TransDataEdgeSlideVert *sv;
- sv = &sv_array[j];
- sv->v = v;
- copy_v3_v3(sv->v_co_orig, v->co);
- sv->v_side[0] = BM_edge_other_vert(v->e, v);
- sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co);
- sv->loop_nr = 0;
- sv_table[i] = j;
- j += 1;
- }
- }
- }
- }
-
- /* check for wire vertices,
- * interpolate the directions of wire verts between non-wire verts */
- if (sv_tot != bm->totvert) {
- const int sv_tot_nowire = sv_tot;
- TransDataEdgeSlideVert *sv_iter = sv_array;
-
- for (int i = 0; i < sv_tot_nowire; i++, sv_iter++) {
- BMIter eiter;
- BM_ITER_ELEM (e, &eiter, sv_iter->v, BM_EDGES_OF_VERT) {
- /* walk over wire */
- TransDataEdgeSlideVert *sv_end = NULL;
- BMEdge *e_step = e;
- BMVert *v = sv_iter->v;
- int j;
-
- j = sv_tot;
-
- while (1) {
- BMVert *v_other = BM_edge_other_vert(e_step, v);
- int endpoint = ((sv_table[BM_elem_index_get(v_other)] != -1) +
- (BM_vert_is_edge_pair(v_other) == false));
-
- if ((BM_elem_flag_test(e_step, BM_ELEM_SELECT) &&
- BM_elem_flag_test(v_other, BM_ELEM_SELECT)) &&
- (endpoint == 0)) {
- /* scan down the list */
- TransDataEdgeSlideVert *sv;
- BLI_assert(sv_table[BM_elem_index_get(v_other)] == -1);
- sv_table[BM_elem_index_get(v_other)] = j;
- sv = &sv_array[j];
- sv->v = v_other;
- copy_v3_v3(sv->v_co_orig, v_other->co);
- copy_v3_v3(sv->dir_side[0], sv_iter->dir_side[0]);
- j++;
-
- /* advance! */
- v = v_other;
- e_step = BM_DISK_EDGE_NEXT(e_step, v_other);
- }
- else {
- if ((endpoint == 2) && (sv_tot != j)) {
- BLI_assert(BM_elem_index_get(v_other) != -1);
- sv_end = &sv_array[sv_table[BM_elem_index_get(v_other)]];
- }
- break;
- }
- }
-
- if (sv_end) {
- int sv_tot_prev = sv_tot;
- const float *co_src = sv_iter->v->co;
- const float *co_dst = sv_end->v->co;
- const float *dir_src = sv_iter->dir_side[0];
- const float *dir_dst = sv_end->dir_side[0];
- sv_tot = j;
-
- while (j-- != sv_tot_prev) {
- float factor;
- factor = line_point_factor_v3(sv_array[j].v->co, co_src, co_dst);
- interp_v3_v3v3(sv_array[j].dir_side[0], dir_src, dir_dst, factor);
- }
- }
- }
- }
- }
-
- /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
-
- sld->sv = sv_array;
- sld->totsv = sv_tot;
-
- /* use for visibility checks */
- if (t->spacetype == SPACE_VIEW3D) {
- v3d = t->sa ? t->sa->spacedata.first : NULL;
- rv3d = t->ar ? t->ar->regiondata : NULL;
- use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE &&
- !XRAY_ENABLED(v3d));
- }
-
- calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, false);
-
- if (rv3d) {
- calcEdgeSlide_even(t, tc, sld, mval);
- }
-
- tc->custom.mode.data = sld;
-
- MEM_freeN(sv_table);
-
- return true;
-}
-
-void projectEdgeSlideData(TransInfo *t, bool is_final)
-{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EdgeSlideData *sld = tc->custom.mode.data;
-
- if (sld == NULL) {
- continue;
- }
-
- trans_mesh_customdata_correction_apply(tc, is_final);
- }
-}
-
-void freeEdgeSlideVerts(TransInfo *UNUSED(t),
- TransDataContainer *UNUSED(tc),
- TransCustomData *custom_data)
-{
- EdgeSlideData *sld = custom_data->data;
-
- if (sld == NULL) {
- return;
- }
-
- MEM_freeN(sld->sv);
- MEM_freeN(sld);
-
- custom_data->data = NULL;
-}
-
-static void initEdgeSlide_ex(
- TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp)
-{
- EdgeSlideData *sld;
- bool ok = false;
-
- t->mode = TFM_EDGE_SLIDE;
- t->transform = applyEdgeSlide;
- t->handleEvent = handleEventEdgeSlide;
-
- {
- EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
- slp->use_even = use_even;
- slp->flipped = flipped;
- /* happens to be best for single-sided */
- if (use_double_side == false) {
- slp->flipped = !flipped;
- }
- slp->perc = 0.0f;
-
- if (!use_clamp) {
- t->flag |= T_ALT_TRANSFORM;
- }
-
- t->custom.mode.data = slp;
- t->custom.mode.use_free = true;
- }
-
- if (use_double_side) {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- ok |= createEdgeSlideVerts_double_side(t, tc);
- }
- }
- else {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- ok |= createEdgeSlideVerts_single_side(t, tc);
- }
- }
-
- if (!ok) {
- t->state = TRANS_CANCEL;
- return;
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- sld = tc->custom.mode.data;
- if (!sld) {
- continue;
- }
- tc->custom.mode.free_cb = freeEdgeSlideVerts;
- }
-
- trans_mesh_customdata_correction_init(t);
-
- /* set custom point first if you want value to be initialized by init */
- calcEdgeSlideCustomPoints(t);
- initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
-}
-
-static void initEdgeSlide(TransInfo *t)
-{
- initEdgeSlide_ex(t, true, false, false, true);
-}
-
-static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event)
-{
- if (t->mode == TFM_EDGE_SLIDE) {
- EdgeSlideParams *slp = t->custom.mode.data;
-
- if (slp) {
- switch (event->type) {
- case EKEY:
- if (event->val == KM_PRESS) {
- slp->use_even = !slp->use_even;
- calcEdgeSlideCustomPoints(t);
- return TREDRAW_HARD;
- }
- break;
- case FKEY:
- if (event->val == KM_PRESS) {
- slp->flipped = !slp->flipped;
- calcEdgeSlideCustomPoints(t);
- return TREDRAW_HARD;
- }
- break;
- case CKEY:
- /* use like a modifier key */
- if (event->val == KM_PRESS) {
- t->flag ^= T_ALT_TRANSFORM;
- calcEdgeSlideCustomPoints(t);
- return TREDRAW_HARD;
- }
- break;
- case EVT_MODAL_MAP:
-#if 0
- switch (event->val) {
- case TFM_MODAL_EDGESLIDE_DOWN:
- sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
- return TREDRAW_HARD;
- case TFM_MODAL_EDGESLIDE_UP:
- sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
- return TREDRAW_HARD;
- }
-#endif
- break;
- case MOUSEMOVE:
- calcEdgeSlideCustomPoints(t);
- break;
- default:
- break;
- }
- }
- }
- return TREDRAW_NOTHING;
-}
-
-static void drawEdgeSlide(TransInfo *t)
-{
- if ((t->mode == TFM_EDGE_SLIDE) && edgeSlideFirstGet(t)) {
- const EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld = edgeSlideFirstGet(t);
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
-
- /* Even mode */
- if ((slp->use_even == true) || (is_clamp == false)) {
- const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
-
- GPU_depth_test(false);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- GPU_matrix_push();
- GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
-
- uint pos = GPU_vertformat_attr_add(
- immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
-
- if (slp->use_even == true) {
- float co_a[3], co_b[3], co_mark[3];
- TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
- const float fac = (slp->perc + 1.0f) / 2.0f;
- const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
- const float guide_size = ctrl_size - 0.5f;
- const int alpha_shade = -30;
-
- add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]);
- add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]);
-
- GPU_line_width(line_size);
- immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immBeginAtMost(GPU_PRIM_LINES, 4);
- if (curr_sv->v_side[0]) {
- immVertex3fv(pos, curr_sv->v_side[0]->co);
- immVertex3fv(pos, curr_sv->v_co_orig);
- }
- if (curr_sv->v_side[1]) {
- immVertex3fv(pos, curr_sv->v_side[1]->co);
- immVertex3fv(pos, curr_sv->v_co_orig);
- }
- immEnd();
-
- {
- float *co_test = NULL;
- if (slp->flipped) {
- if (curr_sv->v_side[1]) {
- co_test = curr_sv->v_side[1]->co;
- }
- }
- else {
- if (curr_sv->v_side[0]) {
- co_test = curr_sv->v_side[0]->co;
- }
- }
-
- if (co_test != NULL) {
- immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
- GPU_point_size(ctrl_size);
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, co_test);
- immEnd();
- }
- }
-
- immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
- GPU_point_size(guide_size);
- immBegin(GPU_PRIM_POINTS, 1);
- interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
- immVertex3fv(pos, co_mark);
- immEnd();
- }
- else {
- if (is_clamp == false) {
- const int side_index = sld->curr_side_unclamp;
- TransDataEdgeSlideVert *sv;
- int i;
- const int alpha_shade = -160;
-
- GPU_line_width(line_size);
- immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immBegin(GPU_PRIM_LINES, sld->totsv * 2);
-
- /* TODO(campbell): Loop over all verts */
- sv = sld->sv;
- for (i = 0; i < sld->totsv; i++, sv++) {
- float a[3], b[3];
-
- if (!is_zero_v3(sv->dir_side[side_index])) {
- copy_v3_v3(a, sv->dir_side[side_index]);
- }
- else {
- copy_v3_v3(a, sv->dir_side[!side_index]);
- }
-
- mul_v3_fl(a, 100.0f);
- negate_v3_v3(b, a);
- add_v3_v3(a, sv->v_co_orig);
- add_v3_v3(b, sv->v_co_orig);
-
- immVertex3fv(pos, a);
- immVertex3fv(pos, b);
- }
- immEnd();
- }
- else {
- BLI_assert(0);
- }
- }
-
- immUnbindProgram();
-
- GPU_matrix_pop();
-
- GPU_blend(false);
-
- GPU_depth_test(true);
- }
- }
-}
-
-static void doEdgeSlide(TransInfo *t, float perc)
-{
- EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld_active = edgeSlideFirstGet(t);
-
- slp->perc = perc;
-
- if (slp->use_even == false) {
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
- if (is_clamp) {
- const int side_index = (perc < 0.0f);
- 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);
- }
- sld->curr_side_unclamp = side_index;
- }
- }
- else {
- const float perc_init = fabsf(perc) *
- ((sld_active->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1);
- 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];
- float perc_final = perc_init;
- if (!is_zero_v3(sv->dir_side[side_index])) {
- copy_v3_v3(dir_flip, sv->dir_side[side_index]);
- }
- else {
- copy_v3_v3(dir_flip, sv->dir_side[!side_index]);
- perc_final *= -1;
- }
- madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, dir_flip, perc_final);
- }
- }
- }
- }
- else {
- /**
- * Implementation note, even mode ignores the starting positions and uses
- * only the a/b verts, this could be changed/improved so the distance is
- * still met but the verts are moved along their original path (which may not be straight),
- * however how it works now is OK and matches 2.4x - Campbell
- *
- * \note `len_v3v3(curr_sv->dir_side[0], curr_sv->dir_side[1])`
- * is the same as the distance between the original vert locations,
- * same goes for the lines below.
- */
- TransDataEdgeSlideVert *curr_sv = &sld_active->sv[sld_active->curr_sv_index];
- const float curr_length_perc = curr_sv->edge_len *
- (((slp->flipped ? perc : -perc) + 1.0f) / 2.0f);
-
- float co_a[3];
- float co_b[3];
-
- 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) {
- const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len;
-
- add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]);
- add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]);
-
- if (slp->flipped) {
- interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac);
- }
- else {
- interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac);
- }
- }
- }
- }
- }
-}
-
-static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
-{
- char str[UI_MAX_DRAW_STR];
- size_t ofs = 0;
- float final;
- EdgeSlideParams *slp = t->custom.mode.data;
- bool flipped = slp->flipped;
- bool use_even = slp->use_even;
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
- const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num));
-
- final = t->values[0];
-
- snapGridIncrement(t, &final);
-
- /* only do this so out of range values are not displayed */
- if (is_constrained) {
- CLAMP(final, -1.0f, 1.0f);
- }
-
- applyNumInput(&t->num, &final);
-
- t->values_final[0] = final;
-
- /* header string */
- ofs += BLI_strncpy_rlen(str + ofs, TIP_("Edge Slide: "), sizeof(str) - ofs);
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs);
- }
- else {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final);
- }
- ofs += BLI_snprintf(
- str + ofs, sizeof(str) - ofs, TIP_("(E)ven: %s, "), WM_bool_as_string(use_even));
- if (use_even) {
- ofs += BLI_snprintf(
- str + ofs, sizeof(str) - ofs, TIP_("(F)lipped: %s, "), WM_bool_as_string(flipped));
- }
- ofs += BLI_snprintf(
- str + ofs, sizeof(str) - ofs, TIP_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
- /* done with header string */
-
- /* do stuff here */
- doEdgeSlide(t, final);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Vert Slide) */
-
-/** \name Transform Vert Slide
- * \{ */
-
-static void calcVertSlideCustomPoints(struct TransInfo *t)
-{
- VertSlideParams *slp = t->custom.mode.data;
- VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
-
- const float *co_orig_3d = sv->co_orig_3d;
- const float *co_curr_3d = sv->co_link_orig_3d[sv->co_link_curr];
-
- float co_curr_2d[2], co_orig_2d[2];
-
- int mval_ofs[2], mval_start[2], mval_end[2];
-
- ED_view3d_project_float_v2_m4(t->ar, co_orig_3d, co_orig_2d, sld->proj_mat);
- ED_view3d_project_float_v2_m4(t->ar, co_curr_3d, co_curr_2d, sld->proj_mat);
-
- ARRAY_SET_ITEMS(mval_ofs, t->mouse.imval[0] - co_orig_2d[0], t->mouse.imval[1] - co_orig_2d[1]);
- ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]);
- ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]);
-
- if (slp->flipped && slp->use_even) {
- setCustomPoints(t, &t->mouse, mval_start, mval_end);
- }
- else {
- setCustomPoints(t, &t->mouse, mval_end, mval_start);
- }
-
- /* setCustomPoints isn't normally changing as the mouse moves,
- * in this case apply mouse input immediately so we don't refresh
- * with the value from the previous points */
- applyMouseInput(t, &t->mouse, t->mval, t->values);
-}
-
-/**
- * Run once when initializing vert slide to find the reference edge
- */
-static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
-{
- /* Active object may have no selected vertices. */
- VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- float mval_fl[2] = {UNPACK2(mval)};
- TransDataVertSlideVert *sv;
-
- /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */
- float dist_sq = 0.0f;
- float dist_min_sq = FLT_MAX;
- int i;
-
- for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
- float co_2d[2];
-
- ED_view3d_project_float_v2_m4(t->ar, sv->co_orig_3d, co_2d, sld->proj_mat);
-
- dist_sq = len_squared_v2v2(mval_fl, co_2d);
- if (dist_sq < dist_min_sq) {
- dist_min_sq = dist_sq;
- sld->curr_sv_index = i;
- }
- }
-}
-
-/**
- * Run while moving the mouse to slide along the edge matching the mouse direction
- */
-static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2])
-{
- VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- float imval_fl[2] = {UNPACK2(t->mouse.imval)};
- float mval_fl[2] = {UNPACK2(mval)};
-
- float dir[3];
- TransDataVertSlideVert *sv;
- int i;
-
- /* note: we could save a matrix-multiply for each vertex
- * by finding the closest edge in local-space.
- * However this skews the outcome with non-uniform-scale. */
-
- /* first get the direction of the original mouse position */
- sub_v2_v2v2(dir, imval_fl, mval_fl);
- ED_view3d_win_to_delta(t->ar, dir, dir, t->zfac);
- normalize_v3(dir);
-
- for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
- if (sv->co_link_tot > 1) {
- float dir_dot_best = -FLT_MAX;
- int co_link_curr_best = -1;
- int j;
-
- for (j = 0; j < sv->co_link_tot; j++) {
- float tdir[3];
- float dir_dot;
-
- sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]);
- mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, tdir);
- project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]);
-
- normalize_v3(tdir);
- dir_dot = dot_v3v3(dir, tdir);
- if (dir_dot > dir_dot_best) {
- dir_dot_best = dir_dot;
- co_link_curr_best = j;
- }
- }
-
- if (co_link_curr_best != -1) {
- sv->co_link_curr = co_link_curr_best;
- }
- }
- }
-}
-
-static bool createVertSlideVerts(TransInfo *t, TransDataContainer *tc)
-{
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- BMIter iter;
- BMIter eiter;
- BMEdge *e;
- BMVert *v;
- TransDataVertSlideVert *sv_array;
- VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
- int j;
-
- sld->curr_sv_index = 0;
-
- j = 0;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- bool ok = false;
- if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) {
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- ok = true;
- break;
- }
- }
- }
-
- if (ok) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- j += 1;
- }
- else {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
- }
-
- if (!j) {
- MEM_freeN(sld);
- return false;
- }
-
- sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array");
-
- j = 0;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- int k;
- sv_array[j].v = v;
- copy_v3_v3(sv_array[j].co_orig_3d, v->co);
-
- k = 0;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- k++;
- }
- }
-
- sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k,
- __func__);
- sv_array[j].co_link_tot = k;
-
- k = 0;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co);
- k++;
- }
- }
- j++;
- }
- }
-
- sld->sv = sv_array;
- sld->totsv = j;
-
- tc->custom.mode.data = sld;
-
- /* most likely will be set below */
- unit_m4(sld->proj_mat);
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* view vars */
- RegionView3D *rv3d = NULL;
- ARegion *ar = t->ar;
-
- rv3d = ar ? ar->regiondata : NULL;
- if (rv3d) {
- ED_view3d_ob_project_mat_get(rv3d, tc->obedit, sld->proj_mat);
- }
- }
-
- /* XXX, calc vert slide across all objects */
- if (tc == t->data_container) {
- calcVertSlideMouseActiveVert(t, t->mval);
- calcVertSlideMouseActiveEdges(t, t->mval);
- }
-
- return true;
-}
-
-void projectVertSlideData(TransInfo *t, bool is_final)
-{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- trans_mesh_customdata_correction_apply(tc, is_final);
- }
-}
-
-void freeVertSlideVerts(TransInfo *UNUSED(t),
- TransDataContainer *UNUSED(tc),
- TransCustomData *custom_data)
-{
- VertSlideData *sld = custom_data->data;
-
- if (!sld) {
- return;
- }
-
- if (sld->totsv > 0) {
- TransDataVertSlideVert *sv = sld->sv;
- int i = 0;
- for (i = 0; i < sld->totsv; i++, sv++) {
- MEM_freeN(sv->co_link_orig_3d);
- }
- }
-
- MEM_freeN(sld->sv);
- MEM_freeN(sld);
-
- custom_data->data = NULL;
-}
-
-static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
-{
-
- t->mode = TFM_VERT_SLIDE;
- t->transform = applyVertSlide;
- t->handleEvent = handleEventVertSlide;
-
- {
- VertSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
- slp->use_even = use_even;
- slp->flipped = flipped;
- slp->perc = 0.0f;
-
- if (!use_clamp) {
- t->flag |= T_ALT_TRANSFORM;
- }
-
- t->custom.mode.data = slp;
- t->custom.mode.use_free = true;
- }
-
- bool ok = false;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- ok |= createVertSlideVerts(t, tc);
- VertSlideData *sld = tc->custom.mode.data;
- if (sld) {
- tc->custom.mode.free_cb = freeVertSlideVerts;
- }
- }
-
- if (ok == false) {
- t->state = TRANS_CANCEL;
- return;
- }
-
- trans_mesh_customdata_correction_init(t);
-
- /* set custom point first if you want value to be initialized by init */
- calcVertSlideCustomPoints(t);
- initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
-}
-
-static void initVertSlide(TransInfo *t)
-{
- initVertSlide_ex(t, false, false, true);
-}
-
-static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event)
-{
- if (t->mode == TFM_VERT_SLIDE) {
- VertSlideParams *slp = t->custom.mode.data;
-
- if (slp) {
- switch (event->type) {
- case EKEY:
- if (event->val == KM_PRESS) {
- slp->use_even = !slp->use_even;
- if (slp->flipped) {
- calcVertSlideCustomPoints(t);
- }
- return TREDRAW_HARD;
- }
- break;
- case FKEY:
- if (event->val == KM_PRESS) {
- slp->flipped = !slp->flipped;
- calcVertSlideCustomPoints(t);
- return TREDRAW_HARD;
- }
- break;
- case CKEY:
- /* use like a modifier key */
- if (event->val == KM_PRESS) {
- t->flag ^= T_ALT_TRANSFORM;
- calcVertSlideCustomPoints(t);
- return TREDRAW_HARD;
- }
- break;
-#if 0
- case EVT_MODAL_MAP:
- switch (event->val) {
- case TFM_MODAL_EDGESLIDE_DOWN:
- sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
- break;
- case TFM_MODAL_EDGESLIDE_UP:
- sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
- break;
- }
- break;
-#endif
- case MOUSEMOVE: {
- /* don't recalculate the best edge */
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
- if (is_clamp) {
- calcVertSlideMouseActiveEdges(t, event->mval);
- }
- calcVertSlideCustomPoints(t);
- break;
- }
- default:
- break;
- }
- }
- }
- return TREDRAW_NOTHING;
-}
-
-static void drawVertSlide(TransInfo *t)
-{
- if ((t->mode == TFM_VERT_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
- const VertSlideParams *slp = t->custom.mode.data;
- VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
-
- /* Non-Prop mode */
- {
- TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
- TransDataVertSlideVert *sv;
- const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
- const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
- const int alpha_shade = -160;
- int i;
-
- GPU_depth_test(false);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- GPU_matrix_push();
- GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
-
- GPU_line_width(line_size);
-
- const uint shdr_pos = GPU_vertformat_attr_add(
- immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
-
- immBegin(GPU_PRIM_LINES, sld->totsv * 2);
- if (is_clamp) {
- sv = sld->sv;
- for (i = 0; i < sld->totsv; i++, sv++) {
- immVertex3fv(shdr_pos, sv->co_orig_3d);
- immVertex3fv(shdr_pos, sv->co_link_orig_3d[sv->co_link_curr]);
- }
- }
- else {
- sv = sld->sv;
- for (i = 0; i < sld->totsv; i++, sv++) {
- float a[3], b[3];
- sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
- mul_v3_fl(a, 100.0f);
- negate_v3_v3(b, a);
- add_v3_v3(a, sv->co_orig_3d);
- add_v3_v3(b, sv->co_orig_3d);
-
- immVertex3fv(shdr_pos, a);
- immVertex3fv(shdr_pos, b);
- }
- }
- immEnd();
-
- GPU_point_size(ctrl_size);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(shdr_pos,
- (slp->flipped && slp->use_even) ?
- curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
- curr_sv->co_orig_3d);
- immEnd();
-
- immUnbindProgram();
-
- /* direction from active vertex! */
- if ((t->mval[0] != t->mouse.imval[0]) || (t->mval[1] != t->mouse.imval[1])) {
- float zfac;
- float mval_ofs[2];
- float co_orig_3d[3];
- float co_dest_3d[3];
-
- mval_ofs[0] = t->mval[0] - t->mouse.imval[0];
- mval_ofs[1] = t->mval[1] - t->mouse.imval[1];
-
- mul_v3_m4v3(
- co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d);
- zfac = ED_view3d_calc_zfac(t->ar->regiondata, co_orig_3d, NULL);
-
- ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac);
-
- invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat,
- TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
- mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d);
-
- add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
-
- GPU_line_width(1.0f);
-
- immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
-
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(shdr_pos, curr_sv->co_orig_3d);
- immVertex3fv(shdr_pos, co_dest_3d);
- immEnd();
-
- immUnbindProgram();
- }
-
- GPU_matrix_pop();
-
- GPU_depth_test(true);
- }
- }
-}
-
-static void doVertSlide(TransInfo *t, float perc)
-{
- VertSlideParams *slp = t->custom.mode.data;
-
- slp->perc = perc;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- VertSlideData *sld = tc->custom.mode.data;
- TransDataVertSlideVert *svlist = sld->sv, *sv;
- int i;
-
- sv = svlist;
-
- if (slp->use_even == false) {
- for (i = 0; i < sld->totsv; i++, sv++) {
- interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc);
- }
- }
- else {
- TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index];
- const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d,
- sv_curr->co_link_orig_3d[sv_curr->co_link_curr]);
- const float tperc = perc * edge_len_curr;
-
- for (i = 0; i < sld->totsv; i++, sv++) {
- float edge_len;
- float dir[3];
-
- sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
- edge_len = normalize_v3(dir);
-
- if (edge_len > FLT_EPSILON) {
- if (slp->flipped) {
- madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc);
- }
- else {
- madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc);
- }
- }
- else {
- copy_v3_v3(sv->v->co, sv->co_orig_3d);
- }
- }
- }
- }
-}
-
-static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
-{
- char str[UI_MAX_DRAW_STR];
- size_t ofs = 0;
- float final;
- VertSlideParams *slp = t->custom.mode.data;
- const bool flipped = slp->flipped;
- const bool use_even = slp->use_even;
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
- const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num));
-
- final = t->values[0];
-
- snapGridIncrement(t, &final);
-
- /* only do this so out of range values are not displayed */
- if (is_constrained) {
- CLAMP(final, 0.0f, 1.0f);
- }
-
- applyNumInput(&t->num, &final);
-
- t->values_final[0] = final;
-
- /* header string */
- ofs += BLI_strncpy_rlen(str + ofs, TIP_("Vert Slide: "), sizeof(str) - ofs);
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs);
- }
- else {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final);
- }
- ofs += BLI_snprintf(
- str + ofs, sizeof(str) - ofs, TIP_("(E)ven: %s, "), WM_bool_as_string(use_even));
- if (use_even) {
- ofs += BLI_snprintf(
- str + ofs, sizeof(str) - ofs, TIP_("(F)lipped: %s, "), WM_bool_as_string(flipped));
- }
- ofs += BLI_snprintf(
- str + ofs, sizeof(str) - ofs, TIP_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
- /* done with header string */
-
- /* do stuff here */
- doVertSlide(t, final);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (EditBone Roll) */
-
-/** \name Transform EditBone Roll
- * \{ */
-
-static void initBoneRoll(TransInfo *t)
-{
- t->mode = TFM_BONE_ROLL;
- t->transform = applyBoneRoll;
-
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
-
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
-}
-
-static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
-{
- int i;
- char str[UI_MAX_DRAW_STR];
-
- float final;
-
- final = t->values[0];
-
- snapGridIncrement(t, &final);
-
- applyNumInput(&t->num, &final);
-
- t->values_final[0] = final;
-
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- BLI_snprintf(str, sizeof(str), TIP_("Roll: %s"), &c[0]);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Roll: %.2f"), RAD2DEGF(final));
- }
-
- /* set roll values */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- *(td->val) = td->ival - final;
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Bake-Time) */
-
-/** \name Transform Bake-Time
- * \{ */
-
-static void initBakeTime(TransInfo *t)
-{
- t->transform = applyBakeTime;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
-
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 1.0f;
- t->snap[2] = t->snap[1] * 0.1f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE; /* Don't think this uses units? */
-}
-
-static void applyBakeTime(TransInfo *t, const int mval[2])
-{
- float time;
- int i;
- char str[UI_MAX_DRAW_STR];
-
- float fac = 0.1f;
-
- /* XXX, disable precision for now,
- * this isn't even accessible by the user */
-#if 0
- if (t->mouse.precision) {
- /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
- time = (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac;
- time += 0.1f * ((float)(t->center2d[0] * fac - mval[0]) - time);
- }
- else
-#endif
- {
- time = (float)(t->center2d[0] - mval[0]) * fac;
- }
-
- snapGridIncrement(t, &time);
-
- applyNumInput(&t->num, &time);
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- if (time >= 0.0f) {
- BLI_snprintf(str, sizeof(str), TIP_("Time: +%s %s"), c, t->proptext);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Time: %s %s"), c, t->proptext);
- }
- }
- else {
- /* default header print */
- if (time >= 0.0f) {
- BLI_snprintf(str, sizeof(str), TIP_("Time: +%.3f %s"), time, t->proptext);
- }
- else {
- BLI_snprintf(str, sizeof(str), TIP_("Time: %.3f %s"), time, t->proptext);
- }
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->val) {
- *td->val = td->ival + time * td->factor;
- if (td->ext->size && *td->val < *td->ext->size) {
- *td->val = *td->ext->size;
- }
- if (td->ext->quat && *td->val > *td->ext->quat) {
- *td->val = *td->ext->quat;
- }
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Mirror) */
-
-/** \name Transform Mirror
- * \{ */
-
-static void initMirror(TransInfo *t)
-{
- t->transform = applyMirror;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
-
- t->flag |= T_NULL_ONE;
- if ((t->flag & T_EDIT) == 0) {
- t->flag |= T_NO_ZERO;
- }
-}
-
-static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
-{
- float size[3], mat[3][3];
- int i;
- char str[UI_MAX_DRAW_STR];
- copy_v3_v3(t->values_final, t->values);
-
- /*
- * OPTIMIZATION:
- * This still recalcs transformation on mouse move
- * while it should only recalc on constraint change
- * */
-
- /* if an axis has been selected */
- if (t->con.mode & CON_APPLY) {
- size[0] = size[1] = size[2] = -1;
-
- size_to_mat3(mat, size);
-
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, mat);
- }
-
- BLI_snprintf(str, sizeof(str), TIP_("Mirror%s"), t->con.text);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- ElementResize(t, tc, td, mat);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
- }
- else {
- size[0] = size[1] = size[2] = 1;
-
- size_to_mat3(mat, size);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- ElementResize(t, tc, td, mat);
- }
- }
-
- recalcData(t);
-
- if (t->flag & T_2D_EDIT) {
- ED_area_status_text(t->sa, TIP_("Select a mirror axis (X, Y)"));
- }
- else {
- ED_area_status_text(t->sa, TIP_("Select a mirror axis (X, Y, Z)"));
- }
- }
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Align) */
-
-/** \name Transform Align
- * \{ */
-
-static void initAlign(TransInfo *t)
-{
- t->flag |= T_NO_CONSTRAINT;
-
- t->transform = applyAlign;
-
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
-}
-
-static void applyAlign(TransInfo *t, const int UNUSED(mval[2]))
-{
- float center[3];
- int i;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- /* saving original center */
- copy_v3_v3(center, tc->center_local);
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float mat[3][3], invmat[3][3];
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- /* around local centers */
- if (t->flag & (T_OBJECT | T_POSE)) {
- copy_v3_v3(tc->center_local, td->center);
- }
- else {
- if (t->settings->selectmode & SCE_SELECT_FACE) {
- copy_v3_v3(tc->center_local, td->center);
- }
- }
-
- invert_m3_m3(invmat, td->axismtx);
-
- mul_m3_m3m3(mat, t->spacemtx, invmat);
-
- ElementRotation(t, tc, td, mat, t->around);
- }
- /* restoring original center */
- copy_v3_v3(tc->center_local, center);
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, TIP_("Align"));
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Sequencer Slide) */
-
-/** \name Transform Sequencer Slide
- * \{ */
-
-static void initSeqSlide(TransInfo *t)
-{
- t->transform = applySeqSlide;
-
- initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
-
- t->idx_max = 1;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
-
- t->snap[0] = 0.0f;
- t->snap[1] = floorf(t->scene->r.frs_sec / t->scene->r.frs_sec_base);
- t->snap[2] = 10.0f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- /* Would be nice to have a time handling in units as well
- * (supporting frames in addition to "natural" time...). */
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
-}
-
-static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRAW_STR])
-{
- char tvec[NUM_STR_REP_LEN * 3];
- size_t ofs = 0;
-
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]);
- }
-
- ofs += BLI_snprintf(
- str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text);
-
- if (t->keymap) {
- wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE);
- if (kmi) {
- ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs);
- }
- }
- ofs += BLI_snprintf(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- TIP_(" or Alt) Expand to fit %s"),
- WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
-}
-
-static void applySeqSlideValue(TransInfo *t, const float val[2])
-{
- int i;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor);
- }
- }
-}
-
-static void applySeqSlide(TransInfo *t, const int mval[2])
-{
- char str[UI_MAX_DRAW_STR];
-
- snapSequenceBounds(t, mval);
-
- if (t->con.mode & CON_APPLY) {
- float pvec[3] = {0.0f, 0.0f, 0.0f};
- float tvec[3];
- t->con.applyVec(t, NULL, NULL, t->values, tvec, pvec);
- copy_v3_v3(t->values_final, tvec);
- }
- else {
- // snapGridIncrement(t, t->values);
- applyNumInput(&t->num, t->values);
- copy_v3_v3(t->values_final, t->values);
- }
-
- t->values_final[0] = floorf(t->values_final[0] + 0.5f);
- t->values_final[1] = floorf(t->values_final[1] + 0.5f);
-
- headerSeqSlide(t, t->values_final, str);
- applySeqSlideValue(t, t->values_final);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Animation Editors - Transform Utils
- *
- * Special Helpers for Various Settings
- */
-
-/** \name Animation Editor Utils
- * \{ */
-
-/* This function returns the snapping 'mode' for Animation Editors only
- * We cannot use the standard snapping due to NLA-strip scaling complexities.
- */
-// XXX these modifier checks should be keymappable
-static short getAnimEdit_SnapMode(TransInfo *t)
-{
- short autosnap = SACTSNAP_OFF;
-
- if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
-
- if (saction) {
- autosnap = saction->autosnap;
- }
- }
- else if (t->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
-
- if (sipo) {
- autosnap = sipo->autosnap;
- }
- }
- else if (t->spacetype == SPACE_NLA) {
- SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
-
- if (snla) {
- autosnap = snla->autosnap;
- }
- }
- else {
- autosnap = SACTSNAP_OFF;
- }
-
- /* toggle autosnap on/off
- * - when toggling on, prefer nearest frame over 1.0 frame increments
- */
- if (t->modifiers & MOD_SNAP_INVERT) {
- if (autosnap) {
- autosnap = SACTSNAP_OFF;
- }
- else {
- autosnap = SACTSNAP_FRAME;
- }
- }
-
- return autosnap;
-}
-
-/* This function is used by Animation Editor specific transform functions to do
- * the Snap Keyframe to Nearest Frame/Marker
- */
-static void doAnimEdit_SnapFrame(
- TransInfo *t, TransData *td, TransData2D *td2d, AnimData *adt, short autosnap)
-{
- if (ELEM(autosnap, SACTSNAP_FRAME, SACTSNAP_SECOND, SACTSNAP_MARKER)) {
- float val;
-
- /* convert frame to nla-action time (if needed) */
- if (adt) {
- val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP);
- }
- else {
- val = *(td->val);
- }
-
- snapFrameTransform(t, autosnap, true, val, &val);
-
- /* convert frame out of nla-action time */
- if (adt) {
- *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
- }
- else {
- *(td->val) = val;
- }
- }
-
- /* If the handles are to be moved too
- * (as side-effect of keyframes moving, to keep the general effect)
- * offset them by the same amount so that the general angles are maintained
- * (i.e. won't change while handles are free-to-roam and keyframes are snap-locked).
- */
- if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
- td2d->h1[0] = td2d->ih1[0] + *td->val - td->ival;
- }
- if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
- td2d->h2[0] = td2d->ih2[0] + *td->val - td->ival;
- }
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Animation Translation) */
-
-/** \name Transform Animation Translation
- * \{ */
-
-static void initTimeTranslate(TransInfo *t)
-{
- /* this tool is only really available in the Action Editor... */
- if (!ELEM(t->spacetype, SPACE_ACTION, SPACE_SEQ)) {
- t->state = TRANS_CANCEL;
- }
-
- t->mode = TFM_TIME_TRANSLATE;
- t->transform = applyTimeTranslate;
-
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
-
- /* num-input has max of (n-1) */
- t->idx_max = 0;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
-
- /* initialize snap like for everything else */
- t->snap[0] = 0.0f;
- t->snap[1] = t->snap[2] = 1.0f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- /* No time unit supporting frames currently... */
- t->num.unit_type[0] = B_UNIT_NONE;
-}
-
-static void headerTimeTranslate(TransInfo *t, char str[UI_MAX_DRAW_STR])
-{
- char tvec[NUM_STR_REP_LEN * 3];
- int ofs = 0;
-
- /* if numeric input is active, use results from that, otherwise apply snapping to result */
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- const short autosnap = getAnimEdit_SnapMode(t);
- float val = t->values_final[0];
-
- float snap_val;
- snapFrameTransform(t, autosnap, false, val, &snap_val);
-
- if (autosnap == SACTSNAP_FRAME) {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.2f (%.4f)", snap_val, val);
- }
- else if (autosnap == SACTSNAP_SECOND) {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.2f sec (%.4f)", snap_val, val);
- }
- else if (autosnap == SACTSNAP_TSTEP) {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f sec", snap_val);
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", snap_val);
- }
- }
-
- ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, TIP_("DeltaX: %s"), &tvec[0]);
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(
- str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
- }
-}
-
-static void applyTimeTranslateValue(TransInfo *t, float value)
-{
- Scene *scene = t->scene;
- int i;
-
- const short autosnap = getAnimEdit_SnapMode(t);
- const double secf = FPS;
-
- float deltax, val /* , valprev */;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- TransData2D *td2d = tc->data_2d;
- /* It doesn't matter whether we apply to t->data or
- * t->data2d, but t->data2d is more convenient. */
- for (i = 0; i < tc->data_len; i++, td++, td2d++) {
- /* It is assumed that td->extra is a pointer to the AnimData,
- * whose active action is where this keyframe comes from.
- * (this is only valid when not in NLA)
- * (also: masks and gpencil dont have animadata)
- */
- AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
-
- /* valprev = *td->val; */ /* UNUSED */
-
- /* check if any need to apply nla-mapping */
- if (adt && (t->spacetype != SPACE_SEQ)) {
- deltax = value;
-
- if (autosnap == SACTSNAP_TSTEP) {
- deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf);
- }
- else if (autosnap == SACTSNAP_STEP) {
- deltax = floorf(deltax + 0.5f);
- }
-
- val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP);
- val += deltax * td->factor;
- *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
- }
- else {
- deltax = val = t->values_final[0];
-
- if (autosnap == SACTSNAP_TSTEP) {
- val = (float)(floor(((double)deltax / secf) + 0.5) * secf);
- }
- else if (autosnap == SACTSNAP_STEP) {
- val = floorf(val + 0.5f);
- }
-
- *(td->val) = td->ival + val * td->factor;
- }
-
- /* apply nearest snapping */
- doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
- }
- }
-}
-
-static void applyTimeTranslate(TransInfo *t, const int mval[2])
-{
- View2D *v2d = (View2D *)t->view;
- char str[UI_MAX_DRAW_STR];
-
- /* calculate translation amount from mouse movement - in 'time-grid space' */
- if (t->flag & T_MODAL) {
- float cval[2], sval[2];
- UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
- UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[0], &sval[0], &sval[1]);
-
- /* we only need to calculate effect for time (applyTimeTranslate only needs that) */
- t->values[0] = cval[0] - sval[0];
- }
-
- /* handle numeric-input stuff */
- t->vec[0] = t->values[0];
- applyNumInput(&t->num, &t->vec[0]);
- t->values_final[0] = t->vec[0];
- headerTimeTranslate(t, str);
-
- applyTimeTranslateValue(t, t->values_final[0]);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Animation Time Slide) */
-
-/** \name Transform Animation Time Slide
- * \{ */
-
-static void initTimeSlide(TransInfo *t)
-{
- /* this tool is only really available in the Action Editor... */
- if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
-
- /* set flag for drawing stuff */
- saction->flag |= SACTION_MOVING;
- }
- else {
- t->state = TRANS_CANCEL;
- }
-
- t->mode = TFM_TIME_SLIDE;
- t->transform = applyTimeSlide;
-
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
-
- {
- Scene *scene = t->scene;
- float *range;
- t->custom.mode.data = range = MEM_mallocN(sizeof(float[2]), "TimeSlide Min/Max");
- t->custom.mode.use_free = true;
-
- float min = 999999999.0f, max = -999999999.0f;
- int i;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
- float val = *(td->val);
-
- /* strip/action time to global (mapped) time */
- if (adt) {
- val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP);
- }
-
- if (min > val) {
- min = val;
- }
- if (max < val) {
- max = val;
- }
- }
- }
-
- if (min == max) {
- /* just use the current frame ranges */
- min = (float)PSFRA;
- max = (float)PEFRA;
- }
-
- range[0] = min;
- range[1] = max;
- }
-
- /* num-input has max of (n-1) */
- t->idx_max = 0;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
-
- /* initialize snap like for everything else */
- t->snap[0] = 0.0f;
- t->snap[1] = t->snap[2] = 1.0f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- /* No time unit supporting frames currently... */
- t->num.unit_type[0] = B_UNIT_NONE;
-}
-
-static void headerTimeSlide(TransInfo *t, const float sval, char str[UI_MAX_DRAW_STR])
-{
- char tvec[NUM_STR_REP_LEN * 3];
-
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- const float *range = t->custom.mode.data;
- float minx = range[0];
- float maxx = range[1];
- float cval = t->values_final[0];
- float val;
-
- val = 2.0f * (cval - sval) / (maxx - minx);
- CLAMP(val, -1.0f, 1.0f);
-
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
- }
-
- BLI_snprintf(str, UI_MAX_DRAW_STR, TIP_("TimeSlide: %s"), &tvec[0]);
-}
-
-static void applyTimeSlideValue(TransInfo *t, float sval, float cval)
-{
- int i;
- const float *range = t->custom.mode.data;
- float minx = range[0];
- float maxx = range[1];
-
- /* set value for drawing black line */
- if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
- saction->timeslide = cval;
- }
-
- /* It doesn't matter whether we apply to t->data or
- * t->data2d, but t->data2d is more convenient. */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- /* it is assumed that td->extra is a pointer to the AnimData,
- * whose active action is where this keyframe comes from
- * (this is only valid when not in NLA)
- */
- AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
-
- /* only apply to data if in range */
- if ((sval > minx) && (sval < maxx)) {
- float cvalc = CLAMPIS(cval, minx, maxx);
- float ival = td->ival;
- float timefac;
-
- /* NLA mapping magic here works as follows:
- * - "ival" goes from strip time to global time
- * - calculation is performed into td->val in global time
- * (since sval and min/max are all in global time)
- * - "td->val" then gets put back into strip time
- */
- if (adt) {
- /* strip to global */
- ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP);
- }
-
- /* left half? */
- if (ival < sval) {
- timefac = (sval - ival) / (sval - minx);
- *(td->val) = cvalc - timefac * (cvalc - minx);
- }
- else {
- timefac = (ival - sval) / (maxx - sval);
- *(td->val) = cvalc + timefac * (maxx - cvalc);
- }
-
- if (adt) {
- /* global to strip */
- *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP);
- }
- }
- }
- }
-}
-
-static void applyTimeSlide(TransInfo *t, const int mval[2])
-{
- View2D *v2d = (View2D *)t->view;
- float cval[2], sval[2];
- const float *range = t->custom.mode.data;
- float minx = range[0];
- float maxx = range[1];
- char str[UI_MAX_DRAW_STR];
-
- /* calculate mouse co-ordinates */
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]);
- UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &sval[0], &sval[1]);
-
- /* t->values_final[0] stores cval[0], which is the current mouse-pointer location (in frames) */
- // XXX Need to be able to repeat this
- /* t->values_final[0] = cval[0]; */ /* UNUSED (reset again later). */
-
- /* handle numeric-input stuff */
- t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx);
- applyNumInput(&t->num, &t->vec[0]);
- t->values_final[0] = (maxx - minx) * t->vec[0] / 2.0f + sval[0];
-
- headerTimeSlide(t, sval[0], str);
- applyTimeSlideValue(t, sval[0], t->values_final[0]);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/* Transform (Animation Time Scale) */
-
-/** \name Transform Animation Time Scale
- * \{ */
-
-static void initTimeScale(TransInfo *t)
-{
- float center[2];
-
- /* this tool is only really available in the Action Editor
- * AND NLA Editor (for strip scaling)
- */
- if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA) == 0) {
- t->state = TRANS_CANCEL;
- }
-
- t->mode = TFM_TIME_SCALE;
- t->transform = applyTimeScale;
-
- /* recalculate center2d to use CFRA and mouse Y, since that's
- * what is used in time scale */
- if ((t->flag & T_OVERRIDE_CENTER) == 0) {
- t->center_global[0] = t->scene->r.cfra;
- projectFloatView(t, t->center_global, center);
- center[1] = t->mouse.imval[1];
- }
-
- /* force a reinit with the center2d used here */
- initMouseInput(t, &t->mouse, center, t->mouse.imval, false);
-
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
-
- t->flag |= T_NULL_ONE;
- t->num.val_flag[0] |= NUM_NULL_ONE;
-
- /* num-input has max of (n-1) */
- t->idx_max = 0;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
-
- /* initialize snap like for everything else */
- t->snap[0] = 0.0f;
- t->snap[1] = t->snap[2] = 1.0f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
-}
-
-static void headerTimeScale(TransInfo *t, char str[UI_MAX_DRAW_STR])
-{
- char tvec[NUM_STR_REP_LEN * 3];
-
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values_final[0]);
- }
-
- BLI_snprintf(str, UI_MAX_DRAW_STR, TIP_("ScaleX: %s"), &tvec[0]);
-}
-
-static void applyTimeScaleValue(TransInfo *t, float value)
-{
- Scene *scene = t->scene;
- int i;
-
- const short autosnap = getAnimEdit_SnapMode(t);
- const double secf = FPS;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- TransData2D *td2d = tc->data_2d;
- for (i = 0; i < tc->data_len; i++, td++, td2d++) {
- /* it is assumed that td->extra is a pointer to the AnimData,
- * whose active action is where this keyframe comes from
- * (this is only valid when not in NLA)
- */
- AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
- float startx = CFRA;
- float fac = value;
-
- if (autosnap == SACTSNAP_TSTEP) {
- fac = (float)(floor((double)fac / secf + 0.5) * secf);
- }
- else if (autosnap == SACTSNAP_STEP) {
- fac = floorf(fac + 0.5f);
- }
-
- /* take proportional editing into account */
- fac = ((fac - 1.0f) * td->factor) + 1;
-
- /* check if any need to apply nla-mapping */
- if (adt) {
- startx = BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP);
- }
-
- /* now, calculate the new value */
- *(td->val) = ((td->ival - startx) * fac) + startx;
-
- /* apply nearest snapping */
- doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
- }
- }
-}
-
-static void applyTimeScale(TransInfo *t, const int UNUSED(mval[2]))
-{
- char str[UI_MAX_DRAW_STR];
-
- /* handle numeric-input stuff */
- t->vec[0] = t->values[0];
- applyNumInput(&t->num, &t->vec[0]);
- t->values_final[0] = t->vec[0];
- headerTimeScale(t, str);
-
- applyTimeScaleValue(t, t->values_final[0]);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
-}
-/** \} */
-
/* TODO, move to: transform_query.c */
bool checkUseAxisMatrix(TransInfo *t)
{
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 95506918d98..503e7bd4691 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -24,8 +24,8 @@
#ifndef __TRANSFORM_H__
#define __TRANSFORM_H__
-#include "ED_transform.h"
#include "ED_numinput.h"
+#include "ED_transform.h"
#include "ED_view3d.h"
#include "RE_engine.h"
@@ -270,114 +270,6 @@ typedef struct TransDataNla {
int handle;
} TransDataNla;
-struct LinkNode;
-
-/* header of TransDataEdgeSlideVert, TransDataEdgeSlideEdge */
-typedef struct TransDataGenericSlideVert {
- struct BMVert *v;
- struct LinkNode **cd_loop_groups;
- float co_orig_3d[3];
-} TransDataGenericSlideVert;
-
-typedef struct TransDataEdgeSlideVert {
- /** #TransDataGenericSlideVert (header) */
- struct BMVert *v;
- struct LinkNode **cd_loop_groups;
- float v_co_orig[3];
- /* end generic */
-
- float edge_len;
-
- struct BMVert *v_side[2];
-
- /* add origvert.co to get the original locations */
- float dir_side[2][3];
-
- int loop_nr;
-} TransDataEdgeSlideVert;
-
-typedef struct EdgeSlideData {
- TransDataEdgeSlideVert *sv;
- int totsv;
-
- int mval_start[2], mval_end[2];
- int curr_sv_index;
-
- /** when un-clamped - use this index: #TransDataEdgeSlideVert.dir_side */
- int curr_side_unclamp;
-} EdgeSlideData;
-
-typedef struct EdgeSlideParams {
- float perc;
-
- bool use_even;
- bool flipped;
-} EdgeSlideParams;
-
-typedef struct TransDataVertSlideVert {
- /** #TransDataGenericSlideVert (header) */
- struct BMVert *v;
- struct LinkNode **cd_loop_groups;
- float co_orig_3d[3];
- /* end generic */
-
- float (*co_link_orig_3d)[3];
- int co_link_tot;
- int co_link_curr;
-} TransDataVertSlideVert;
-
-typedef struct VertSlideData {
- TransDataVertSlideVert *sv;
- int totsv;
- int curr_sv_index;
-
- /* result of ED_view3d_ob_project_mat_get */
- float proj_mat[4][4];
-} VertSlideData;
-
-typedef struct VertSlideParams {
- float perc;
-
- bool use_even;
- bool flipped;
-} VertSlideParams;
-
-typedef struct BoneInitData {
- struct EditBone *bone;
- float tail[3];
- float rad_head;
- float rad_tail;
- float roll;
- float head[3];
- float dist;
- float xwidth;
- float zwidth;
-} BoneInitData;
-
-typedef struct PoseInitData_Mirror {
- /** Points to the bone which this info is initialized & restored to.
- * A NULL value is used to terminate the array. */
- struct bPoseChannel *pchan;
- struct {
- float loc[3];
- float size[3];
- union {
- float eul[3];
- float quat[4];
- float axis_angle[4];
- };
- float curve_in_x;
- float curve_out_x;
- float roll1;
- float roll2;
- } orig;
- /**
- * An extra offset to apply after mirroring.
- * Use with #POSE_MIRROR_RELATIVE.
- */
- float offset_mtx[4][4];
-} PoseInitData_Mirror;
-
typedef struct TransData {
/** Distance needed to affect element (for Proportionnal Editing). */
float dist;
@@ -639,17 +531,12 @@ typedef struct TransInfo {
bool is_launch_event_tweak;
struct {
- /** Orientation type when when we're not constrained.
- * nearly always global except for rotate which defaults to screen-space orientation. */
- short unset;
- /** Orientation to use when a key is pressed. */
- short user;
- /* Used when user is global. */
- short user_alt;
short index;
- short *types[2];
- /* this gets used when custom_orientation is V3D_ORIENT_CUSTOM */
+ short types[3];
+ /* this gets used when orientation.type[x] is V3D_ORIENT_CUSTOM */
struct TransformOrientation *custom;
+ /* this gets used when orientation.type[0] is V3D_ORIENT_CUSTOM_MATRIX */
+ float custom_matrix[3][3];
} orientation;
/** backup from view3d, to restore on end. */
short gizmo_flag;
@@ -674,23 +561,14 @@ typedef struct TransInfo {
/** Secondary axis, shear uses this. */
int orient_axis_ortho;
- /** Often this matrix has similar usage to #TransInfo.spacemtx however this
- * is used to define extra axes to operate on, not necessarily a space.
- *
- * For example, by default rotation operates on the view (`orient_matrix[2]`),
- * even when the current space isn't set to the view. */
- float orient_matrix[3][3];
- /** Don't overwrite when set by operator redo defines the orientation axis. */
- bool orient_matrix_is_set;
-
/** remove elements if operator is canceled. */
bool remove_on_cancel;
void *view;
/** Only valid (non null) during an operator called function. */
struct bContext *context;
- struct ScrArea *sa;
- struct ARegion *ar;
+ struct ScrArea *area;
+ struct ARegion *region;
struct Depsgraph *depsgraph;
struct Scene *scene;
struct ViewLayer *view_layer;
@@ -785,6 +663,10 @@ enum {
T_MODAL_CURSOR_SET = 1 << 26,
T_CLNOR_REBUILD = 1 << 27,
+
+ /* Special Aftertrans. */
+ T_AUTOMERGE = 1 << 28,
+ T_AUTOSPLIT = 1 << 29,
};
/** #TransInfo.modifiers */
@@ -875,6 +757,43 @@ enum {
MULTI_POINTS = 1 << 3,
};
+/** keymap modal items */
+/* NOTE: these values are saved in keymap files, do not change then but just add new ones. */
+enum {
+ TFM_MODAL_CANCEL = 1,
+ TFM_MODAL_CONFIRM = 2,
+ TFM_MODAL_TRANSLATE = 3,
+ TFM_MODAL_ROTATE = 4,
+ TFM_MODAL_RESIZE = 5,
+ TFM_MODAL_SNAP_INV_ON = 6,
+ TFM_MODAL_SNAP_INV_OFF = 7,
+ TFM_MODAL_SNAP_TOGGLE = 8,
+ TFM_MODAL_AXIS_X = 9,
+ TFM_MODAL_AXIS_Y = 10,
+ TFM_MODAL_AXIS_Z = 11,
+ TFM_MODAL_PLANE_X = 12,
+ TFM_MODAL_PLANE_Y = 13,
+ TFM_MODAL_PLANE_Z = 14,
+ TFM_MODAL_CONS_OFF = 15,
+ TFM_MODAL_ADD_SNAP = 16,
+ TFM_MODAL_REMOVE_SNAP = 17,
+
+ /* 18 and 19 used by numinput, defined in transform.h */
+
+ TFM_MODAL_PROPSIZE_UP = 20,
+ TFM_MODAL_PROPSIZE_DOWN = 21,
+ TFM_MODAL_AUTOIK_LEN_INC = 22,
+ TFM_MODAL_AUTOIK_LEN_DEC = 23,
+
+ TFM_MODAL_EDGESLIDE_UP = 24,
+ TFM_MODAL_EDGESLIDE_DOWN = 25,
+
+ /* for analog input, like trackpad */
+ TFM_MODAL_PROPSIZE = 26,
+ /* node editor insert offset (aka auto-offset) direction toggle */
+ TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27,
+};
+
/* Hard min/max for proportional size. */
#define T_PROP_SIZE_MIN 1e-6f
#define T_PROP_SIZE_MAX 1e12f
@@ -900,8 +819,6 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2]);
void applyAspectRatio(TransInfo *t, float vec[2]);
void removeAspectRatio(TransInfo *t, float vec[2]);
-void drawPropCircle(const struct bContext *C, TransInfo *t);
-
struct wmKeyMap *transform_modal_keymap(struct wmKeyConfig *keyconf);
/*********************** transform_gizmo.c ********** */
@@ -915,32 +832,6 @@ void drawDial3d(const TransInfo *t);
/*********************** TransData Creation and General Handling *********** */
bool transdata_check_local_islands(TransInfo *t, short around);
-/*********************** Constraints *****************************/
-
-void drawConstraint(TransInfo *t);
-
-void getConstraintMatrix(TransInfo *t);
-void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[]);
-void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]);
-void setLocalConstraint(TransInfo *t, int mode, const char text[]);
-void setUserConstraint(TransInfo *t, short orientation, int mode, const char text[]);
-
-void constraintNumInput(TransInfo *t, float vec[3]);
-
-bool isLockConstraint(TransInfo *t);
-int getConstraintSpaceDimension(TransInfo *t);
-int constraintModeToIndex(const TransInfo *t);
-char constraintModeToChar(const TransInfo *t);
-
-void startConstraint(TransInfo *t);
-void stopConstraint(TransInfo *t);
-
-void initSelectConstraint(TransInfo *t, float mtx[3][3]);
-void selectConstraint(TransInfo *t);
-void postSelectConstraint(TransInfo *t);
-
-void setNearestAxis(TransInfo *t);
-
/********************** Mouse Input ******************************/
typedef enum {
@@ -1021,7 +912,7 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot);
/*********************** Transform Orientations ******************************/
-void initTransformOrientation(struct bContext *C, TransInfo *t);
+void initTransformOrientation(struct bContext *C, TransInfo *t, short orientation);
/* Those two fill in mat and return non-zero on success */
bool createSpaceNormal(float mat[3][3], const float normal[3]);
@@ -1052,12 +943,6 @@ int getTransformOrientation(const struct bContext *C, float normal[3], float pla
void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
-void freeEdgeSlideVerts(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
-void projectEdgeSlideData(TransInfo *t, bool is_final);
-
-void freeVertSlideVerts(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
-void projectVertSlideData(TransInfo *t, bool is_final);
-
/* TODO. transform_query.c */
bool checkUseAxisMatrix(TransInfo *t);
@@ -1072,14 +957,14 @@ bool checkUseAxisMatrix(TransInfo *t);
(BLI_assert((t)->data_container_len == 1), (&(t)->data_container[0]))
#define FOREACH_TRANS_DATA_CONTAINER(t, th) \
- for (TransDataContainer *tc = t->data_container, \
- *tc_end = t->data_container + t->data_container_len; \
+ for (TransDataContainer *tc = (t)->data_container, \
+ *tc_end = (t)->data_container + (t)->data_container_len; \
th != tc_end; \
th++)
#define FOREACH_TRANS_DATA_CONTAINER_INDEX(t, th, i) \
- for (TransDataContainer *tc = ((i = 0), t->data_container), \
- *tc_end = t->data_container + t->data_container_len; \
+ for (TransDataContainer *tc = ((i = 0), (t)->data_container), \
+ *tc_end = (t)->data_container + (t)->data_container_len; \
th != tc_end; \
th++, i++)
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index b43e1fec988..b07eb6edf5a 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -21,10 +21,10 @@
* \ingroup edtransform
*/
-#include <stdlib.h>
+#include <math.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -32,20 +32,17 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
-#include "BIF_glutil.h"
-
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_string.h"
#include "BLI_rect.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "ED_image.h"
#include "ED_view3d.h"
#include "BLT_translation.h"
@@ -55,6 +52,9 @@
#include "transform.h"
#include "transform_snap.h"
+/* Own include. */
+#include "transform_constraints.h"
+
static void drawObjectConstraint(TransInfo *t);
/* ************************** CONSTRAINTS ************************* */
@@ -171,7 +171,7 @@ static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3])
static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3])
{
if (t->spacetype == SPACE_VIEW3D) {
- // View3D *v3d = t->sa->spacedata.first;
+ // View3D *v3d = t->area->spacedata.first;
const float min_dist = 1.0f; /* v3d->clip_start; */
float dir[3];
float l;
@@ -713,7 +713,10 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte
break;
case V3D_ORIENT_VIEW:
BLI_snprintf(text, sizeof(text), ftext, TIP_("view"));
- setConstraint(t, t->spacemtx, mode, text);
+ float mtx[3][3];
+ copy_m3_m3(mtx, t->spacemtx);
+ negate_v3(mtx[2]);
+ setConstraint(t, mtx, mode, text);
break;
case V3D_ORIENT_CURSOR:
BLI_snprintf(text, sizeof(text), ftext, TIP_("cursor"));
@@ -727,7 +730,9 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte
BLI_snprintf(text, sizeof(text), ftext, TIP_("custom matrix"));
setConstraint(t, t->spacemtx, mode, text);
break;
- case V3D_ORIENT_CUSTOM: {
+ case V3D_ORIENT_CUSTOM:
+ default: {
+ BLI_assert(orientation >= V3D_ORIENT_CUSTOM);
char orientation_str[128];
BLI_snprintf(orientation_str,
sizeof(orientation_str),
@@ -846,8 +851,8 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
}
else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_ACTION)) {
/* only scale y */
- rcti *mask = &t->ar->v2d.mask;
- rctf *datamask = &t->ar->v2d.cur;
+ rcti *mask = &t->region->v2d.mask;
+ rctf *datamask = &t->region->v2d.cur;
float xsize = BLI_rctf_size_x(datamask);
float ysize = BLI_rctf_size_y(datamask);
float xmask = BLI_rcti_size_x(mask);
@@ -984,17 +989,22 @@ void getConstraintMatrix(TransInfo *t)
/*------------------------- MMB Select -------------------------------*/
-void initSelectConstraint(TransInfo *t, float mtx[3][3])
+void initSelectConstraint(TransInfo *t, bool force_global)
{
- copy_m3_m3(t->con.mtx, mtx);
- t->con.mode |= CON_APPLY;
- t->con.mode |= CON_SELECT;
+ short orientation;
+ if (force_global) {
+ orientation = V3D_ORIENT_GLOBAL;
+ }
+ else {
+ if (t->orientation.index == 0) {
+ t->orientation.index = 1;
+ initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]);
+ }
+ orientation = t->orientation.types[t->orientation.index];
+ }
+ setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, "");
setNearestAxis(t);
- t->con.drawExtra = NULL;
- t->con.applyVec = applyAxisConstraintVec;
- t->con.applySize = applyAxisConstraintSize;
- t->con.applyRot = applyAxisConstraintRot;
}
void selectConstraint(TransInfo *t)
@@ -1055,7 +1065,7 @@ static void setNearestAxis3d(TransInfo *t)
* projecting them with ED_view3d_win_to_delta and then get the length of that vector.
*/
zfac = mul_project_m4_v3_zfac(t->persmat, t->center_global);
- zfac = len_v3(t->persinv[0]) * 2.0f / t->ar->winx * zfac * 30.0f;
+ zfac = len_v3(t->persinv[0]) * 2.0f / t->region->winx * zfac * 30.0f;
for (i = 0; i < 3; i++) {
float axis[3], axis_2d[2];
diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h
new file mode 100644
index 00000000000..c98234c83da
--- /dev/null
+++ b/source/blender/editors/transform/transform_constraints.h
@@ -0,0 +1,48 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#ifndef __TRANSFORM_CONSTRAINTS_H__
+#define __TRANSFORM_CONSTRAINTS_H__
+
+struct TransInfo;
+
+void constraintNumInput(TransInfo *t, float vec[3]);
+void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[]);
+void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]);
+void setLocalConstraint(TransInfo *t, int mode, const char text[]);
+void setUserConstraint(TransInfo *t, short orientation, int mode, const char text[]);
+void drawConstraint(TransInfo *t);
+void drawPropCircle(const struct bContext *C, TransInfo *t);
+void startConstraint(TransInfo *t);
+void stopConstraint(TransInfo *t);
+void getConstraintMatrix(TransInfo *t);
+void initSelectConstraint(TransInfo *t, bool force_global);
+void selectConstraint(TransInfo *t);
+void postSelectConstraint(TransInfo *t);
+void setNearestAxis(TransInfo *t);
+int constraintModeToIndex(const TransInfo *t);
+char constraintModeToChar(const TransInfo *t);
+bool isLockConstraint(TransInfo *t);
+int getConstraintSpaceDimension(TransInfo *t);
+
+#endif
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 869c23de74c..d6875f173e3 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -23,51 +23,53 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
-#include "DNA_space_types.h"
#include "DNA_constraint_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_mask_types.h"
+#include "DNA_space_types.h"
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
+#include "BLI_kdtree.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_string.h"
-#include "BLI_kdtree.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_context.h"
+#include "BKE_editmesh.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_layer.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_mask.h"
#include "BKE_modifier.h"
#include "BKE_nla.h"
#include "BKE_node.h"
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
-#include "BKE_editmesh.h"
#include "BKE_tracking.h"
-#include "BKE_mask.h"
#include "BIK_api.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
-#include "ED_particle.h"
+#include "ED_clip.h"
#include "ED_image.h"
-#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
-#include "ED_object.h"
+#include "ED_keyframing.h"
#include "ED_markers.h"
+#include "ED_mask.h"
#include "ED_mesh.h"
#include "ED_node.h"
-#include "ED_clip.h"
-#include "ED_mask.h"
+#include "ED_object.h"
+#include "ED_particle.h"
+
+#include "UI_view2d.h"
#include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
#include "WM_types.h"
@@ -79,6 +81,12 @@
#include "transform.h"
#include "transform_convert.h"
+#include "transform_mode.h"
+
+bool transform_mode_use_local_origins(const TransInfo *t)
+{
+ return ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL);
+}
/**
* Transforming around ourselves is no use, fallback to individual origins,
@@ -86,14 +94,40 @@
*/
void transform_around_single_fallback(TransInfo *t)
{
- if ((t->data_len_all == 1) &&
- (ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN, V3D_AROUND_ACTIVE)) &&
- (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL))) {
- t->around = V3D_AROUND_LOCAL_ORIGINS;
+ if ((ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN, V3D_AROUND_ACTIVE)) &&
+ transform_mode_use_local_origins(t)) {
+
+ bool is_data_single = false;
+ if (t->data_len_all == 1) {
+ is_data_single = true;
+ }
+ else if (t->data_len_all == 3) {
+ if (t->obedit_type == OB_CURVE) {
+ /* Special case check for curve, if we have a single curve bezier triple selected
+ * treat */
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ if (!tc->data_len) {
+ continue;
+ }
+ if (tc->data_len == 3) {
+ const TransData *td = tc->data;
+ if ((td[0].loc == td[1].loc) && (td[1].loc == td[2].loc)) {
+ is_data_single = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+ if (is_data_single) {
+ t->around = V3D_AROUND_LOCAL_ORIGINS;
+ }
}
}
-/* ************************** Functions *************************** */
+/* -------------------------------------------------------------------- */
+/** \name Proportional Editing
+ * \{ */
static int trans_data_compare_dist(const void *a, const void *b)
{
@@ -203,8 +237,8 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
const bool use_island = transdata_check_local_islands(t, t->around);
if (t->flag & T_PROP_PROJECTED) {
- if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = t->ar->regiondata;
+ if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = t->region->regiondata;
normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
proj_vec = _proj_vec;
}
@@ -330,7 +364,11 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
MEM_freeN(td_table);
}
-/* ********************* pose mode ************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pose Mode
+ * \{ */
static short apply_targetless_ik(Object *ob)
{
@@ -368,23 +406,25 @@ static short apply_targetless_ik(Object *ob)
}
for (; segcount; segcount--) {
Bone *bone;
- float rmat[4][4] /*, tmat[4][4], imat[4][4]*/;
+ float mat[4][4];
/* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
- /* we put in channel the entire result of rmat = (channel * constraint * IK) */
- /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
- /* rmat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */
+ /* we put in channel the entire result of mat = (channel * constraint * IK) */
+ /* pose_mat(b) = pose_mat(b-1) * offs_bone * mat */
+ /* mat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */
parchan = chanlist[segcount - 1];
bone = parchan->bone;
bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
- BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, rmat);
-
+ BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, mat);
/* apply and decompose, doesn't work for constraints or non-uniform scale well */
{
float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
- copy_m3_m4(rmat3, rmat);
+
+ copy_m3_m4(rmat3, mat);
+ /* Make sure that our rotation matrix only contains rotation and not scale. */
+ normalize_m3(rmat3);
/* rotation */
/* [#22409] is partially caused by this, as slight numeric error introduced during
@@ -404,7 +444,7 @@ static short apply_targetless_ik(Object *ob)
/* causes problems with some constraints (e.g. childof), so disable this */
/* as it is IK shouldn't affect location directly */
- /* copy_v3_v3(parchan->loc, rmat[3]); */
+ /* copy_v3_v3(parchan->loc, mat[3]); */
}
}
@@ -436,12 +476,12 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
}
}
-/* sets transform flags in the bones
- * returns total number of bones with BONE_TRANSFORM */
-int count_set_pose_transflags(Object *ob,
- const int mode,
- const short around,
- bool has_translate_rotate[2])
+/* Sets transform flags in the bones.
+ * Returns total number of bones with `BONE_TRANSFORM`. */
+int transform_convert_pose_transflags_update(Object *ob,
+ const int mode,
+ const short around,
+ bool has_translate_rotate[2])
{
bArmature *arm = ob->data;
bPoseChannel *pchan;
@@ -450,15 +490,20 @@ int count_set_pose_transflags(Object *ob,
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
- bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
if (PBONE_VISIBLE(arm, bone)) {
if ((bone->flag & BONE_SELECTED)) {
bone->flag |= BONE_TRANSFORM;
}
+ else {
+ bone->flag &= ~BONE_TRANSFORM;
+ }
bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
bone->flag &= ~BONE_TRANSFORM_CHILD;
}
+ else {
+ bone->flag &= ~BONE_TRANSFORM;
+ }
}
/* make sure no bone can be transformed when a parent is transformed */
@@ -503,7 +548,11 @@ int count_set_pose_transflags(Object *ob,
return total;
}
-/* -------- Auto-IK ---------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pose Mode (Auto-IK)
+ * \{ */
/* adjust pose-channel's auto-ik chainlen */
static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
@@ -628,7 +677,11 @@ static void pose_grab_with_ik_clear(Main *bmain, Object *ob)
}
}
-/* ********************* curve/surface ********* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Curve Surface
+ * \{ */
void calc_distanceCurveVerts(TransData *head, TransData *tail)
{
@@ -698,7 +751,11 @@ TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTr
return hdata;
}
-/* ********************* UV ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name UV Coordinates
+ * \{ */
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
{
@@ -784,7 +841,36 @@ void clipUVData(TransInfo *t)
}
}
-/* ********************* ANIMATION EDITORS (GENERAL) ************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Animation Editors (General)
+ * \{ */
+
+/**
+ * Used for `TFM_TIME_EXTEND`.
+ */
+char transform_convert_frame_side_dir_get(TransInfo *t, float cframe)
+{
+ char r_dir;
+ float center[2];
+ if (t->flag & T_MODAL) {
+ UI_view2d_region_to_view(
+ (View2D *)t->view, t->mouse.imval[0], t->mouse.imval[1], &center[0], &center[1]);
+ r_dir = (center[0] > cframe) ? 'R' : 'L';
+ {
+ /* XXX: This saves the direction in the "mirror" property to be used for redo! */
+ if (r_dir == 'R') {
+ t->flag |= T_NO_MIRROR;
+ }
+ }
+ }
+ else {
+ r_dir = (t->flag & T_NO_MIRROR) ? 'R' : 'L';
+ }
+
+ return r_dir;
+}
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
bool FrameOnMouseSide(char side, float frame, float cframe)
@@ -803,26 +889,11 @@ bool FrameOnMouseSide(char side, float frame, float cframe)
}
}
-/* ********************* ACTION EDITOR ****************** */
+/** \} */
-static int gpf_cmp_frame(void *thunk, const void *a, const void *b)
-{
- const bGPDframe *frame_a = a;
- const bGPDframe *frame_b = b;
-
- if (frame_a->framenum < frame_b->framenum) {
- return -1;
- }
- if (frame_a->framenum > frame_b->framenum) {
- return 1;
- }
- *((bool *)thunk) = true;
- /* selected last */
- if ((frame_a->flag & GP_FRAME_SELECT) && ((frame_b->flag & GP_FRAME_SELECT) == 0)) {
- return 1;
- }
- return 0;
-}
+/* -------------------------------------------------------------------- */
+/** \name Animation Editor
+ * \{ */
static int masklay_shape_cmp_frame(void *thunk, const void *a, const void *b)
{
@@ -856,13 +927,13 @@ static void posttrans_gpd_clean(bGPdata *gpd)
bGPDframe *gpf, *gpfn;
bool is_double = false;
- BLI_listbase_sort_r(&gpl->frames, gpf_cmp_frame, &is_double);
+ BKE_gpencil_layer_frames_sort(gpl, &is_double);
if (is_double) {
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
gpfn = gpf->next;
if (gpfn && gpf->framenum == gpfn->framenum) {
- BKE_gpencil_layer_delframe(gpl, gpf);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
}
}
}
@@ -875,6 +946,8 @@ static void posttrans_gpd_clean(bGPdata *gpd)
}
/* set cache flag to dirty */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ WM_main_add_notifier(NC_GPENCIL | NA_EDITED, gpd);
}
static void posttrans_mask_clean(Mask *mask)
@@ -904,6 +977,8 @@ static void posttrans_mask_clean(Mask *mask)
}
#endif
}
+
+ WM_main_add_notifier(NC_MASK | NA_EDITED, mask);
}
/* Time + Average value */
@@ -985,7 +1060,7 @@ static void posttrans_fcurve_clean(FCurve *fcu,
}
else {
/* Compute the average values for each retained keyframe */
- for (tRetainedKeyframe *rk = retained_keys.first; rk; rk = rk->next) {
+ LISTBASE_FOREACH (tRetainedKeyframe *, rk, &retained_keys) {
rk->val = rk->val / (float)rk->tot_count;
}
}
@@ -1078,15 +1153,19 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act)
ANIM_animdata_freelist(&anim_data);
}
-/* ********************* GRAPH EDITOR ************************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Graph Editor
+ * \{ */
/* struct for use in re-sorting BezTriples during Graph Editor transform */
typedef struct BeztMap {
BezTriple *bezt;
- unsigned int oldIndex; /* index of bezt in fcu->bezt array before sorting */
- unsigned int newIndex; /* index of bezt in fcu->bezt array after sorting */
- short swapHs; /* swap order of handles (-1=clear; 0=not checked, 1=swap) */
- char pipo, cipo; /* interpolation of current and next segments */
+ uint oldIndex; /* index of bezt in fcu->bezt array before sorting */
+ uint newIndex; /* index of bezt in fcu->bezt array after sorting */
+ short swapHs; /* swap order of handles (-1=clear; 0=not checked, 1=swap) */
+ char pipo, cipo; /* interpolation of current and next segments */
} BeztMap;
/* This function converts an FCurve's BezTriple array to a BeztMap array
@@ -1249,6 +1328,12 @@ static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totve
MEM_freeN(adjusted);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform Utilities
+ * \{ */
+
/* This function is called by recalcData during the Transform loop to recalculate
* the handles of curves and sort the keyframes so that the curves draw correctly.
* It is only called if some keyframes have moved out of order.
@@ -1258,7 +1343,7 @@ static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totve
*/
void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
bAnimListElem *ale;
const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
@@ -1287,8 +1372,6 @@ void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
}
}
-/* *********************** Transform data ******************* */
-
/* Little helper function for ObjectToTransData used to give certain
* constraints (ChildOf, FollowPath, and others that may be added)
* inverse corrections for transform, so that they aren't in CrazySpace.
@@ -1374,6 +1457,12 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list)
return false;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform (Auto-Keyframing)
+ * \{ */
+
/**
* Auto-keyframing feature - for objects
*
@@ -1395,10 +1484,10 @@ void autokeyframe_object(bContext *C, Scene *scene, ViewLayer *view_layer, Objec
KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
ListBase dsources = {NULL, NULL};
float cfra = (float)CFRA; // xxx this will do for now
- short flag = 0;
+ eInsertKeyFlags flag = 0;
- /* get flags used for inserting keyframes */
- flag = ANIM_get_keyframing_flags(scene, 1);
+ /* Get flags used for inserting keyframes. */
+ flag = ANIM_get_keyframing_flags(scene, true);
/* add datasource override for the object */
ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL);
@@ -1417,7 +1506,6 @@ void autokeyframe_object(bContext *C, Scene *scene, ViewLayer *view_layer, Objec
if (adt && adt->action) {
ListBase nla_cache = {NULL, NULL};
for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
- fcu->flag &= ~FCURVE_SELECTED;
insert_keyframe(bmain,
reports,
id,
@@ -1532,147 +1620,156 @@ void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short t
FCurve *fcu;
// TODO: this should probably be done per channel instead...
- if (autokeyframe_cfra_can_key(scene, id)) {
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
- KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
- ListBase nla_cache = {NULL, NULL};
- float cfra = (float)CFRA;
- short flag = 0;
-
- /* flag is initialized from UserPref keyframing settings
- * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
- * visual keyframes even if flag not set, as it's not that useful otherwise
- * (for quick animation recording)
- */
- flag = ANIM_get_keyframing_flags(scene, 1);
+ if (!autokeyframe_cfra_can_key(scene, id)) {
+ /* tag channels that should have unkeyed data */
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ /* tag this channel */
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+ }
+ return;
+ }
+
+ ReportList *reports = CTX_wm_reports(C);
+ ToolSettings *ts = scene->toolsettings;
+ KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
+ ListBase nla_cache = {NULL, NULL};
+ float cfra = (float)CFRA;
+ eInsertKeyFlags flag = 0;
- if (targetless_ik) {
- flag |= INSERTKEY_MATRIX;
+ /* flag is initialized from UserPref keyframing settings
+ * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
+ * visual keyframes even if flag not set, as it's not that useful otherwise
+ * (for quick animation recording)
+ */
+ flag = ANIM_get_keyframing_flags(scene, true);
+
+ if (targetless_ik) {
+ flag |= INSERTKEY_MATRIX;
+ }
+
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((pchan->bone->flag & BONE_TRANSFORM) == 0 &&
+ !((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR))) {
+ continue;
}
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((pchan->bone->flag & BONE_TRANSFORM) ||
- ((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR))) {
- ListBase dsources = {NULL, NULL};
-
- /* clear any 'unkeyed' flag it may have */
- pchan->bone->flag &= ~BONE_UNKEYED;
-
- /* add datasource override for the camera object */
- ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan);
-
- /* only insert into active keyingset? */
- if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
- /* run the active Keying Set on the current datasource */
- ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- /* only insert into available channels? */
- else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
- if (act) {
- for (fcu = act->curves.first; fcu; fcu = fcu->next) {
- /* only insert keyframes for this F-Curve if it affects the current bone */
- if (strstr(fcu->rna_path, "bones")) {
- char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
-
- /* only if bone name matches too...
- * NOTE: this will do constraints too, but those are ok to do here too?
- */
- if (pchanName && STREQ(pchanName, pchan->name)) {
- insert_keyframe(bmain,
- reports,
- id,
- act,
- ((fcu->grp) ? (fcu->grp->name) : (NULL)),
- fcu->rna_path,
- fcu->array_index,
- cfra,
- ts->keyframe_type,
- &nla_cache,
- flag);
- }
-
- if (pchanName) {
- MEM_freeN(pchanName);
- }
- }
- }
- }
- }
- /* only insert keyframe if needed? */
- else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
- bool do_loc = false, do_rot = false, do_scale = false;
+ ListBase dsources = {NULL, NULL};
- /* Filter the conditions when this happens
- * (assume that 'curarea->spacetype == SPACE_VIEW3D'). */
- if (tmode == TFM_TRANSLATION) {
- if (targetless_ik) {
- do_rot = true;
- }
- else {
- do_loc = true;
- }
- }
- else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
- if (ELEM(scene->toolsettings->transform_pivot_point,
- V3D_AROUND_CURSOR,
- V3D_AROUND_ACTIVE)) {
- do_loc = true;
- }
+ /* clear any 'unkeyed' flag it may have */
+ pchan->bone->flag &= ~BONE_UNKEYED;
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_rot = true;
- }
- }
- else if (tmode == TFM_RESIZE) {
- if (ELEM(scene->toolsettings->transform_pivot_point,
- V3D_AROUND_CURSOR,
- V3D_AROUND_ACTIVE)) {
- do_loc = true;
- }
+ /* add datasource override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan);
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_scale = true;
- }
+ /* only insert into active keyingset? */
+ if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
+ /* run the active Keying Set on the current datasource */
+ ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ /* only insert into available channels? */
+ else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
+ if (act) {
+ for (fcu = act->curves.first; fcu; fcu = fcu->next) {
+ /* only insert keyframes for this F-Curve if it affects the current bone */
+ if (strstr(fcu->rna_path, "bones") == NULL) {
+ continue;
}
+ char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
- if (do_loc) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- if (do_rot) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ /* only if bone name matches too...
+ * NOTE: this will do constraints too, but those are ok to do here too?
+ */
+ if (pchanName && STREQ(pchanName, pchan->name)) {
+ insert_keyframe(bmain,
+ reports,
+ id,
+ act,
+ ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ fcu->rna_path,
+ fcu->array_index,
+ cfra,
+ ts->keyframe_type,
+ &nla_cache,
+ flag);
}
- if (do_scale) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+
+ if (pchanName) {
+ MEM_freeN(pchanName);
}
}
- /* insert keyframe in all (transform) channels */
+ }
+ }
+ /* only insert keyframe if needed? */
+ else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
+ bool do_loc = false, do_rot = false, do_scale = false;
+
+ /* Filter the conditions when this happens
+ * (assume that 'curarea->spacetype == SPACE_VIEW3D'). */
+ if (tmode == TFM_TRANSLATION) {
+ if (targetless_ik) {
+ do_rot = true;
+ }
else {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ do_loc = true;
+ }
+ }
+ else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
+ if (ELEM(scene->toolsettings->transform_pivot_point,
+ V3D_AROUND_CURSOR,
+ V3D_AROUND_ACTIVE)) {
+ do_loc = true;
}
- /* free temp info */
- BLI_freelistN(&dsources);
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_rot = true;
+ }
}
- }
+ else if (tmode == TFM_RESIZE) {
+ if (ELEM(scene->toolsettings->transform_pivot_point,
+ V3D_AROUND_CURSOR,
+ V3D_AROUND_ACTIVE)) {
+ do_loc = true;
+ }
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
- }
- else {
- /* tag channels that should have unkeyed data */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_TRANSFORM) {
- /* tag this channel */
- pchan->bone->flag |= BONE_UNKEYED;
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_scale = true;
+ }
+ }
+
+ if (do_loc) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_rot) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_scale) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
}
+ /* insert keyframe in all (transform) channels */
+ else {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+
+ /* free temp info */
+ BLI_freelistN(&dsources);
}
+
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform (After-Transform Update)
+ * \{ */
+
/* Return if we need to update motion paths, only if they already exist,
* and we will insert a keyframe at the end of transform. */
bool motionpath_need_update_pose(Scene *scene, Object *ob)
@@ -1686,13 +1783,12 @@ bool motionpath_need_update_pose(Scene *scene, Object *ob)
static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t)
{
- SpaceClip *sc = t->sa->spacedata.first;
+ SpaceClip *sc = t->area->spacedata.first;
MovieClip *clip = ED_space_clip_get_clip(sc);
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
const int framenr = ED_space_clip_get_clip_frame_number(sc);
/* Update coordinates of modified plane tracks. */
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track;
- plane_track = plane_track->next) {
+ LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
bool do_update = false;
if (plane_track->flag & PLANE_TRACK_HIDDEN) {
continue;
@@ -1728,11 +1824,11 @@ static void special_aftertrans_update__mask(bContext *C, TransInfo *t)
Mask *mask = NULL;
if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
+ SpaceClip *sc = t->area->spacedata.first;
mask = ED_space_clip_get_mask(sc);
}
else if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = t->sa->spacedata.first;
+ SpaceImage *sima = t->area->spacedata.first;
mask = ED_space_image_get_mask(sima);
}
else {
@@ -1763,7 +1859,7 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t)
if (canceled && t->remove_on_cancel) {
/* remove selected nodes on cancel */
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+ SpaceNode *snode = (SpaceNode *)t->area->spacedata.first;
bNodeTree *ntree = snode->edittree;
if (ntree) {
bNode *node, *node_next;
@@ -1779,8 +1875,8 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t)
static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
{
- /* so automerge supports mirror */
- if ((t->scene->toolsettings->automerge) && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) {
+ bool use_automerge = (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0;
+ if (use_automerge && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) {
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
@@ -1806,14 +1902,12 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
hflag = BM_ELEM_SELECT;
}
- if (t->scene->toolsettings->automerge & AUTO_MERGE) {
- if (t->scene->toolsettings->automerge & AUTO_MERGE_AND_SPLIT) {
- EDBM_automerge_and_split(
- tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit);
- }
- else {
- EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit);
- }
+ if (t->flag & T_AUTOSPLIT) {
+ EDBM_automerge_and_split(
+ tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit);
+ }
+ else {
+ EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit);
}
/* Special case, this is needed or faces won't re-select.
@@ -1870,13 +1964,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
else {
if (t->mode == TFM_EDGE_SLIDE) {
- EdgeSlideParams *slp = t->custom.mode.data;
- slp->perc = 0.0;
projectEdgeSlideData(t, false);
}
else if (t->mode == TFM_VERT_SLIDE) {
- EdgeSlideParams *slp = t->custom.mode.data;
- slp->perc = 0.0;
projectVertSlideData(t, false);
}
}
@@ -1890,7 +1980,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
/* freeSeqData in transform_conversions.c does this
* keep here so the else at the end wont run... */
- SpaceSeq *sseq = (SpaceSeq *)t->sa->spacedata.first;
+ SpaceSeq *sseq = (SpaceSeq *)t->area->spacedata.first;
/* Marker transform, not especially nice but we may want to move markers
* at the same time as strips in the Video Sequencer. */
@@ -1916,16 +2006,16 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
}
else if (t->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+ SpaceNode *snode = (SpaceNode *)t->area->spacedata.first;
special_aftertrans_update__node(C, t);
if (canceled == 0) {
ED_node_post_apply_transform(C, snode->edittree);
- ED_node_link_insert(bmain, t->sa);
+ ED_node_link_insert(bmain, t->area);
}
/* clear link line */
- ED_node_link_intersect_test(t->sa, 0);
+ ED_node_link_intersect_test(t->area, 0);
}
else if (t->spacetype == SPACE_CLIP) {
if (t->options & CTX_MOVIECLIP) {
@@ -1936,7 +2026,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
}
else if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+ SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
bAnimContext ac;
/* initialize relevant anim-context 'context' data */
@@ -2015,15 +2105,24 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
* but we made duplicates, so get rid of these
*/
if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
- bGPdata *gpd;
+ ListBase anim_data = {NULL, NULL};
+ const int filter = ANIMFILTER_DATA_VISIBLE;
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- // XXX: BAD! this get gpencil datablocks directly from main db...
- // but that's how this currently works :/
- for (gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- if (ID_REAL_USERS(gpd)) {
- posttrans_gpd_clean(gpd);
+ LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
+ if (ale->datatype == ALE_GPFRAME) {
+ ale->id->tag |= LIB_TAG_DOIT;
+ }
+ }
+ LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
+ if (ale->datatype == ALE_GPFRAME) {
+ if (ale->id->tag & LIB_TAG_DOIT) {
+ ale->id->tag &= ~LIB_TAG_DOIT;
+ posttrans_gpd_clean((bGPdata *)ale->id);
+ }
}
}
+ ANIM_animdata_freelist(&anim_data);
}
}
else if (ac.datatype == ANIMCONT_MASK) {
@@ -2037,15 +2136,24 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
* User canceled the transform, but we made duplicates, so get rid of these.
*/
if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
- Mask *mask;
+ ListBase anim_data = {NULL, NULL};
+ const int filter = ANIMFILTER_DATA_VISIBLE;
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- // XXX: BAD! this get gpencil datablocks directly from main db...
- // but that's how this currently works :/
- for (mask = bmain->masks.first; mask; mask = mask->id.next) {
- if (ID_REAL_USERS(mask)) {
- posttrans_mask_clean(mask);
+ LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
+ if (ale->datatype == ALE_MASKLAY) {
+ ale->id->tag |= LIB_TAG_DOIT;
}
}
+ LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
+ if (ale->datatype == ALE_MASKLAY) {
+ if (ale->id->tag & LIB_TAG_DOIT) {
+ ale->id->tag &= ~LIB_TAG_DOIT;
+ posttrans_mask_clean((Mask *)ale->id);
+ }
+ }
+ }
+ ANIM_animdata_freelist(&anim_data);
}
}
@@ -2074,7 +2182,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
/* make sure all F-Curves are set correctly */
- if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ if (!ELEM(ac.datatype, ANIMCONT_GPENCIL)) {
ANIM_editkeyframes_refresh(&ac);
}
@@ -2082,7 +2190,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
saction->flag &= ~SACTION_MOVING;
}
else if (t->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
bAnimContext ac;
const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
@@ -2171,9 +2279,8 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
else if (t->flag & T_EDIT) {
if (t->obedit_type == OB_MESH) {
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
/* table needs to be created for each edit command, since vertices can move etc */
- ED_mesh_mirror_spatial_table(tc->obedit, em, NULL, NULL, 'e');
+ ED_mesh_mirror_spatial_table_end(tc->obedit);
/* TODO(campbell): xform: We need support for many mirror objects at once! */
break;
}
@@ -2208,7 +2315,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
/* set BONE_TRANSFORM flags for autokey, gizmo draw might have changed them */
if (!canceled && (t->mode != TFM_DUMMY)) {
- count_set_pose_transflags(ob, t->mode, t->around, NULL);
+ transform_convert_pose_transflags_update(ob, t->mode, t->around, NULL);
}
/* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
@@ -2360,6 +2467,10 @@ int special_transform_moving(TransInfo *t)
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Transform Data Create
+ * \{ */
+
static int countAndCleanTransDataContainer(TransInfo *t)
{
BLI_assert(ELEM(t->data_len_all, 0, -1));
@@ -2518,7 +2629,7 @@ void createTransData(bContext *C, TransInfo *t)
t->obedit_type = -1;
t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */
- createTransSeqData(C, t);
+ createTransSeqData(t);
countAndCleanTransDataContainer(t);
}
else if (t->spacetype == SPACE_GRAPH) {
@@ -2659,7 +2770,7 @@ void createTransData(bContext *C, TransInfo *t)
/* important that ob_armature can be set even when its not selected [#23412]
* lines below just check is also visible */
has_transform_context = false;
- Object *ob_armature = modifiers_isDeformedByArmature(ob);
+ Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob);
if (ob_armature && ob_armature->mode & OB_MODE_POSE) {
Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature);
if (base_arm) {
@@ -2698,9 +2809,11 @@ void createTransData(bContext *C, TransInfo *t)
has_transform_context = false;
}
}
- else if ((ob) &&
- (ELEM(
- ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL))) {
+ else if ((ob) && (ELEM(ob->mode,
+ OB_MODE_PAINT_GPENCIL,
+ OB_MODE_SCULPT_GPENCIL,
+ OB_MODE_WEIGHT_GPENCIL,
+ OB_MODE_VERTEX_GPENCIL))) {
/* In grease pencil all transformations must be canceled if not Object or Edit. */
has_transform_context = false;
}
@@ -2726,16 +2839,16 @@ void createTransData(bContext *C, TransInfo *t)
}
/* Check if we're transforming the camera from the camera */
- if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
+ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
View3D *v3d = t->view;
- RegionView3D *rv3d = t->ar->regiondata;
+ RegionView3D *rv3d = t->region->regiondata;
if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
/* we could have a flag to easily check an object is being transformed */
if (v3d->camera->id.tag & LIB_TAG_DOIT) {
t->flag |= T_CAMERA;
}
}
- else if (v3d->ob_centre && v3d->ob_centre->id.tag & LIB_TAG_DOIT) {
+ else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) {
t->flag |= T_CAMERA;
}
}
@@ -2752,3 +2865,5 @@ void createTransData(bContext *C, TransInfo *t)
BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1)));
}
+
+/** \} */
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index 53ff9952d05..e5d758135e2 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -19,6 +19,7 @@
/** \file
* \ingroup edtransform
+ * \brief conversion and adaptation of different datablocks to a common struct.
*/
#ifndef __TRANSFORM_CONVERT_H__
@@ -36,10 +37,10 @@ struct bKinematicConstraint;
struct bPoseChannel;
/* transform_convert.c */
-int count_set_pose_transflags(Object *ob,
- const int mode,
- const short around,
- bool has_translate_rotate[2]);
+int transform_convert_pose_transflags_update(Object *ob,
+ const int mode,
+ const short around,
+ bool has_translate_rotate[2]);
void transform_autoik_update(TransInfo *t, short mode);
void autokeyframe_object(struct bContext *C,
struct Scene *scene,
@@ -60,81 +61,111 @@ void clipUVData(TransInfo *t);
/* transform_convert_action.c */
void flushTransIntFrameActionData(TransInfo *t);
+
/* transform_convert_armature.c */
+void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object *ob);
void restoreMirrorPoseBones(TransDataContainer *tc);
void restoreBones(TransDataContainer *tc);
+
/* transform_convert_graph.c */
void flushTransGraphData(TransInfo *t);
+
/* transform_convert_mask.c */
void flushTransMasking(TransInfo *t);
+
/* transform_convert_mesh.c */
void flushTransUVs(TransInfo *t);
void trans_mesh_customdata_correction_init(TransInfo *t);
void trans_mesh_customdata_correction_apply(struct TransDataContainer *tc, bool is_final);
+
/* transform_convert_node.c */
void flushTransNodes(TransInfo *t);
+
/* transform_convert_object.c */
void trans_obdata_in_obmode_update_all(struct TransInfo *t);
void trans_obchild_in_obmode_update_all(struct TransInfo *t);
+
/* transform_convert_paintcurve.c */
void flushTransPaintCurve(TransInfo *t);
+
/* transform_convert_particle.c */
void flushTransParticles(TransInfo *t);
+
/* transform_convert_sequencer.c */
void flushTransSeq(TransInfo *t);
+
/* transform_convert_tracking.c */
void flushTransTracking(TransInfo *t);
/********************* intern **********************/
/* transform_convert.c */
+bool transform_mode_use_local_origins(const TransInfo *t);
void transform_around_single_fallback(TransInfo *t);
bool constraints_list_needinv(TransInfo *t, ListBase *list);
void calc_distanceCurveVerts(TransData *head, TransData *tail);
struct TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt);
+char transform_convert_frame_side_dir_get(TransInfo *t, float cframe);
bool FrameOnMouseSide(char side, float frame, float cframe);
/* transform_convert_action.c */
void createTransActionData(bContext *C, TransInfo *t);
+
/* transform_convert_armature.c */
struct bKinematicConstraint *has_targetless_ik(struct bPoseChannel *pchan);
void createTransPose(TransInfo *t);
void createTransArmatureVerts(TransInfo *t);
+
/* transform_convert_cursor.c */
void createTransCursor_image(TransInfo *t);
void createTransCursor_view3d(TransInfo *t);
+
/* transform_convert_curve.c */
void createTransCurveVerts(TransInfo *t);
+
/* transform_convert_graph.c */
void createTransGraphEditData(bContext *C, TransInfo *t);
+
/* transform_convert_gpencil.c */
void createTransGPencil(bContext *C, TransInfo *t);
+
/* transform_convert_lattice.c */
void createTransLatticeVerts(TransInfo *t);
+
/* transform_convert_mask.c */
void createTransMaskingData(bContext *C, TransInfo *t);
+
/* transform_convert_mball.c */
void createTransMBallVerts(TransInfo *t);
+
/* transform_convert_mesh.c */
void createTransEditVerts(TransInfo *t);
void createTransEdge(TransInfo *t);
void createTransUVs(bContext *C, TransInfo *t);
+
/* transform_convert_nla.c */
void createTransNlaData(bContext *C, TransInfo *t);
+
/* transform_convert_node.c */
void createTransNodeData(bContext *UNUSED(C), TransInfo *t);
+
/* transform_convert_object.c */
void clear_trans_object_base_flags(TransInfo *t);
void createTransObject(bContext *C, TransInfo *t);
void createTransTexspace(TransInfo *t);
+
/* transform_convert_paintcurve.c */
void createTransPaintCurveVerts(bContext *C, TransInfo *t);
+
/* transform_convert_particle.c */
void createTransParticleVerts(bContext *C, TransInfo *t);
+
/* transform_convert_sculpt.c */
void createTransSculpt(TransInfo *t);
+
/* transform_convert_sequence.c */
-void createTransSeqData(bContext *C, TransInfo *t);
+void createTransSeqData(TransInfo *t);
+
/* transform_convert_tracking.c */
void createTransTrackingData(bContext *C, TransInfo *t);
void cancelTransTracking(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_convert_action.c b/source/blender/editors/transform/transform_convert_action.c
index 0b1d2757435..21ef1539911 100644
--- a/source/blender/editors/transform/transform_convert_action.c
+++ b/source/blender/editors/transform/transform_convert_action.c
@@ -30,14 +30,12 @@
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_nla.h"
#include "BKE_report.h"
#include "ED_anim_api.h"
-#include "UI_view2d.h"
-
#include "transform.h"
#include "transform_convert.h"
@@ -299,8 +297,8 @@ void createTransActionData(bContext *C, TransInfo *t)
TransData2D *td2d = NULL;
tGPFtransdata *tfd = NULL;
- rcti *mask = &t->ar->v2d.mask;
- rctf *datamask = &t->ar->v2d.cur;
+ rcti *mask = &t->region->v2d.mask;
+ rctf *datamask = &t->region->v2d.cur;
float xsize = BLI_rctf_size_x(datamask);
float ysize = BLI_rctf_size_y(datamask);
@@ -315,7 +313,7 @@ void createTransActionData(bContext *C, TransInfo *t)
int count = 0;
float cfra;
- float ypos = 1.0f / ((ysize / xsize) * (xmask / ymask)) * BLI_rctf_cent_y(&t->ar->v2d.cur);
+ float ypos = 1.0f / ((ysize / xsize) * (xmask / ymask)) * BLI_rctf_cent_y(&t->region->v2d.cur);
/* determine what type of data we are operating on */
if (ANIM_animdata_get_context(C, &ac) == 0) {
@@ -333,11 +331,7 @@ void createTransActionData(bContext *C, TransInfo *t)
/* which side of the current frame should be allowed */
if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA);
}
else {
/* normal transform - both sides of current frame are considered */
diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c
index 0edf55ece7e..35bb7e3f0d8 100644
--- a/source/blender/editors/transform/transform_convert_armature.c
+++ b/source/blender/editors/transform/transform_convert_armature.c
@@ -26,6 +26,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BKE_action.h"
@@ -45,23 +46,47 @@
#include "transform.h"
#include "transform_convert.h"
-bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
+typedef struct BoneInitData {
+ struct EditBone *bone;
+ float tail[3];
+ float rad_head;
+ float rad_tail;
+ float roll;
+ float head[3];
+ float dist;
+ float xwidth;
+ float zwidth;
+} BoneInitData;
+
+static bConstraint *add_temporary_ik_constraint(bPoseChannel *pchan,
+ bKinematicConstraint *targetless_con)
{
- bConstraint *con = pchan->constraints.first;
+ bConstraint *con = BKE_constraint_add_for_pose(
+ NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
- for (; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
- bKinematicConstraint *data = con->data;
+ /* for draw, but also for detecting while pose solving */
+ pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET);
- if (data->tar == NULL) {
- return data;
- }
- if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0) {
- return data;
- }
- }
+ bKinematicConstraint *temp_con_data = con->data;
+
+ if (targetless_con) {
+ /* if exists, use values from last targetless (but disabled) IK-constraint as base */
+ *temp_con_data = *targetless_con;
}
- return NULL;
+ else {
+ temp_con_data->flag = CONSTRAINT_IK_TIP;
+ }
+
+ temp_con_data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO | CONSTRAINT_IK_POS;
+
+ return con;
+}
+
+static void update_deg_with_temporary_ik(Main *bmain, Object *ob)
+{
+ BIK_clear_data(ob->pose);
+ /* TODO(sergey): Consider doing partial update only. */
+ DEG_relations_tag_update(bmain);
}
static void add_pose_transdata(
@@ -206,8 +231,16 @@ static void add_pose_transdata(
}
td->loc = data->grabtarget;
copy_v3_v3(td->iloc, td->loc);
+
data->flag |= CONSTRAINT_IK_AUTO;
+ /* Add a temporary auto IK constraint here, as we will only temporarily active this
+ * targetless bone during transform. (Targetless IK constraints are treated as if they are
+ * disabled unless they are transformed). */
+ add_temporary_ik_constraint(pchan, data);
+ Main *bmain = CTX_data_main(t->context);
+ update_deg_with_temporary_ik(bmain, ob);
+
/* only object matrix correction */
copy_m3_m3(td->mtx, omat);
pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
@@ -218,6 +251,30 @@ static void add_pose_transdata(
td->con = pchan->constraints.first;
}
+/* -------------------------------------------------------------------- */
+/** \name Pose Auto-IK
+ * \{ */
+
+bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
+{
+ bConstraint *con = pchan->constraints.first;
+
+ for (; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->flag & CONSTRAINT_OFF) == 0 &&
+ (con->enforce != 0.0f)) {
+ bKinematicConstraint *data = con->data;
+
+ if (data->tar == NULL) {
+ return data;
+ }
+ if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0) {
+ return data;
+ }
+ }
+ }
+ return NULL;
+}
+
/* adds the IK to pchan - returns if added */
static short pose_grab_with_ik_add(bPoseChannel *pchan)
{
@@ -232,7 +289,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan)
/* Rule: not if there's already an IK on this channel */
for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->flag & CONSTRAINT_OFF) == 0) {
data = con->data;
if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == '\0')) {
@@ -247,22 +304,20 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan)
/* if no chain length has been specified,
* just make things obey standard rotation locks too */
if (data->rootbone == 0) {
- for (; pchan; pchan = pchan->parent) {
+ for (bPoseChannel *pchan_iter = pchan; pchan_iter; pchan_iter = pchan_iter->parent) {
/* here, we set ik-settings for bone from pchan->protectflag */
// XXX: careful with quats/axis-angle rotations where we're locking 4d components
- if (pchan->protectflag & OB_LOCK_ROTX) {
- pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
+ if (pchan_iter->protectflag & OB_LOCK_ROTX) {
+ pchan_iter->ikflag |= BONE_IK_NO_XDOF_TEMP;
}
- if (pchan->protectflag & OB_LOCK_ROTY) {
- pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
+ if (pchan_iter->protectflag & OB_LOCK_ROTY) {
+ pchan_iter->ikflag |= BONE_IK_NO_YDOF_TEMP;
}
- if (pchan->protectflag & OB_LOCK_ROTZ) {
- pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
+ if (pchan_iter->protectflag & OB_LOCK_ROTZ) {
+ pchan_iter->ikflag |= BONE_IK_NO_ZDOF_TEMP;
}
}
}
-
- return 0;
}
}
@@ -272,20 +327,8 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan)
}
}
- con = BKE_constraint_add_for_pose(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
+ data = add_temporary_ik_constraint(pchan, targetless)->data;
- /* for draw, but also for detecting while pose solving */
- pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET);
-
- data = con->data;
- if (targetless) {
- /* if exists, use values from last targetless (but disabled) IK-constraint as base */
- *data = *targetless;
- }
- else {
- data->flag = CONSTRAINT_IK_TIP;
- }
- data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO | CONSTRAINT_IK_POS;
copy_v3_v3(data->grabtarget, pchan->pose_tail);
/* watch-it! has to be 0 here, since we're still on the
@@ -398,14 +441,42 @@ static short pose_grab_with_ik(Main *bmain, Object *ob)
/* iTaSC needs clear for new IK constraints */
if (tot_ik) {
- BIK_clear_data(ob->pose);
- /* TODO(sergey): Consider doing partial update only. */
- DEG_relations_tag_update(bmain);
+ update_deg_with_temporary_ik(bmain, ob);
}
return (tot_ik) ? 1 : 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pose Mirror
+ * \{ */
+
+typedef struct PoseInitData_Mirror {
+ /** Points to the bone which this info is initialized & restored to.
+ * A NULL value is used to terminate the array. */
+ struct bPoseChannel *pchan;
+ struct {
+ float loc[3];
+ float size[3];
+ union {
+ float eul[3];
+ float quat[4];
+ float axis_angle[4];
+ };
+ float curve_in_x;
+ float curve_out_x;
+ float roll1;
+ float roll2;
+ } orig;
+ /**
+ * An extra offset to apply after mirroring.
+ * Use with #POSE_MIRROR_RELATIVE.
+ */
+ float offset_mtx[4][4];
+} PoseInitData_Mirror;
+
static void pose_mirror_info_init(PoseInitData_Mirror *pid,
bPoseChannel *pchan,
bPoseChannel *pchan_orig,
@@ -475,6 +546,103 @@ static void pose_mirror_info_restore(const PoseInitData_Mirror *pid)
}
/**
+ * if pose bone (partial) selected, copy data.
+ * context; posemode armature, with mirror editing enabled.
+ */
+void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object *ob)
+{
+ float flip_mtx[4][4];
+ unit_m4(flip_mtx);
+ flip_mtx[0][0] = -1;
+
+ LISTBASE_FOREACH (bPoseChannel *, pchan_orig, &ob->pose->chanbase) {
+ /* Clear the MIRROR flag from previous runs. */
+ pchan_orig->bone->flag &= ~BONE_TRANSFORM_MIRROR;
+ }
+
+ bPose *pose = ob->pose;
+ PoseInitData_Mirror *pid = NULL;
+ if ((t->mode != TFM_BONESIZE) && (pose->flag & POSE_MIRROR_RELATIVE)) {
+ pid = tc->custom.type.data;
+ }
+
+ TransData *td = tc->data;
+ for (int i = tc->data_len; i--; td++) {
+ bPoseChannel *pchan_orig = td->extra;
+ BLI_assert(pchan_orig->bone->flag & BONE_TRANSFORM);
+ /* No layer check, correct mirror is more important. */
+ bPoseChannel *pchan = BKE_pose_channel_get_mirrored(pose, pchan_orig->name);
+ if (pchan == NULL) {
+ continue;
+ }
+
+ /* Also do bbone scaling. */
+ pchan->bone->xwidth = pchan_orig->bone->xwidth;
+ pchan->bone->zwidth = pchan_orig->bone->zwidth;
+
+ /* We assume X-axis flipping for now. */
+ pchan->curve_in_x = pchan_orig->curve_in_x * -1;
+ pchan->curve_out_x = pchan_orig->curve_out_x * -1;
+ pchan->roll1 = pchan_orig->roll1 * -1; // XXX?
+ pchan->roll2 = pchan_orig->roll2 * -1; // XXX?
+
+ float pchan_mtx_final[4][4];
+ BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final);
+ mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx);
+ mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final);
+ if (pid) {
+ mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final);
+ }
+ BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false);
+
+ /* Set flag to let autokeyframe know to keyframe the mirrred bone. */
+ pchan->bone->flag |= BONE_TRANSFORM_MIRROR;
+
+ /* In this case we can do target-less IK grabbing. */
+ if (t->mode == TFM_TRANSLATION) {
+ bKinematicConstraint *data = has_targetless_ik(pchan);
+ if (data == NULL) {
+ continue;
+ }
+ mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc);
+ if (pid) {
+ /* TODO(germano): Realitve Mirror support */
+ }
+ data->flag |= CONSTRAINT_IK_AUTO;
+ /* Add a temporary auto IK constraint here, as we will only temporarily active this
+ * target-less bone during transform. (Target-less IK constraints are treated as if they are
+ * disabled unless they are transformed) */
+ add_temporary_ik_constraint(pchan, data);
+ Main *bmain = CTX_data_main(t->context);
+ update_deg_with_temporary_ik(bmain, ob);
+ }
+
+ if (pid) {
+ pid++;
+ }
+ }
+}
+
+void restoreMirrorPoseBones(TransDataContainer *tc)
+{
+ bPose *pose = tc->poseobj->pose;
+
+ if (!(pose->flag & POSE_MIRROR_EDIT)) {
+ return;
+ }
+
+ for (PoseInitData_Mirror *pid = tc->custom.type.data; pid->pchan; pid++) {
+ pose_mirror_info_restore(pid);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Convert Armature
+ * \{ */
+
+/**
* When objects array is NULL, use 't->data_container' as is.
*/
void createTransPose(TransInfo *t)
@@ -501,7 +669,9 @@ void createTransPose(TransInfo *t)
const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
/* set flags and count total */
- tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate);
+ tc->data_len = transform_convert_pose_transflags_update(
+ ob, t->mode, t->around, has_translate_rotate);
+
if (tc->data_len == 0) {
continue;
}
@@ -516,7 +686,10 @@ void createTransPose(TransInfo *t)
if (mirror) {
int total_mirrored = 0;
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ /* Clear the MIRROR flag from previous runs. */
+ pchan->bone->flag &= ~BONE_TRANSFORM_MIRROR;
+
if ((pchan->bone->flag & BONE_TRANSFORM) &&
BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) {
total_mirrored++;
@@ -566,7 +739,7 @@ void createTransPose(TransInfo *t)
}
if (mirror) {
- for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
if (pchan->bone->flag & BONE_TRANSFORM) {
bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name);
if (pchan_mirror) {
@@ -588,7 +761,7 @@ void createTransPose(TransInfo *t)
/* use pose channels to fill trans data */
td = tc->data;
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
if (pchan->bone->flag & BONE_TRANSFORM) {
add_pose_transdata(t, pchan, ob, tc, td);
td++;
@@ -620,19 +793,6 @@ void createTransPose(TransInfo *t)
t->flag &= ~T_PROP_EDIT_ALL;
}
-void restoreMirrorPoseBones(TransDataContainer *tc)
-{
- bPose *pose = tc->poseobj->pose;
-
- if (!(pose->flag & POSE_MIRROR_EDIT)) {
- return;
- }
-
- for (PoseInitData_Mirror *pid = tc->custom.type.data; pid->pchan; pid++) {
- pose_mirror_info_restore(pid);
- }
-}
-
void restoreBones(TransDataContainer *tc)
{
bArmature *arm;
@@ -682,7 +842,6 @@ void restoreBones(TransDataContainer *tc)
}
}
-/* ********************* armature ************** */
void createTransArmatureVerts(TransInfo *t)
{
t->data_len_all = 0;
@@ -936,3 +1095,5 @@ void createTransArmatureVerts(TransInfo *t)
}
}
}
+
+/** \} */
diff --git a/source/blender/editors/transform/transform_convert_cursor.c b/source/blender/editors/transform/transform_convert_cursor.c
index 621f9dd63e2..e6a972bfc7c 100644
--- a/source/blender/editors/transform/transform_convert_cursor.c
+++ b/source/blender/editors/transform/transform_convert_cursor.c
@@ -44,7 +44,7 @@
void createTransCursor_image(TransInfo *t)
{
TransData *td;
- SpaceImage *sima = t->sa->spacedata.first;
+ SpaceImage *sima = t->area->spacedata.first;
float *cursor_location = sima->cursor;
{
diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c
index 487de27aff2..42ffe675dc5 100644
--- a/source/blender/editors/transform/transform_convert_curve.c
+++ b/source/blender/editors/transform/transform_convert_curve.c
@@ -25,11 +25,11 @@
#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_report.h"
#include "transform.h"
#include "transform_convert.h"
@@ -99,7 +99,7 @@ void createTransCurveVerts(TransInfo *t)
/* count total of vertices, check identical as in 2nd loop for making transdata! */
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, nurbs) {
if (nu->type == CU_BEZIER) {
for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
if (bezt->hide == 0) {
@@ -167,6 +167,8 @@ void createTransCurveVerts(TransInfo *t)
((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
false;
+ bool use_around_origins_for_handles_test = ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ transform_mode_use_local_origins(t));
float mtx[3][3], smtx[3][3];
copy_m3_m4(mtx, tc->obedit->obmat);
@@ -174,7 +176,7 @@ void createTransCurveVerts(TransInfo *t)
TransData *td = tc->data;
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, nurbs) {
if (nu->type == CU_BEZIER) {
TransData *head, *tail;
head = tail = td;
@@ -342,7 +344,7 @@ void createTransCurveVerts(TransInfo *t)
if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
/* sets the handles based on their selection,
* do this after the data is copied to the TransData */
- BKE_nurb_handles_test(nu, !hide_handles);
+ BKE_nurb_handles_test(nu, !hide_handles, use_around_origins_for_handles_test);
}
}
else {
diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c
index 80c0afc3f56..efd7879c8b2 100644
--- a/source/blender/editors/transform/transform_convert_gpencil.c
+++ b/source/blender/editors/transform/transform_convert_gpencil.c
@@ -30,7 +30,6 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
-#include "BKE_report.h"
#include "ED_gpencil.h"
@@ -84,6 +83,8 @@ void createTransGPencil(bContext *C, TransInfo *t)
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
+ const bool is_scale_thickness = ((t->mode == TFM_GPENCIL_SHRINKFATTEN) ||
+ (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SCALE_THICKNESS));
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
@@ -109,7 +110,7 @@ void createTransGPencil(bContext *C, TransInfo *t)
*/
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf;
bGPDstroke *gps;
bGPDframe *init_gpf = gpl->actframe;
@@ -181,7 +182,7 @@ void createTransGPencil(bContext *C, TransInfo *t)
/* Second Pass: Build transdata array */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
bGPDframe *gpf = gpl->actframe;
bGPDstroke *gps;
@@ -197,11 +198,11 @@ void createTransGPencil(bContext *C, TransInfo *t)
int f_end = 0;
if (use_multiframe_falloff) {
- BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
+ BKE_gpencil_frame_range_selected(gpl, &f_init, &f_end);
}
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* undo matrix */
invert_m4_m4(inverse_diff_mat, diff_mat);
@@ -227,10 +228,11 @@ void createTransGPencil(bContext *C, TransInfo *t)
for (gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
- /* if multiframe and falloff, recalculate and save value */
+ /* If multi-frame and falloff, recalculate and save value. */
float falloff = 1.0f; /* by default no falloff */
if ((is_multiedit) && (use_multiframe_falloff)) {
- /* Faloff depends on distance to active frame (relative to the overall frame range) */
+ /* Falloff depends on distance to active frame
+ * (relative to the overall frame range). */
falloff = BKE_gpencil_multiframe_falloff_calc(
gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
}
@@ -313,9 +315,9 @@ void createTransGPencil(bContext *C, TransInfo *t)
}
/* for other transform modes (e.g. shrink-fatten), need to additional data
- * but never for scale or mirror
+ * but never for mirror
*/
- if ((t->mode != TFM_RESIZE) && (t->mode != TFM_MIRROR)) {
+ if ((t->mode != TFM_MIRROR) && (is_scale_thickness)) {
if (t->mode != TFM_GPENCIL_OPACITY) {
td->val = &pt->pressure;
td->ival = pt->pressure;
diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c
index f6f982e854a..f6f0dd3c491 100644
--- a/source/blender/editors/transform/transform_convert_graph.c
+++ b/source/blender/editors/transform/transform_convert_graph.c
@@ -1,4 +1,4 @@
-/*
+/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -167,7 +167,7 @@ static void graph_bezt_get_transform_selection(const TransInfo *t,
bool *r_key,
bool *r_right_handle)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
bool key = (bezt->f2 & SELECT) != 0;
bool left = use_handle ? ((bezt->f1 & SELECT) != 0) : key;
bool right = use_handle ? ((bezt->f3 & SELECT) != 0) : key;
@@ -224,10 +224,10 @@ static void graph_key_shortest_dist(
*/
void createTransGraphEditData(bContext *C, TransInfo *t)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
Scene *scene = t->scene;
- ARegion *ar = t->ar;
- View2D *v2d = &ar->v2d;
+ ARegion *region = t->region;
+ View2D *v2d = &region->v2d;
TransData *td = NULL;
TransData2D *td2d = NULL;
@@ -261,11 +261,7 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
/* which side of the current frame should be allowed */
// XXX we still want this mode, but how to get this using standard transform too?
if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA);
}
else {
/* normal transform - both sides of current frame are considered */
@@ -643,7 +639,7 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
*/
void flushTransGraphData(TransInfo *t)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
TransData *td;
TransData2D *td2d;
TransDataGraph *tdg;
diff --git a/source/blender/editors/transform/transform_convert_lattice.c b/source/blender/editors/transform/transform_convert_lattice.c
index 15af24090f0..57d0f707971 100644
--- a/source/blender/editors/transform/transform_convert_lattice.c
+++ b/source/blender/editors/transform/transform_convert_lattice.c
@@ -29,7 +29,6 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "transform.h"
#include "transform_convert.h"
diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c
index 32152442acf..6c743da3e65 100644
--- a/source/blender/editors/transform/transform_convert_mask.c
+++ b/source/blender/editors/transform/transform_convert_mask.c
@@ -280,7 +280,7 @@ void createTransMaskingData(bContext *C, TransInfo *t)
}
if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
+ SpaceClip *sc = t->area->spacedata.first;
MovieClip *clip = ED_space_clip_get_clip(sc);
if (!clip) {
return;
@@ -333,7 +333,7 @@ void createTransMaskingData(bContext *C, TransInfo *t)
return;
}
- ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
+ ED_mask_get_aspect(t->area, t->region, &asp[0], &asp[1]);
tc->data_len = (is_prop_edit) ? count : countsel;
td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Mask Editing)");
@@ -409,7 +409,7 @@ void flushTransMasking(TransInfo *t)
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
+ ED_mask_get_aspect(t->area, t->region, &asp[0], &asp[1]);
inv[0] = 1.0f / asp[0];
inv[1] = 1.0f / asp[1];
diff --git a/source/blender/editors/transform/transform_convert_mball.c b/source/blender/editors/transform/transform_convert_mball.c
index 5d7e36cc834..447733357d6 100644
--- a/source/blender/editors/transform/transform_convert_mball.c
+++ b/source/blender/editors/transform/transform_convert_mball.c
@@ -28,7 +28,6 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "transform.h"
#include "transform_convert.h"
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 5d3d1d936a2..24dda8c8464 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -29,9 +29,9 @@
#include "BLI_alloca.h"
#include "BLI_bitmap.h"
+#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
-#include "BLI_linklist_stack.h"
#include "BKE_context.h"
#include "BKE_crazyspace.h"
@@ -61,8 +61,10 @@
/* when transforming islands */
struct TransIslandData {
- float co[3];
- float axismtx[3][3];
+ float (*center)[3];
+ float (*axismtx)[3][3];
+ int island_tot;
+ int *island_vert_map;
};
/* -------------------------------------------------------------------- */
@@ -247,18 +249,19 @@ static void editmesh_set_connectivity_distance(BMesh *bm,
}
}
-static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
- int *r_island_tot,
- int **r_island_vert_map,
- bool calc_single_islands)
+static void editmesh_islands_info_calc(BMEditMesh *em,
+ const bool calc_single_islands,
+ const bool calc_island_axismtx,
+ struct TransIslandData *r_island_data)
{
BMesh *bm = em->bm;
- struct TransIslandData *trans_islands;
char htype;
char itype;
int i;
/* group vars */
+ float(*center)[3];
+ float(*axismtx)[3][3] = NULL;
int *groups_array;
int(*group_index)[2];
int group_tot;
@@ -283,7 +286,11 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
itype = BM_VERTS_OF_FACE;
}
- trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__);
+ center = MEM_mallocN(sizeof(*center) * group_tot, __func__);
+
+ if (calc_island_axismtx) {
+ axismtx = MEM_mallocN(sizeof(*axismtx) * group_tot, __func__);
+ }
vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
/* we shouldn't need this, but with incorrect selection flushing
@@ -311,7 +318,7 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
ese.htype = htype;
- /* loop on each face in this group:
+ /* loop on each face or edge in this group:
* - assign r_vert_map
* - calculate (co, no)
*/
@@ -321,12 +328,14 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
ese.ele = ele_array[groups_array[fg_sta + j]];
BM_editselection_center(&ese, tmp_co);
- BM_editselection_normal(&ese, tmp_no);
- BM_editselection_plane(&ese, tmp_tangent);
-
add_v3_v3(co, tmp_co);
- add_v3_v3(no, tmp_no);
- add_v3_v3(tangent, tmp_tangent);
+
+ if (axismtx) {
+ BM_editselection_normal(&ese, tmp_no);
+ BM_editselection_plane(&ese, tmp_tangent);
+ add_v3_v3(no, tmp_no);
+ add_v3_v3(tangent, tmp_tangent);
+ }
{
/* setup vertex map */
@@ -340,18 +349,20 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
}
}
- mul_v3_v3fl(trans_islands[i].co, co, 1.0f / (float)fg_len);
+ mul_v3_v3fl(center[i], co, 1.0f / (float)fg_len);
- if (createSpaceNormalTangent(trans_islands[i].axismtx, no, tangent)) {
- /* pass */
- }
- else {
- if (normalize_v3(no) != 0.0f) {
- axis_dominant_v3_to_m3(trans_islands[i].axismtx, no);
- invert_m3(trans_islands[i].axismtx);
+ if (axismtx) {
+ if (createSpaceNormalTangent(axismtx[i], no, tangent)) {
+ /* pass */
}
else {
- unit_m3(trans_islands[i].axismtx);
+ if (normalize_v3(no) != 0.0f) {
+ axis_dominant_v3_to_m3(axismtx[i], no);
+ invert_m3(axismtx[i]);
+ }
+ else {
+ unit_m3(axismtx[i]);
+ }
}
}
}
@@ -372,22 +383,24 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
}
if (group_tot_single != 0) {
- trans_islands = MEM_reallocN(trans_islands,
- sizeof(*trans_islands) * (group_tot + group_tot_single));
+ center = MEM_reallocN(center, sizeof(*center) * (group_tot + group_tot_single));
+ if (axismtx) {
+ axismtx = MEM_reallocN(axismtx, sizeof(*axismtx) * (group_tot + group_tot_single));
+ }
BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
- struct TransIslandData *v_island = &trans_islands[group_tot];
vert_map[i] = group_tot;
+ copy_v3_v3(center[group_tot], v->co);
- copy_v3_v3(v_island->co, v->co);
-
- if (is_zero_v3(v->no) != 0.0f) {
- axis_dominant_v3_to_m3(v_island->axismtx, v->no);
- invert_m3(v_island->axismtx);
- }
- else {
- unit_m3(v_island->axismtx);
+ if (axismtx) {
+ if (is_zero_v3(v->no) != 0.0f) {
+ axis_dominant_v3_to_m3(axismtx[group_tot], v->no);
+ invert_m3(axismtx[group_tot]);
+ }
+ else {
+ unit_m3(axismtx[group_tot]);
+ }
}
group_tot += 1;
@@ -396,10 +409,10 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
}
}
- *r_island_tot = group_tot;
- *r_island_vert_map = vert_map;
-
- return trans_islands;
+ r_island_data->axismtx = axismtx;
+ r_island_data->center = center;
+ r_island_data->island_tot = group_tot;
+ r_island_data->island_vert_map = vert_map;
}
static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const float epsilon)
@@ -567,7 +580,8 @@ static void VertsToTransData(TransInfo *t,
BMEditMesh *em,
BMVert *eve,
float *bweight,
- struct TransIslandData *v_island,
+ const struct TransIslandData *island_data,
+ const int island_index,
const bool no_island_center)
{
float *no, _no[3];
@@ -589,14 +603,17 @@ static void VertsToTransData(TransInfo *t,
no = eve->no;
}
- if (v_island) {
+ if (island_index != -1) {
if (no_island_center) {
copy_v3_v3(td->center, td->loc);
}
else {
- copy_v3_v3(td->center, v_island->co);
+ copy_v3_v3(td->center, island_data->center[island_index]);
}
- copy_m3_m3(td->axismtx, v_island->axismtx);
+ }
+
+ if ((island_index != -1) && island_data->axismtx) {
+ copy_m3_m3(td->axismtx, island_data->axismtx[island_index]);
}
else if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
copy_v3_v3(td->center, td->loc);
@@ -654,9 +671,7 @@ void createTransEditVerts(TransInfo *t)
const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
int cd_vert_bweight_offset = -1;
- struct TransIslandData *island_info = NULL;
- int island_info_tot;
- int *island_vert_map = NULL;
+ struct TransIslandData island_data = {NULL};
/* Snap rotation along normal needs a common axis for whole islands,
* otherwise one get random crazy results, see T59104.
@@ -758,14 +773,17 @@ void createTransEditVerts(TransInfo *t)
(t->around == V3D_AROUND_LOCAL_ORIGINS) &&
(em->selectmode & SCE_SELECT_VERTEX));
- island_info = editmesh_islands_info_calc(
- em, &island_info_tot, &island_vert_map, calc_single_islands);
+ /* The island axismtx is only necessary in some modes.
+ * TODO(Germano): Extend the list to exclude other modes. */
+ const bool calc_island_axismtx = !ELEM(t->mode, TFM_SHRINKFATTEN);
+
+ editmesh_islands_info_calc(em, calc_single_islands, calc_island_axismtx, &island_data);
}
/* detect CrazySpace [tm] */
- if (modifiers_getCageIndex(t->scene, tc->obedit, NULL, 1) != -1) {
+ if (BKE_modifiers_get_cage_index(t->scene, tc->obedit, NULL, 1) != -1) {
int totleft = -1;
- if (modifiers_isCorrectableDeformed(t->scene, tc->obedit)) {
+ if (BKE_modifiers_is_correctable_deformed(t->scene, tc->obedit)) {
BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context));
/* Use evaluated state because we need b-bone cache. */
@@ -809,21 +827,19 @@ void createTransEditVerts(TransInfo *t)
continue;
}
if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- struct TransIslandData *v_island = NULL;
float *bweight = (cd_vert_bweight_offset != -1) ?
BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) :
NULL;
- if (island_info) {
+ int island_index = -1;
+ if (island_data.island_vert_map) {
const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
- v_island = (island_vert_map[connected_index] != -1) ?
- &island_info[island_vert_map[connected_index]] :
- NULL;
+ island_index = island_data.island_vert_map[connected_index];
}
/* Do not use the island center in case we are using islands
* only to get axis for snap/rotate to normal... */
- VertsToTransData(t, tob, tx, em, eve, bweight, v_island, is_snap_rotate);
+ VertsToTransData(t, tob, tx, em, eve, bweight, &island_data, island_index, is_snap_rotate);
if (tx) {
tx++;
}
@@ -889,9 +905,16 @@ void createTransEditVerts(TransInfo *t)
}
}
- if (island_info) {
- MEM_freeN(island_info);
- MEM_freeN(island_vert_map);
+ if (island_data.center) {
+ MEM_freeN(island_data.center);
+ }
+
+ if (island_data.axismtx) {
+ MEM_freeN(island_data.axismtx);
+ }
+
+ if (island_data.island_vert_map) {
+ MEM_freeN(island_data.island_vert_map);
}
cleanup:
@@ -1030,7 +1053,15 @@ static void create_trans_vert_customdata_layer(BMVert *v,
void trans_mesh_customdata_correction_init(TransInfo *t)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- BLI_assert(tc->custom.type.data == NULL);
+ if (tc->custom.type.data) {
+ if (tc->custom.type.free_cb == trans_mesh_customdata_free_cb) {
+ /* Custom data correction has initiated before. */
+ continue;
+ }
+ else {
+ BLI_assert(false);
+ }
+ }
int i;
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
@@ -1168,7 +1199,7 @@ static void trans_mesh_customdata_correction_apply_vert(struct TransCustomDataLa
BM_loop_interp_from_face(bm, l, f_copy, false, false);
/* make sure face-attributes are correct (e.g. #MLoopUV, #MLoopCol) */
- BM_elem_attrs_copy_ex(tcld->bm_origfaces, bm, f_copy, l->f, 0x0, CD_MASK_NORMAL);
+ BM_elem_attrs_copy_ex(tcld->bm_origfaces, bm, f_copy, l->f, BM_ELEM_SELECT, CD_MASK_NORMAL);
/* weight the loop */
if (do_loop_weight) {
@@ -1600,7 +1631,7 @@ void createTransUVs(bContext *C, TransInfo *t)
void flushTransUVs(TransInfo *t)
{
- SpaceImage *sima = t->sa->spacedata.first;
+ SpaceImage *sima = t->area->spacedata.first;
const bool use_pixel_snap = ((sima->pixel_snap_mode != SI_PIXEL_SNAP_DISABLED) &&
(t->state != TRANS_CANCEL));
diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c
index 114968ec83f..2978c36b15f 100644
--- a/source/blender/editors/transform/transform_convert_nla.c
+++ b/source/blender/editors/transform/transform_convert_nla.c
@@ -26,17 +26,15 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
-#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_nla.h"
#include "BKE_report.h"
#include "ED_anim_api.h"
-#include "UI_view2d.h"
-
#include "transform.h"
#include "transform_convert.h"
@@ -73,11 +71,7 @@ void createTransNlaData(bContext *C, TransInfo *t)
/* which side of the current frame should be allowed */
if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
+ t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA);
}
else {
/* normal transform - both sides of current frame are considered */
diff --git a/source/blender/editors/transform/transform_convert_node.c b/source/blender/editors/transform/transform_convert_node.c
index ee4aa053444..d783bfdf40e 100644
--- a/source/blender/editors/transform/transform_convert_node.c
+++ b/source/blender/editors/transform/transform_convert_node.c
@@ -109,7 +109,7 @@ void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
const float dpi_fac = UI_DPI_FAC;
TransData *td;
TransData2D *td2d;
- SpaceNode *snode = t->sa->spacedata.first;
+ SpaceNode *snode = t->area->spacedata.first;
bNode *node;
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
@@ -188,7 +188,7 @@ void flushTransNodes(TransInfo *t)
/* handle intersection with noodles */
if (tc->data_len == 1) {
- ED_node_link_intersect_test(t->sa, 1);
+ ED_node_link_intersect_test(t->area, 1);
}
}
}
diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c
index 16dfdd35c32..8deba0f7ad0 100644
--- a/source/blender/editors/transform/transform_convert_object.c
+++ b/source/blender/editors/transform/transform_convert_object.c
@@ -63,12 +63,10 @@ typedef struct TransDataObject {
* - The key is object data #Object.
* - The value is #XFormObjectSkipChild.
*/
- struct GHash *obchild_in_obmode_map;
+ struct XFormObjectSkipChild_Container *xcs;
} TransDataObject;
-static void trans_obchild_in_obmode_free_all(TransDataObject *tdo);
-
static void freeTransObjectCustomData(TransInfo *t,
TransDataContainer *UNUSED(tc),
TransCustomData *custom_data)
@@ -81,7 +79,7 @@ static void freeTransObjectCustomData(TransInfo *t,
}
if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) {
- trans_obchild_in_obmode_free_all(tdo);
+ ED_object_xform_skip_child_container_destroy(tdo->xcs);
}
MEM_freeN(tdo);
}
@@ -117,140 +115,19 @@ void trans_obdata_in_obmode_update_all(TransInfo *t)
* Don't transform unselected children, this is done using the parent inverse matrix.
*
* \note The complex logic here is caused by mixed selection within a single selection chain,
- * otherwise we only need #OB_SKIP_CHILD_PARENT_IS_XFORM for single objects.
+ * otherwise we only need #XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM for single objects.
*
* \{ */
-enum {
- /**
- * The parent is transformed, this is held in place.
- */
- OB_SKIP_CHILD_PARENT_IS_XFORM = 1,
- /**
- * The same as #OB_SKIP_CHILD_PARENT_IS_XFORM,
- * however this objects parent isn't transformed directly.
- */
- OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT = 3,
- /**
- * Use the parent invert matrix to apply transformation,
- * this is needed, because breaks in the selection chain prevents this from being transformed.
- * This is used to add the transform which would have been added
- * if there weren't breaks in the parent/child chain.
- */
- OB_SKIP_CHILD_PARENT_APPLY_TRANSFORM = 2,
-};
-
-struct XFormObjectSkipChild {
- float obmat_orig[4][4];
- float parent_obmat_orig[4][4];
- float parent_obmat_inv_orig[4][4];
- float parent_recurse_obmat_orig[4][4];
- float parentinv_orig[4][4];
- Object *ob_parent_recurse;
- int mode;
-};
-
-static void trans_obchild_in_obmode_ensure_object(TransDataObject *tdo,
- Object *ob,
- Object *ob_parent_recurse,
- int mode)
-{
- if (tdo->obchild_in_obmode_map == NULL) {
- tdo->obchild_in_obmode_map = BLI_ghash_ptr_new(__func__);
- }
-
- void **xf_p;
- if (!BLI_ghash_ensure_p(tdo->obchild_in_obmode_map, ob, &xf_p)) {
- struct XFormObjectSkipChild *xf = MEM_mallocN(sizeof(*xf), __func__);
- copy_m4_m4(xf->parentinv_orig, ob->parentinv);
- copy_m4_m4(xf->obmat_orig, ob->obmat);
- copy_m4_m4(xf->parent_obmat_orig, ob->parent->obmat);
- invert_m4_m4(xf->parent_obmat_inv_orig, ob->parent->obmat);
- if (ob_parent_recurse) {
- copy_m4_m4(xf->parent_recurse_obmat_orig, ob_parent_recurse->obmat);
- }
- xf->mode = mode;
- xf->ob_parent_recurse = ob_parent_recurse;
- *xf_p = xf;
- }
-}
-
void trans_obchild_in_obmode_update_all(TransInfo *t)
{
TransDataObject *tdo = t->custom.type.data;
- if (tdo->obchild_in_obmode_map == NULL) {
+ if (tdo->xcs == NULL) {
return;
}
struct Main *bmain = CTX_data_main(t->context);
- BKE_scene_graph_evaluated_ensure(t->depsgraph, bmain);
-
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, tdo->obchild_in_obmode_map) {
- Object *ob = BLI_ghashIterator_getKey(&gh_iter);
- struct XFormObjectSkipChild *xf = BLI_ghashIterator_getValue(&gh_iter);
-
- /* The following blocks below assign 'dmat'. */
- float dmat[4][4];
-
- if (xf->mode == OB_SKIP_CHILD_PARENT_IS_XFORM) {
- /* Parent is transformed, this isn't so compensate. */
- Object *ob_parent_eval = DEG_get_evaluated_object(t->depsgraph, ob->parent);
- mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, ob_parent_eval->obmat);
- invert_m4(dmat);
- }
- else if (xf->mode == OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT) {
- /* Calculate parent matrix (from the root transform). */
- Object *ob_parent_recurse_eval = DEG_get_evaluated_object(t->depsgraph,
- xf->ob_parent_recurse);
- float parent_recurse_obmat_inv[4][4];
- invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
- mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
- invert_m4(dmat);
- float parent_obmat_calc[4][4];
- mul_m4_m4m4(parent_obmat_calc, dmat, xf->parent_obmat_orig);
-
- /* Apply to the parent inverse matrix. */
- mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, parent_obmat_calc);
- invert_m4(dmat);
- }
- else {
- BLI_assert(xf->mode == OB_SKIP_CHILD_PARENT_APPLY_TRANSFORM);
- /* Transform this - without transform data. */
- Object *ob_parent_recurse_eval = DEG_get_evaluated_object(t->depsgraph,
- xf->ob_parent_recurse);
- float parent_recurse_obmat_inv[4][4];
- invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
- mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
- invert_m4(dmat);
- float obmat_calc[4][4];
- mul_m4_m4m4(obmat_calc, dmat, xf->obmat_orig);
- /* obmat_calc is just obmat. */
-
- /* Get the matrices relative to the parent. */
- float obmat_parent_relative_orig[4][4];
- float obmat_parent_relative_calc[4][4];
- float obmat_parent_relative_inv_orig[4][4];
-
- mul_m4_m4m4(obmat_parent_relative_orig, xf->parent_obmat_inv_orig, xf->obmat_orig);
- mul_m4_m4m4(obmat_parent_relative_calc, xf->parent_obmat_inv_orig, obmat_calc);
- invert_m4_m4(obmat_parent_relative_inv_orig, obmat_parent_relative_orig);
-
- /* Apply to the parent inverse matrix. */
- mul_m4_m4m4(dmat, obmat_parent_relative_calc, obmat_parent_relative_inv_orig);
- }
-
- mul_m4_m4m4(ob->parentinv, dmat, xf->parentinv_orig);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
-}
-
-static void trans_obchild_in_obmode_free_all(TransDataObject *tdo)
-{
- if (tdo->obchild_in_obmode_map != NULL) {
- BLI_ghash_free(tdo->obchild_in_obmode_map, NULL, MEM_freeN);
- }
+ ED_object_xform_skip_child_container_update_all(tdo->xcs, bmain, t->depsgraph);
}
/** \} */
@@ -320,7 +197,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
/* NOTE: This is not really following copy-on-write design and we should not
* be re-evaluating the evaluated object. But as the comment above mentioned
* this is part of a hack.
- * More proper solution would be to make a shallow copy of the object and
+ * More proper solution would be to make a shallow copy of the object and
* evaluate that, and access matrix of that evaluated copy of the object.
* Might be more tricky than it sounds, if some logic later on accesses the
* object matrix via td->ob->obmat. */
@@ -413,7 +290,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer)
{
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
base->object->id.tag &= ~LIB_TAG_DOIT;
}
}
@@ -447,7 +324,7 @@ static void trans_object_base_deps_flag_finish(const TransInfo *t, ViewLayer *vi
{
if ((t->options & CTX_OBMODE_XFORM_OBDATA) == 0) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->object->id.tag & LIB_TAG_DOIT) {
base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
}
@@ -478,7 +355,7 @@ static void set_trans_object_base_flags(TransInfo *t)
/* Clear all flags we need. It will be used to detect dependencies. */
trans_object_base_deps_flag_prepare(view_layer);
/* Traverse all bases and set all possible flags. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
base->flag_legacy &= ~(BA_WAS_SEL | BA_TRANSFORM_LOCKED_IN_PLACE);
if (BASE_SELECTED_EDITABLE(v3d, base)) {
Object *ob = base->object;
@@ -545,7 +422,7 @@ static int count_proportional_objects(TransInfo *t)
if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
(t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))) {
/* Mark all parents. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (BASE_SELECTED_EDITABLE(v3d, base) && BASE_SELECTABLE(v3d, base)) {
Object *parent = base->object->parent;
/* flag all parents */
@@ -556,7 +433,7 @@ static int count_proportional_objects(TransInfo *t)
}
}
/* Mark all children. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
/* all base not already selected or marked that is editable */
if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
(base->flag & BASE_SELECTED) == 0 &&
@@ -566,7 +443,7 @@ static int count_proportional_objects(TransInfo *t)
}
}
/* Flush changed flags to all dependencies. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
/* If base is not selected, not a parent of selection or not a child of
* selection and it is editable and selectable.
@@ -715,7 +592,7 @@ void createTransObject(bContext *C, TransInfo *t)
ViewLayer *view_layer = t->view_layer;
View3D *v3d = t->view;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
/* if base is not selected, not a parent of selection
@@ -746,6 +623,8 @@ void createTransObject(bContext *C, TransInfo *t)
if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) {
+ tdo->xcs = ED_object_xform_skip_child_container_create();
+
#define BASE_XFORM_INDIRECT(base) \
((base->flag_legacy & BA_WAS_SEL) && (base->flag & BASE_SELECTED) == 0)
@@ -760,7 +639,7 @@ void createTransObject(bContext *C, TransInfo *t)
ViewLayer *view_layer = t->view_layer;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
if (ob->parent != NULL) {
if (ob->parent && !BLI_gset_haskey(objects_in_transdata, ob->parent) &&
@@ -778,8 +657,8 @@ void createTransObject(bContext *C, TransInfo *t)
}
if (ob_parent_recurse) {
- trans_obchild_in_obmode_ensure_object(
- tdo, ob, ob_parent_recurse, OB_SKIP_CHILD_PARENT_APPLY_TRANSFORM);
+ ED_object_xform_skip_child_container_item_ensure(
+ tdo->xcs, ob, ob_parent_recurse, XFORM_OB_SKIP_CHILD_PARENT_APPLY);
BLI_ghash_insert(objects_parent_root, ob, ob_parent_recurse);
base->flag_legacy |= BA_TRANSFORM_LOCKED_IN_PLACE;
}
@@ -790,7 +669,7 @@ void createTransObject(bContext *C, TransInfo *t)
}
}
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
if (BASE_XFORM_INDIRECT(base) || BLI_gset_haskey(objects_in_transdata, ob)) {
@@ -801,14 +680,15 @@ void createTransObject(bContext *C, TransInfo *t)
if (base_parent) {
if (BASE_XFORM_INDIRECT(base_parent) ||
BLI_gset_haskey(objects_in_transdata, ob->parent)) {
- trans_obchild_in_obmode_ensure_object(tdo, ob, NULL, OB_SKIP_CHILD_PARENT_IS_XFORM);
+ ED_object_xform_skip_child_container_item_ensure(
+ tdo->xcs, ob, NULL, XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM);
base->flag_legacy |= BA_TRANSFORM_LOCKED_IN_PLACE;
}
else {
Object *ob_parent_recurse = BLI_ghash_lookup(objects_parent_root, ob->parent);
if (ob_parent_recurse) {
- trans_obchild_in_obmode_ensure_object(
- tdo, ob, ob_parent_recurse, OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT);
+ ED_object_xform_skip_child_container_item_ensure(
+ tdo->xcs, ob, ob_parent_recurse, XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT);
}
}
}
diff --git a/source/blender/editors/transform/transform_convert_paintcurve.c b/source/blender/editors/transform/transform_convert_paintcurve.c
index 6d46a94214e..4dbe57fc143 100644
--- a/source/blender/editors/transform/transform_convert_paintcurve.c
+++ b/source/blender/editors/transform/transform_convert_paintcurve.c
@@ -29,7 +29,6 @@
#include "BKE_context.h"
#include "BKE_paint.h"
-#include "BKE_report.h"
#include "transform.h"
#include "transform_convert.h"
diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c
index 2a961da018b..4e1fc6ae1fa 100644
--- a/source/blender/editors/transform/transform_convert_particle.c
+++ b/source/blender/editors/transform/transform_convert_particle.c
@@ -21,15 +21,14 @@
* \ingroup edtransform
*/
-#include "DNA_particle_types.h"
#include "DNA_modifier_types.h"
+#include "DNA_particle_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_report.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
diff --git a/source/blender/editors/transform/transform_convert_sculpt.c b/source/blender/editors/transform/transform_convert_sculpt.c
index 6b584f806b8..55dc36e9693 100644
--- a/source/blender/editors/transform/transform_convert_sculpt.c
+++ b/source/blender/editors/transform/transform_convert_sculpt.c
@@ -21,16 +21,13 @@
* \ingroup edtransform
*/
-#include "DNA_space_types.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_report.h"
-#include "BKE_scene.h"
#include "BKE_paint.h"
+#include "BKE_report.h"
#include "transform.h"
#include "transform_convert.h"
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 4baf0e8a3cb..0175bf6e673 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -28,8 +28,8 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_sequencer.h"
#include "BKE_report.h"
+#include "BKE_sequencer.h"
#include "UI_view2d.h"
@@ -49,7 +49,7 @@
* seq->depth must be set before running this function so we know if the strips
* are root level or not
*/
-static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count, int *flag)
+static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_count, int *r_flag)
{
/* for extend we need to do some tricks */
if (t->mode == TFM_TIME_EXTEND) {
@@ -62,51 +62,51 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count
int right = BKE_sequence_tx_get_final_right(seq, true);
if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) {
- *recursive = false;
- *count = 0;
- *flag = 0;
+ *r_recursive = false;
+ *r_count = 0;
+ *r_flag = 0;
}
else if (seq->type == SEQ_TYPE_META) {
/* for meta's we only ever need to extend their children, no matter what depth
* just check the meta's are in the bounds */
if (t->frame_side == 'R' && right <= cfra) {
- *recursive = false;
+ *r_recursive = false;
}
else if (t->frame_side == 'L' && left >= cfra) {
- *recursive = false;
+ *r_recursive = false;
}
else {
- *recursive = true;
+ *r_recursive = true;
}
- *count = 1;
- *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ *r_count = 1;
+ *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
}
else {
- *recursive = false; /* not a meta, so no thinking here */
- *count = 1; /* unless its set to 0, extend will never set 2 handles at once */
- *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ *r_recursive = false; /* not a meta, so no thinking here */
+ *r_count = 1; /* unless its set to 0, extend will never set 2 handles at once */
+ *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
if (t->frame_side == 'R') {
if (right <= cfra) {
- *count = *flag = 0;
+ *r_count = *r_flag = 0;
} /* ignore */
else if (left > cfra) {
} /* keep the selection */
else {
- *flag |= SEQ_RIGHTSEL;
+ *r_flag |= SEQ_RIGHTSEL;
}
}
else {
if (left >= cfra) {
- *count = *flag = 0;
+ *r_count = *r_flag = 0;
} /* ignore */
else if (right < cfra) {
} /* keep the selection */
else {
- *flag |= SEQ_LEFTSEL;
+ *r_flag |= SEQ_LEFTSEL;
}
}
}
@@ -123,28 +123,28 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count
/* Non nested strips (resect selection and handles) */
if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) {
- *recursive = false;
- *count = 0;
- *flag = 0;
+ *r_recursive = false;
+ *r_count = 0;
+ *r_flag = 0;
}
else {
if ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
- *flag = seq->flag;
- *count = 2; /* we need 2 transdata's */
+ *r_flag = seq->flag;
+ *r_count = 2; /* we need 2 transdata's */
}
else {
- *flag = seq->flag;
- *count = 1; /* selected or with a handle selected */
+ *r_flag = seq->flag;
+ *r_count = 1; /* selected or with a handle selected */
}
/* Recursive */
if ((seq->type == SEQ_TYPE_META) && ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == 0)) {
/* if any handles are selected, don't recurse */
- *recursive = true;
+ *r_recursive = true;
}
else {
- *recursive = false;
+ *r_recursive = false;
}
}
}
@@ -152,23 +152,23 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count
/* Nested, different rules apply */
#ifdef SEQ_TX_NESTED_METAS
- *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
- *count = 1; /* ignore the selection for nested */
- *recursive = (seq->type == SEQ_TYPE_META);
+ *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ *r_count = 1; /* ignore the selection for nested */
+ *r_recursive = (seq->type == SEQ_TYPE_META);
#else
if (seq->type == SEQ_TYPE_META) {
/* Meta's can only directly be moved between channels since they
* don't have their start and length set directly (children affect that)
* since this Meta is nested we don't need any of its data in fact.
* BKE_sequence_calc() will update its settings when run on the top-level meta. */
- *flag = 0;
- *count = 0;
- *recursive = true;
+ *r_flag = 0;
+ *r_count = 0;
+ *r_recursive = true;
}
else {
- *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
- *count = 1; /* ignore the selection for nested */
- *recursive = false;
+ *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ *r_count = 1; /* ignore the selection for nested */
+ *r_recursive = false;
}
#endif
}
@@ -381,7 +381,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
}
if (overlap) {
- const bool use_sync_markers = (((SpaceSeq *)t->sa->spacedata.first)->flag &
+ const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
SEQ_MARKER_TRANS) != 0;
ListBase *markers = &t->scene->markers;
@@ -522,18 +522,16 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
DEG_id_tag_update(&t->scene->id, ID_RECALC_SEQUENCER_STRIPS);
}
-void createTransSeqData(bContext *C, TransInfo *t)
+void createTransSeqData(TransInfo *t)
{
#define XXX_DURIAN_ANIM_TX_HACK
- View2D *v2d = UI_view2d_fromcontext(C);
Scene *scene = t->scene;
Editing *ed = BKE_sequencer_editing_get(t->scene, false);
TransData *td = NULL;
TransData2D *td2d = NULL;
TransDataSeq *tdsq = NULL;
TransSeq *ts = NULL;
- int xmouse;
int count = 0;
@@ -545,18 +543,7 @@ void createTransSeqData(bContext *C, TransInfo *t)
}
tc->custom.type.free_cb = freeSeqData;
-
- xmouse = (int)UI_view2d_region_to_view_x(v2d, t->mouse.imval[0]);
-
- /* which side of the current frame should be allowed */
- if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
- }
- else {
- /* normal transform - both sides of current frame are considered */
- t->frame_side = 'B';
- }
+ t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA);
#ifdef XXX_DURIAN_ANIM_TX_HACK
{
@@ -598,9 +585,12 @@ void createTransSeqData(bContext *C, TransInfo *t)
SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
SeqTransDataBounds(t, ed->seqbasep, ts);
- /* set the snap mode based on how close the mouse is at the end/start points */
- if (abs(xmouse - ts->max) > abs(xmouse - ts->min)) {
- ts->snap_left = true;
+ if (t->flag & T_MODAL) {
+ /* set the snap mode based on how close the mouse is at the end/start points */
+ int xmouse = (int)UI_view2d_region_to_view_x((View2D *)t->view, t->mouse.imval[0]);
+ if (abs(xmouse - ts->max) > abs(xmouse - ts->min)) {
+ ts->snap_left = true;
+ }
}
#undef XXX_DURIAN_ANIM_TX_HACK
diff --git a/source/blender/editors/transform/transform_convert_tracking.c b/source/blender/editors/transform/transform_convert_tracking.c
index b68b79adbd8..6704567a76b 100644
--- a/source/blender/editors/transform/transform_convert_tracking.c
+++ b/source/blender/editors/transform/transform_convert_tracking.c
@@ -518,7 +518,7 @@ static void createTransTrackingCurvesData(bContext *C, TransInfo *t)
void createTransTrackingData(bContext *C, TransInfo *t)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
int width, height;
@@ -537,7 +537,7 @@ void createTransTrackingData(bContext *C, TransInfo *t)
return;
}
- if (ar->regiontype == RGN_TYPE_PREVIEW) {
+ if (region->regiontype == RGN_TYPE_PREVIEW) {
/* transformation was called from graph editor */
createTransTrackingCurvesData(C, t);
}
@@ -549,7 +549,7 @@ void createTransTrackingData(bContext *C, TransInfo *t)
void cancelTransTracking(TransInfo *t)
{
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- SpaceClip *sc = t->sa->spacedata.first;
+ SpaceClip *sc = t->area->spacedata.first;
int i, framenr = ED_space_clip_get_clip_frame_number(sc);
TransDataTracking *tdt_array = tc->custom.type.data;
diff --git a/source/blender/editors/transform/transform_draw_cursors.c b/source/blender/editors/transform/transform_draw_cursors.c
index dc2ebdca56a..95ca5ae0c30 100644
--- a/source/blender/editors/transform/transform_draw_cursors.c
+++ b/source/blender/editors/transform/transform_draw_cursors.c
@@ -148,9 +148,9 @@ static void drawArc(float angle_start, float angle_end, int segments, float size
*/
bool transform_draw_cursor_poll(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- if (ar && ar->regiontype == RGN_TYPE_WINDOW) {
+ if (region && region->regiontype == RGN_TYPE_WINDOW) {
return 1;
}
return 0;
@@ -181,8 +181,8 @@ void transform_draw_cursor_draw(bContext *UNUSED(C), int x, int y, void *customd
projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO);
/* Offset the values for the area region. */
const float offset[2] = {
- t->ar->winrct.xmin,
- t->ar->winrct.ymin,
+ t->region->winrct.xmin,
+ t->region->winrct.ymin,
};
for (int i = 0; i < 2; i++) {
@@ -313,7 +313,7 @@ void transform_draw_cursor_draw(bContext *UNUSED(C), int x, int y, void *customd
break;
}
case HLP_TRACKBALL: {
- unsigned char col[3], col2[3];
+ uchar col[3], col2[3];
UI_GetThemeColor3ubv(TH_GRID, col);
GPU_matrix_translate_3fv(mval);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 5595c3a0e38..4472facf183 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -21,8 +21,8 @@
* \ingroup edtransform
*/
-#include <string.h>
#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -34,20 +34,21 @@
#include "DNA_constraint_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_mask_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_meta_types.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
@@ -63,16 +64,16 @@
#include "BIK_api.h"
#include "BKE_action.h"
-#include "BKE_animsys.h"
+#include "BKE_anim_data.h"
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_editmesh.h"
#include "BKE_fcurve.h"
-#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mask.h"
#include "BKE_nla.h"
#include "BKE_paint.h"
@@ -86,24 +87,24 @@
#include "ED_anim_api.h"
#include "ED_armature.h"
+#include "ED_clip.h"
+#include "ED_curve.h" /* for curve_editnurbs */
+#include "ED_gpencil.h"
#include "ED_image.h"
#include "ED_keyframing.h"
#include "ED_markers.h"
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_particle.h"
+#include "ED_screen.h"
#include "ED_screen_types.h"
+#include "ED_sculpt.h"
#include "ED_space_api.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
-#include "ED_curve.h" /* for curve_editnurbs */
-#include "ED_clip.h"
-#include "ED_screen.h"
-#include "ED_gpencil.h"
-#include "ED_sculpt.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "RE_engine.h"
@@ -112,6 +113,7 @@
#include "transform.h"
#include "transform_convert.h"
+#include "transform_mode.h"
#include "transform_snap.h"
/* ************************** Functions *************************** */
@@ -335,7 +337,7 @@ static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
static bool fcu_test_selected(FCurve *fcu)
{
BezTriple *bezt = fcu->bezt;
- unsigned int i;
+ uint i;
if (bezt == NULL) { /* ignore baked */
return 0;
@@ -354,7 +356,7 @@ static bool fcu_test_selected(FCurve *fcu)
static void recalcData_actedit(TransInfo *t)
{
ViewLayer *view_layer = t->view_layer;
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+ SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
bAnimContext ac = {NULL};
ListBase anim_data = {NULL, NULL};
@@ -367,11 +369,11 @@ static void recalcData_actedit(TransInfo *t)
ac.scene = t->scene;
ac.view_layer = t->view_layer;
ac.obact = OBACT(view_layer);
- ac.sa = t->sa;
- ac.ar = t->ar;
- ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
- ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
- ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
+ ac.area = t->area;
+ ac.region = t->region;
+ ac.sl = (t->area) ? t->area->spacedata.first : NULL;
+ ac.spacetype = (t->area) ? t->area->spacetype : 0;
+ ac.regiontype = (t->region) ? t->region->regiontype : 0;
ANIM_animdata_context_getdata(&ac);
@@ -404,7 +406,7 @@ static void recalcData_actedit(TransInfo *t)
/* helper for recalcData() - for Graph Editor transforms */
static void recalcData_graphedit(TransInfo *t)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
ViewLayer *view_layer = t->view_layer;
ListBase anim_data = {NULL, NULL};
@@ -420,11 +422,11 @@ static void recalcData_graphedit(TransInfo *t)
ac.scene = t->scene;
ac.view_layer = t->view_layer;
ac.obact = OBACT(view_layer);
- ac.sa = t->sa;
- ac.ar = t->ar;
- ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
- ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
- ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
+ ac.area = t->area;
+ ac.region = t->region;
+ ac.sl = (t->area) ? t->area->spacedata.first : NULL;
+ ac.spacetype = (t->area) ? t->area->spacetype : 0;
+ ac.regiontype = (t->region) ? t->region->regiontype : 0;
ANIM_animdata_context_getdata(&ac);
@@ -472,7 +474,7 @@ static void recalcData_graphedit(TransInfo *t)
/* helper for recalcData() - for NLA Editor transforms */
static void recalcData_nla(TransInfo *t)
{
- SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
+ SpaceNla *snla = (SpaceNla *)t->area->spacedata.first;
Scene *scene = t->scene;
double secf = FPS;
int i;
@@ -716,7 +718,7 @@ static void recalcData_image(TransInfo *t)
flushTransPaintCurve(t);
}
else if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
- SpaceImage *sima = t->sa->spacedata.first;
+ SpaceImage *sima = t->area->spacedata.first;
flushTransUVs(t);
if (sima->flag & SI_LIVE_UNWRAP) {
@@ -734,7 +736,7 @@ static void recalcData_image(TransInfo *t)
/* helper for recalcData() - for Movie Clip transforms */
static void recalcData_spaceclip(TransInfo *t)
{
- SpaceClip *sc = t->sa->spacedata.first;
+ SpaceClip *sc = t->area->spacedata.first;
if (ED_space_clip_check_show_trackedit(sc)) {
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -782,69 +784,6 @@ static void recalcData_spaceclip(TransInfo *t)
}
}
-/**
- * if pose bone (partial) selected, copy data.
- * context; posemode armature, with mirror editing enabled.
- *
- * \param pid: Optional, apply relative transform when set (has no effect on mirrored bones).
- */
-static void pose_transform_mirror_update(TransInfo *t,
- TransDataContainer *tc,
- Object *ob,
- PoseInitData_Mirror *pid)
-{
- float flip_mtx[4][4];
- unit_m4(flip_mtx);
- flip_mtx[0][0] = -1;
-
- TransData *td = tc->data;
- for (int i = tc->data_len; i--; td++) {
- bPoseChannel *pchan_orig = td->extra;
- BLI_assert(pchan_orig->bone->flag & BONE_TRANSFORM);
- /* No layer check, correct mirror is more important. */
- bPoseChannel *pchan = BKE_pose_channel_get_mirrored(ob->pose, pchan_orig->name);
- if (pchan == NULL) {
- continue;
- }
-
- /* Also do bbone scaling. */
- pchan->bone->xwidth = pchan_orig->bone->xwidth;
- pchan->bone->zwidth = pchan_orig->bone->zwidth;
-
- /* We assume X-axis flipping for now. */
- pchan->curve_in_x = pchan_orig->curve_in_x * -1;
- pchan->curve_out_x = pchan_orig->curve_out_x * -1;
- pchan->roll1 = pchan_orig->roll1 * -1; // XXX?
- pchan->roll2 = pchan_orig->roll2 * -1; // XXX?
-
- float pchan_mtx_final[4][4];
- BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final);
- mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx);
- mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final);
- if (pid) {
- mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final);
- }
- BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false);
-
- /* In this case we can do target-less IK grabbing. */
- if (t->mode == TFM_TRANSLATION) {
- bKinematicConstraint *data = has_targetless_ik(pchan);
- if (data == NULL) {
- continue;
- }
- mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc);
- if (pid) {
- /* TODO(germano): Realitve Mirror support */
- }
- data->flag |= CONSTRAINT_IK_AUTO;
- }
-
- if (pid) {
- pid++;
- }
- }
-}
-
/* helper for recalcData() - for object transforms, typically in the 3D view */
static void recalcData_objects(TransInfo *t)
{
@@ -1057,7 +996,7 @@ static void recalcData_objects(TransInfo *t)
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
bPose *pose = ob->pose;
if (arm->flag & ARM_MIRROR_EDIT || pose->flag & POSE_MIRROR_EDIT) {
- pose_transform_mirror_update(t, tc, ob, NULL);
+ pose_transform_mirror_update(t, tc, ob);
}
}
}
@@ -1071,11 +1010,7 @@ static void recalcData_objects(TransInfo *t)
if (pose->flag & POSE_MIRROR_EDIT) {
if (t->state != TRANS_CANCEL) {
- PoseInitData_Mirror *pid = NULL;
- if (pose->flag & POSE_MIRROR_RELATIVE) {
- pid = tc->custom.type.data;
- }
- pose_transform_mirror_update(t, tc, ob, pid);
+ pose_transform_mirror_update(t, tc, ob);
}
else {
restoreMirrorPoseBones(tc);
@@ -1168,7 +1103,7 @@ static void recalcData_objects(TransInfo *t)
if (motionpath_update) {
/* Update motion paths once for all transformed objects. */
- ED_objects_recalculate_paths(t->context, t->scene, OBJECT_PATH_CALC_RANGE_CHANGED);
+ ED_objects_recalculate_paths(t->context, t->scene, OBJECT_PATH_CALC_RANGE_CURRENT_FRAME);
}
if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) {
@@ -1215,14 +1150,19 @@ static void recalcData_sequencer(TransInfo *t)
static void recalcData_gpencil_strokes(TransInfo *t)
{
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ GHash *strokes = BLI_ghash_ptr_new(__func__);
TransData *td = tc->data;
for (int i = 0; i < tc->data_len; i++, td++) {
bGPDstroke *gps = td->extra;
- if (gps != NULL) {
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+ if ((gps != NULL) && (!BLI_ghash_haskey(strokes, gps))) {
+ BLI_ghash_insert(strokes, gps, gps);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
}
+ BLI_ghash_free(strokes, NULL, NULL);
}
static void recalcData_sculpt(TransInfo *t)
@@ -1247,7 +1187,6 @@ void recalcData(TransInfo *t)
flushTransPaintCurve(t);
}
else if (t->options & CTX_GPENCIL_STROKES) {
- /* set recalc triangle cache flag */
recalcData_gpencil_strokes(t);
}
else if (t->options & CTX_SCULPT) {
@@ -1282,7 +1221,7 @@ void recalcData(TransInfo *t)
void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options)
{
float v1[3], v2[3], v3[3];
- unsigned char col[3], col2[3];
+ uchar col[3], col2[3];
if (t->spacetype == SPACE_VIEW3D) {
View3D *v3d = t->view;
@@ -1434,8 +1373,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
Object *obact = OBACT(view_layer);
const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
ToolSettings *ts = CTX_data_tool_settings(C);
- ARegion *ar = CTX_wm_region(C);
- ScrArea *sa = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
PropertyRNA *prop;
@@ -1443,8 +1382,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->depsgraph = CTX_data_depsgraph_pointer(C);
t->scene = sce;
t->view_layer = view_layer;
- t->sa = sa;
- t->ar = ar;
+ t->area = area;
+ t->region = region;
t->settings = ts;
t->reports = op ? op->reports : NULL;
@@ -1468,20 +1407,16 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->redraw = TREDRAW_HARD; /* redraw first time */
+ int mval[2];
if (event) {
- t->mouse.imval[0] = event->mval[0];
- t->mouse.imval[1] = event->mval[1];
+ copy_v2_v2_int(mval, event->mval);
}
else {
- t->mouse.imval[0] = 0;
- t->mouse.imval[1] = 0;
+ zero_v2_int(mval);
}
-
- t->con.imval[0] = t->mouse.imval[0];
- t->con.imval[1] = t->mouse.imval[1];
-
- t->mval[0] = t->mouse.imval[0];
- t->mval[1] = t->mouse.imval[1];
+ copy_v2_v2_int(t->mval, mval);
+ copy_v2_v2_int(t->mouse.imval, mval);
+ copy_v2_v2_int(t->con.imval, mval);
t->transform = NULL;
t->handleEvent = NULL;
@@ -1495,11 +1430,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
unit_m3(t->mat);
- unit_m3(t->orient_matrix);
- negate_m3(t->orient_matrix);
- /* Leave 't->orient_matrix_is_set' to false,
- * so we overwrite it when we have a useful value. */
-
/* Default to rotate on the Z axis. */
t->orient_axis = 2;
t->orient_axis_ortho = 1;
@@ -1529,17 +1459,17 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
/* Assign the space type, some exceptions for running in different mode */
- if (sa == NULL) {
+ if (area == NULL) {
/* background mode */
t->spacetype = SPACE_EMPTY;
}
- else if ((ar == NULL) && (sa->spacetype == SPACE_VIEW3D)) {
+ else if ((region == NULL) && (area->spacetype == SPACE_VIEW3D)) {
/* running in the text editor */
t->spacetype = SPACE_EMPTY;
}
else {
/* normal operation */
- t->spacetype = sa->spacetype;
+ t->spacetype = area->spacetype;
}
/* handle T_ALT_TRANSFORM initialization, we may use for different operators */
@@ -1555,7 +1485,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
if (t->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
bScreen *animscreen = ED_screen_animation_playing(CTX_wm_manager(C));
t->view = v3d;
@@ -1577,22 +1507,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->around = V3D_AROUND_CURSOR;
}
- TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
- t->orientation.unset = V3D_ORIENT_GLOBAL;
- t->orientation.user = orient_slot->type;
- t->orientation.custom = BKE_scene_transform_orientation_find(t->scene,
- orient_slot->index_custom);
-
- t->orientation.index = 0;
- ARRAY_SET_ITEMS(t->orientation.types, &t->orientation.user, NULL);
-
- /* Make second orientation local if both are global. */
- if (t->orientation.user == V3D_ORIENT_GLOBAL) {
- t->orientation.user_alt = V3D_ORIENT_LOCAL;
- t->orientation.types[0] = &t->orientation.user_alt;
- SWAP(short *, t->orientation.types[0], t->orientation.types[1]);
- }
-
/* exceptional case */
if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
@@ -1628,9 +1542,9 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
else if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
// XXX for now, get View2D from the active region
- t->view = &ar->v2d;
+ t->view = &region->v2d;
t->around = sima->around;
if (ED_space_image_show_uvedit(sima, OBACT(t->view_layer))) {
@@ -1649,17 +1563,17 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
else if (t->spacetype == SPACE_NODE) {
// XXX for now, get View2D from the active region
- t->view = &ar->v2d;
+ t->view = &region->v2d;
t->around = V3D_AROUND_CENTER_BOUNDS;
}
else if (t->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = sa->spacedata.first;
- t->view = &ar->v2d;
+ SpaceGraph *sipo = area->spacedata.first;
+ t->view = &region->v2d;
t->around = sipo->around;
}
else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = sa->spacedata.first;
- t->view = &ar->v2d;
+ SpaceClip *sclip = area->spacedata.first;
+ t->view = &region->v2d;
t->around = sclip->around;
if (ED_space_clip_check_show_trackedit(sclip)) {
@@ -1670,9 +1584,9 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
else {
- if (ar) {
+ if (region) {
// XXX for now, get View2D from the active region
- t->view = &ar->v2d;
+ t->view = &region->v2d;
// XXX for now, the center point is the midpoint of the data
}
else {
@@ -1681,49 +1595,138 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->around = V3D_AROUND_CENTER_BOUNDS;
}
- if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
- t->orient_axis = RNA_property_enum_get(op->ptr, prop);
- }
- if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
- t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
- }
+ BLI_assert(is_zero_v4(t->values_modal_offset));
+ bool t_values_set_is_array = false;
+ if (op && (prop = RNA_struct_find_property(op->ptr, "value")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */
+ if (RNA_property_array_check(prop)) {
+ RNA_float_get_array(op->ptr, "value", values);
+ t_values_set_is_array = true;
+ }
+ else {
+ values[0] = RNA_float_get(op->ptr, "value");
+ }
- if (op &&
- ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) &&
- RNA_property_is_set(op->ptr, prop)) &&
- ((t->flag & T_MODAL) ||
- /* When using redo, don't use the custom constraint matrix
- * if the user selects a different orientation. */
- (RNA_enum_get(op->ptr, "orient_type") == RNA_enum_get(op->ptr, "orient_matrix_type")))) {
- RNA_property_float_get_array(op->ptr, prop, &t->spacemtx[0][0]);
- /* Some transform modes use this to operate on an axis. */
- t->orient_matrix_is_set = true;
- copy_m3_m3(t->orient_matrix, t->spacemtx);
- t->orient_matrix_is_set = true;
- t->orientation.user = V3D_ORIENT_CUSTOM_MATRIX;
- t->orientation.custom = 0;
+ copy_v4_v4(t->values, values);
if (t->flag & T_MODAL) {
- RNA_enum_set(op->ptr, "orient_matrix_type", RNA_enum_get(op->ptr, "orient_type"));
+ /* Run before init functions so 'values_modal_offset' can be applied on mouse input. */
+ copy_v4_v4(t->values_modal_offset, values);
+ }
+ else {
+ copy_v4_v4(t->values, values);
+ t->flag |= T_INPUT_IS_VALUES_FINAL;
+ }
+ }
+
+ if (op && (prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
+ bool constraint_axis[3] = {false, false, false};
+ if (RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_get_array(op->ptr, prop, constraint_axis);
+ }
+
+ if (t_values_set_is_array && t->flag & T_INPUT_IS_VALUES_FINAL) {
+ /* For operators whose `t->values` is array, set contrain so that the
+ * orientation is more intuitive in the Redo Panel. */
+ for (int i = 3; i--;) {
+ constraint_axis[i] |= t->values[i] != 0.0f;
+ }
+ }
+
+ if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) {
+ t->con.mode |= CON_APPLY;
+
+ if (constraint_axis[0]) {
+ t->con.mode |= CON_AXIS0;
+ }
+ if (constraint_axis[1]) {
+ t->con.mode |= CON_AXIS1;
+ }
+ if (constraint_axis[2]) {
+ t->con.mode |= CON_AXIS2;
+ }
}
}
- else if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) &&
- RNA_property_is_set(op->ptr, prop))) {
- short orientation = RNA_property_enum_get(op->ptr, prop);
+
+ {
+ TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
TransformOrientation *custom_orientation = NULL;
+ short orient_type_set = -1;
+ short orient_type_matrix_set = -1;
+ short orient_type_scene = orient_slot->type;
+ if (orient_type_scene == V3D_ORIENT_CUSTOM) {
+ const int index_custom = orient_slot->index_custom;
+ custom_orientation = BKE_scene_transform_orientation_find(t->scene, index_custom);
+ orient_type_scene += index_custom;
+ }
+
+ short orient_type_default = V3D_ORIENT_GLOBAL;
+ short orient_type_constraint[2];
+
+ if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
+ t->orient_axis = RNA_property_enum_get(op->ptr, prop);
- if (orientation >= V3D_ORIENT_CUSTOM) {
- if (orientation >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) {
- orientation = V3D_ORIENT_GLOBAL;
+ /* For transfor modes that require "orient_axis" use
+ * `V3D_ORIENT_VIEW` as default. */
+ orient_type_default = V3D_ORIENT_VIEW;
+ }
+ if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
+ t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ orient_type_set = RNA_property_enum_get(op->ptr, prop);
+ if (orient_type_set >= V3D_ORIENT_CUSTOM) {
+ if (orient_type_set >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) {
+ orient_type_set = V3D_ORIENT_GLOBAL;
+ }
+ else {
+ custom_orientation = BKE_scene_transform_orientation_find(
+ t->scene, orient_type_default - V3D_ORIENT_CUSTOM);
+ }
+ }
+
+ /* Change the default orientation to be used when redoing. */
+ orient_type_default = orient_type_set;
+ orient_type_constraint[0] = orient_type_set;
+ orient_type_constraint[1] = orient_type_scene;
+ }
+ else {
+ orient_type_constraint[0] = orient_type_scene;
+ orient_type_constraint[1] = orient_type_scene != V3D_ORIENT_GLOBAL ? V3D_ORIENT_GLOBAL :
+ V3D_ORIENT_LOCAL;
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ RNA_property_float_get_array(op->ptr, prop, &t->orientation.custom_matrix[0][0]);
+
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ orient_type_matrix_set = RNA_property_enum_get(op->ptr, prop);
+ }
+ else if (orient_type_set != -1) {
+ orient_type_matrix_set = orient_type_set;
}
else {
- custom_orientation = BKE_scene_transform_orientation_find(t->scene,
- orientation - V3D_ORIENT_CUSTOM);
- orientation = V3D_ORIENT_CUSTOM;
+ orient_type_matrix_set = orient_type_set = V3D_ORIENT_GLOBAL;
+ }
+
+ if (orient_type_matrix_set == orient_type_set) {
+ /* Constraints are forced to use the custom matrix when redoing. */
+ orient_type_default = V3D_ORIENT_CUSTOM_MATRIX;
}
}
- t->orientation.user = orientation;
+ t->orientation.types[0] = orient_type_default;
+ t->orientation.types[1] = orient_type_constraint[0];
+ t->orientation.types[2] = orient_type_constraint[1];
t->orientation.custom = custom_orientation;
+
+ if (t->con.mode & CON_APPLY) {
+ t->orientation.index = 1;
+ }
}
if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
@@ -1828,6 +1831,24 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->options |= CTX_NO_PET;
}
+ if (t->obedit_type == OB_MESH) {
+ if (op && (prop = RNA_struct_find_property(op->ptr, "use_automerge_and_split")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ t->flag |= T_AUTOMERGE | T_AUTOSPLIT;
+ }
+ }
+ else {
+ char automerge = t->scene->toolsettings->automerge;
+ if (automerge & AUTO_MERGE) {
+ t->flag |= T_AUTOMERGE;
+ if (automerge & AUTO_MERGE_AND_SPLIT) {
+ t->flag |= T_AUTOSPLIT;
+ }
+ }
+ }
+ }
+
// Mirror is not supported with PET, turn it off.
#if 0
if (t->flag & T_PROP_EDIT) {
@@ -1889,13 +1910,13 @@ void freeTransCustomDataForMode(TransInfo *t)
void postTrans(bContext *C, TransInfo *t)
{
if (t->draw_handle_view) {
- ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
+ ED_region_draw_cb_exit(t->region->type, t->draw_handle_view);
}
if (t->draw_handle_apply) {
- ED_region_draw_cb_exit(t->ar->type, t->draw_handle_apply);
+ ED_region_draw_cb_exit(t->region->type, t->draw_handle_apply);
}
if (t->draw_handle_pixel) {
- ED_region_draw_cb_exit(t->ar->type, t->draw_handle_pixel);
+ ED_region_draw_cb_exit(t->region->type, t->draw_handle_pixel);
}
if (t->draw_handle_cursor) {
WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
@@ -1941,14 +1962,14 @@ void postTrans(bContext *C, TransInfo *t)
/* pass */
}
else {
- SpaceImage *sima = t->sa->spacedata.first;
+ SpaceImage *sima = t->area->spacedata.first;
if (sima->flag & SI_LIVE_UNWRAP) {
ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL);
}
}
}
else if (t->spacetype == SPACE_VIEW3D) {
- View3D *v3d = t->sa->spacedata.first;
+ View3D *v3d = t->area->spacedata.first;
/* restore gizmo */
if (t->flag & T_MODAL) {
v3d->gizmo_flag = t->gizmo_flag;
@@ -2074,10 +2095,10 @@ void calculateCenterCursor(TransInfo *t, float r_center[3])
/* If edit or pose mode, move cursor in local space */
if (t->options & CTX_PAINT_CURVE) {
- if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) !=
+ if (ED_view3d_project_float_global(t->region, cursor, r_center, V3D_PROJ_TEST_NOP) !=
V3D_PROJ_RET_OK) {
- r_center[0] = t->ar->winx / 2.0f;
- r_center[1] = t->ar->winy / 2.0f;
+ r_center[0] = t->region->winx / 2.0f;
+ r_center[1] = t->region->winy / 2.0f;
}
r_center[2] = 0.0f;
}
@@ -2088,11 +2109,11 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
const float *cursor = NULL;
if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
+ SpaceImage *sima = (SpaceImage *)t->area->spacedata.first;
cursor = sima->cursor;
}
else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *space_clip = (SpaceClip *)t->sa->spacedata.first;
+ SpaceClip *space_clip = (SpaceClip *)t->area->spacedata.first;
cursor = space_clip->cursor;
}
@@ -2101,11 +2122,11 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
float co[2];
if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
+ SpaceImage *sima = (SpaceImage *)t->area->spacedata.first;
BKE_mask_coord_from_image(sima->image, &sima->iuser, co, cursor);
}
else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *space_clip = (SpaceClip *)t->sa->spacedata.first;
+ SpaceClip *space_clip = (SpaceClip *)t->area->spacedata.first;
BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
}
else {
@@ -2117,8 +2138,8 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
}
else if (t->options & CTX_PAINT_CURVE) {
if (t->spacetype == SPACE_IMAGE) {
- r_center[0] = UI_view2d_view_to_region_x(&t->ar->v2d, cursor[0]);
- r_center[1] = UI_view2d_view_to_region_y(&t->ar->v2d, cursor[1]);
+ r_center[0] = UI_view2d_view_to_region_x(&t->region->v2d, cursor[0]);
+ r_center[1] = UI_view2d_view_to_region_y(&t->region->v2d, cursor[1]);
}
}
else {
@@ -2130,7 +2151,7 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2])
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
Scene *scene = t->scene;
/* cursor is combination of current frame, and graph-editor cursor value */
@@ -2300,7 +2321,7 @@ void calculateCenter(TransInfo *t)
/* for panning from cameraview */
if ((t->flag & T_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) {
- if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
+ if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) {
if (t->flag & T_CAMERA) {
float axis[3];
@@ -2333,8 +2354,8 @@ void calculateCenter(TransInfo *t)
* We need special case here as well, since ED_view3d_calc_zfac will crash when called
* for a region different from RGN_TYPE_WINDOW.
*/
- if (t->ar->regiontype == RGN_TYPE_WINDOW) {
- t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, t->center_global, NULL);
+ if (t->region->regiontype == RGN_TYPE_WINDOW) {
+ t->zfac = ED_view3d_calc_zfac(t->region->regiondata, t->center_global, NULL);
}
else {
t->zfac = 0.0f;
diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c
index 793552865a6..50317d8b395 100644
--- a/source/blender/editors/transform/transform_gizmo_2d.c
+++ b/source/blender/editors/transform/transform_gizmo_2d.c
@@ -42,15 +42,15 @@
#include "UI_view2d.h"
#include "WM_api.h"
+#include "WM_message.h"
#include "WM_types.h"
#include "wm.h" /* XXX */
-#include "WM_message.h"
+#include "ED_gizmo_library.h"
#include "ED_gizmo_utils.h"
#include "ED_image.h"
#include "ED_screen.h"
#include "ED_uvedit.h"
-#include "ED_gizmo_library.h"
#include "transform.h" /* own include */
@@ -68,10 +68,10 @@ static bool gizmo2d_generic_poll(const bContext *C, wmGizmoGroupType *gzgt)
return false;
}
- ScrArea *sa = CTX_wm_area(C);
- switch (sa->spacetype) {
+ ScrArea *area = CTX_wm_area(C);
+ switch (area->spacetype) {
case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
Object *obedit = CTX_data_edit_object(C);
if (!ED_space_image_show_uvedit(sima, obedit)) {
return false;
@@ -86,18 +86,18 @@ static void gizmo2d_pivot_point_message_subscribe(struct wmGizmoGroup *gzgroup,
struct wmMsgBus *mbus,
/* Additional args. */
bScreen *screen,
- ScrArea *sa,
- ARegion *ar)
+ ScrArea *area,
+ ARegion *region)
{
wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
+ .owner = region,
.user_data = gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
};
- switch (sa->spacetype) {
+ switch (area->spacetype) {
case SPACE_IMAGE: {
- SpaceImage *sima = sa->spacedata.first;
+ SpaceImage *sima = area->spacedata.first;
PointerRNA ptr;
RNA_pointer_create(&screen->id, &RNA_SpaceImageEditor, sima, &ptr);
{
@@ -214,10 +214,10 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
r_max = max_buf;
}
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
bool changed = false;
- if (sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
+ if (area->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = area->spacedata.first;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Image *ima = ED_space_image(sima);
@@ -241,11 +241,11 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
static bool gizmo2d_calc_center(const bContext *C, float r_center[2])
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
bool has_select = false;
zero_v2(r_center);
- if (sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
+ if (area->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = area->spacedata.first;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
ED_uvedit_center_from_pivot_ex(sima, scene, view_layer, r_center, sima->around, &has_select);
@@ -256,9 +256,9 @@ static bool gizmo2d_calc_center(const bContext *C, float r_center[2])
/**
* Convert origin (or any other point) from view to region space.
*/
-BLI_INLINE void gizmo2d_origin_to_region(ARegion *ar, float *r_origin)
+BLI_INLINE void gizmo2d_origin_to_region(ARegion *region, float *r_origin)
{
- UI_view2d_view_to_region_fl(&ar->v2d, r_origin[0], r_origin[1], &r_origin[0], &r_origin[1]);
+ UI_view2d_view_to_region_fl(&region->v2d, r_origin[0], r_origin[1], &r_origin[0], &r_origin[1]);
}
/**
@@ -269,14 +269,14 @@ static int gizmo2d_modal(bContext *C,
const wmEvent *UNUSED(event),
eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float origin[3];
gizmo2d_calc_center(C, origin);
- gizmo2d_origin_to_region(ar, origin);
+ gizmo2d_origin_to_region(region, origin);
WM_gizmo_set_matrix_location(widget, origin);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_editor_overlays(region);
return OPERATOR_RUNNING_MODAL;
}
@@ -300,7 +300,7 @@ static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup
/* set up widget data */
RNA_float_set(gz->ptr, "length", 0.8f);
float axis[3] = {0.0f};
- axis[(i + 1) % 2] = 1.0f;
+ axis[i] = 1.0f;
WM_gizmo_set_matrix_rotation_from_z_axis(gz, axis);
float offset[3] = {0, 0, 0};
@@ -315,6 +315,11 @@ static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup
WM_gizmo_set_scale(gz, 1.0f);
}
else {
+ float color[4], color_hi[4];
+ UI_GetThemeColor4fv(TH_GIZMO_VIEW_ALIGN, color);
+ copy_v4_v4(color_hi, color);
+ color[3] *= 0.6f;
+
PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
RNA_property_enum_set(gz->ptr, prop, ICON_NONE);
@@ -322,7 +327,8 @@ static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup
/* Make the center low alpha. */
WM_gizmo_set_line_width(gz, 2.0f);
RNA_float_set(gz->ptr, "backdrop_fill_alpha", 0.0);
- WM_gizmo_set_color(gz, (const float[4]){1, 1, 1, 0.6});
+ WM_gizmo_set_color(gz, color);
+ WM_gizmo_set_color_highlight(gz, color_hi);
WM_gizmo_set_scale(gz, 0.2f);
}
@@ -330,8 +336,8 @@ static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup
/* Assign operator. */
PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_translate, NULL);
if (i < 2) {
- bool constraint[3] = {0};
- constraint[(i + 1) % 2] = 1;
+ bool constraint[3] = {false};
+ constraint[i] = true;
if (RNA_struct_find_property(ptr, "constraint_axis")) {
RNA_boolean_set_array(ptr, "constraint_axis", constraint);
}
@@ -480,19 +486,19 @@ static void gizmo2d_xform_refresh(const bContext *C, wmGizmoGroup *gzgroup)
static void gizmo2d_xform_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
GizmoGroup2D *ggd = gzgroup->customdata;
float origin[3] = {UNPACK2(ggd->origin), 0.0f};
float origin_aa[3] = {UNPACK2(ggd->origin), 0.0f};
- gizmo2d_origin_to_region(ar, origin);
+ gizmo2d_origin_to_region(region, origin);
for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
wmGizmo *gz = ggd->translate_xy[i];
WM_gizmo_set_matrix_location(gz, origin);
}
- UI_view2d_view_to_region_m4(&ar->v2d, ggd->cage->matrix_space);
+ UI_view2d_view_to_region_m4(&region->v2d, ggd->cage->matrix_space);
WM_gizmo_set_matrix_offset_location(ggd->cage, origin_aa);
ggd->cage->matrix_offset[0][0] = (ggd->max[0] - ggd->min[0]);
ggd->cage->matrix_offset[1][1] = (ggd->max[1] - ggd->min[1]);
@@ -503,9 +509,9 @@ static void gizmo2d_xform_no_cage_message_subscribe(const struct bContext *C,
struct wmMsgBus *mbus)
{
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, sa, ar);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, area, region);
}
void ED_widgetgroup_gizmo2d_xform_callbacks_set(wmGizmoGroupType *gzgt)
@@ -575,7 +581,7 @@ static void gizmo2d_resize_refresh(const bContext *C, wmGizmoGroup *gzgroup)
static void gizmo2d_resize_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
GizmoGroup_Resize2D *ggd = gzgroup->customdata;
float origin[3] = {UNPACK2(ggd->origin), 0.0f};
@@ -589,7 +595,7 @@ static void gizmo2d_resize_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup
}
}
- gizmo2d_origin_to_region(ar, origin);
+ gizmo2d_origin_to_region(region, origin);
for (int i = 0; i < ARRAY_SIZE(ggd->gizmo_xy); i++) {
wmGizmo *gz = ggd->gizmo_xy[i];
@@ -629,6 +635,11 @@ static void gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgrou
WM_gizmo_set_scale(gz, 1.0f);
}
else {
+ float color[4], color_hi[4];
+ UI_GetThemeColor4fv(TH_GIZMO_VIEW_ALIGN, color);
+ copy_v4_v4(color_hi, color);
+ color[3] *= 0.6f;
+
PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
RNA_property_enum_set(gz->ptr, prop, ICON_NONE);
@@ -636,7 +647,8 @@ static void gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgrou
/* Make the center low alpha. */
WM_gizmo_set_line_width(gz, 2.0f);
RNA_float_set(gz->ptr, "backdrop_fill_alpha", 0.0);
- WM_gizmo_set_color(gz, (const float[4]){1, 1, 1, 0.6});
+ WM_gizmo_set_color(gz, color);
+ WM_gizmo_set_color_highlight(gz, color_hi);
WM_gizmo_set_scale(gz, 1.2f);
}
@@ -659,9 +671,9 @@ static void gizmo2d_resize_message_subscribe(const struct bContext *C,
struct wmMsgBus *mbus)
{
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, sa, ar);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, area, region);
}
void ED_widgetgroup_gizmo2d_resize_callbacks_set(wmGizmoGroupType *gzgt)
@@ -718,7 +730,7 @@ static void gizmo2d_rotate_refresh(const bContext *C, wmGizmoGroup *gzgroup)
static void gizmo2d_rotate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
GizmoGroup_Rotate2D *ggd = gzgroup->customdata;
float origin[3] = {UNPACK2(ggd->origin), 0.0f};
@@ -732,7 +744,7 @@ static void gizmo2d_rotate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup
}
}
- gizmo2d_origin_to_region(ar, origin);
+ gizmo2d_origin_to_region(region, origin);
wmGizmo *gz = ggd->gizmo;
WM_gizmo_set_matrix_location(gz, origin);
@@ -754,6 +766,9 @@ static void gizmo2d_rotate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgrou
WM_gizmo_set_scale(gz, 1.2f);
{
+ float color[4];
+ UI_GetThemeColor4fv(TH_GIZMO_VIEW_ALIGN, color);
+
PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
RNA_property_enum_set(gz->ptr, prop, ICON_NONE);
@@ -761,7 +776,8 @@ static void gizmo2d_rotate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgrou
/* Make the center low alpha. */
WM_gizmo_set_line_width(gz, 2.0f);
RNA_float_set(gz->ptr, "backdrop_fill_alpha", 0.0);
- WM_gizmo_set_color(gz, (const float[4]){1, 1, 1, 0.6});
+ WM_gizmo_set_color(gz, color);
+ WM_gizmo_set_color_highlight(gz, color);
}
/* Assign operator. */
@@ -775,9 +791,9 @@ static void gizmo2d_rotate_message_subscribe(const struct bContext *C,
struct wmMsgBus *mbus)
{
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, sa, ar);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, area, region);
}
void ED_widgetgroup_gizmo2d_rotate_callbacks_set(wmGizmoGroupType *gzgt)
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index b3c1fbd3aad..b575030778f 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -22,58 +22,58 @@
* Used for 3D View
*/
+#include <float.h>
+#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
-#include <float.h>
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meta_types.h"
-#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "BLI_array_utils.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_curve.h"
+#include "BKE_editmesh.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_lattice.h"
#include "BKE_layer.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "BKE_editmesh.h"
-#include "BKE_lattice.h"
-#include "BKE_gpencil.h"
#include "BKE_scene.h"
#include "BKE_workspace.h"
-#include "BKE_object.h"
-#include "BKE_paint.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "wm.h"
#include "ED_armature.h"
#include "ED_curve.h"
+#include "ED_gizmo_library.h"
+#include "ED_gizmo_utils.h"
+#include "ED_gpencil.h"
#include "ED_object.h"
#include "ED_particle.h"
-#include "ED_view3d.h"
-#include "ED_gpencil.h"
#include "ED_screen.h"
-#include "ED_gizmo_library.h"
-#include "ED_gizmo_utils.h"
+#include "ED_view3d.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -347,7 +347,7 @@ static void gizmo_get_axis_color(const int axis_idx,
if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
/* Never fade rotation rings. */
/* trackball rotation axis is a special case, we only draw a slight overlay */
- alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.1f : 1.0f;
+ alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.05f : 1.0f;
}
else {
bool is_plane = false;
@@ -397,7 +397,7 @@ static void gizmo_get_axis_color(const int axis_idx,
case MAN_AXIS_ROT_C:
case MAN_AXIS_SCALE_C:
case MAN_AXIS_ROT_T:
- copy_v4_fl(r_col, 1.0f);
+ UI_GetThemeColor4fv(TH_GIZMO_VIEW_ALIGN, r_col);
break;
}
@@ -637,11 +637,11 @@ bool gimbal_axis(Object *ob, float gmat[3][3])
void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3])
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
Object *ob = OBACT(view_layer);
const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
@@ -713,7 +713,9 @@ void ED_transform_calc_orientation_from_type_ex(const bContext *C,
ok = true;
break;
}
- case V3D_ORIENT_CUSTOM: {
+ case V3D_ORIENT_CUSTOM:
+ default: {
+ BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM);
TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
scene, orientation_index_custom);
if (applyTransformOrientation(custom_orientation, r_mat, NULL)) {
@@ -734,16 +736,16 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
const struct TransformCalcParams *params,
struct TransformBounds *tbounds)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
/* TODO(sergey): This function is used from operator's modal() and from gizmo's refresh().
* Is it fine to possibly evaluate dependency graph here? */
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = ar->regiondata;
+ RegionView3D *rv3d = region->regiondata;
Base *base;
Object *ob = OBACT(view_layer);
bGPdata *gpd = CTX_data_gpencil_data(C);
@@ -792,15 +794,15 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
if (is_gp_edit) {
float diff_mat[4][4];
const bool use_mat_local = true;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat);
- for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -883,7 +885,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
if (use_mat_local) {
mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
}
- for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
if (EBONE_VISIBLE(arm, ebo)) {
if (ebo->flag & BONE_TIPSEL) {
calc_tw_center_with_matrix(tbounds, ebo->tail, use_mat_local, mat_local);
@@ -977,7 +979,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
}
- for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
+ LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
if (ml->flag & SELECT) {
calc_tw_center_with_matrix(tbounds, &ml->x, use_mat_local, mat_local);
totsel++;
@@ -1033,7 +1035,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
/* mislead counting bones... bah. We don't know the gizmo mode, could be mixed */
const int mode = TFM_ROTATION;
- const int totsel_iter = count_set_pose_transflags(
+ const int totsel_iter = transform_convert_pose_transflags_update(
ob_iter, mode, V3D_AROUND_CENTER_BOUNDS, NULL);
if (totsel_iter) {
@@ -1244,13 +1246,13 @@ static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
struct wmMsgBus *mbus,
Scene *scene,
bScreen *screen,
- ScrArea *sa,
- ARegion *ar,
+ ScrArea *area,
+ ARegion *region,
const void *type_fn)
{
/* Subscribe to view properties */
wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
+ .owner = region,
.user_data = gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
};
@@ -1334,7 +1336,7 @@ static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
}
PointerRNA view3d_ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceView3D, sa->spacedata.first, &view3d_ptr);
+ RNA_pointer_create(&screen->id, &RNA_SpaceView3D, area->spacedata.first, &view3d_ptr);
if (type_fn == VIEW3D_GGT_xform_gizmo) {
GizmoGroup *ggd = gzgroup->customdata;
@@ -1369,7 +1371,7 @@ static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
void drawDial3d(const TransInfo *t)
{
if (t->mode == TFM_ROTATION && t->spacetype == SPACE_VIEW3D) {
- wmGizmo *gz = wm_gizmomap_modal_get(t->ar->gizmo_map);
+ wmGizmo *gz = wm_gizmomap_modal_get(t->region->gizmo_map);
if (gz == NULL) {
/* We only draw Dial3d if the operator has been called by a gizmo. */
return;
@@ -1402,7 +1404,7 @@ void drawDial3d(const TransInfo *t)
}
else {
axis_idx = MAN_AXIS_ROT_C;
- negate_v3_v3(mat_basis[2], t->orient_matrix[t->orient_axis]);
+ negate_v3_v3(mat_basis[2], t->spacemtx[t->orient_axis]);
scale *= 1.2f;
line_with -= 1.0f;
}
@@ -1411,7 +1413,7 @@ void drawDial3d(const TransInfo *t)
mat_basis[2][3] = -dot_v3v3(mat_basis[2], mat_basis[3]);
if (ED_view3d_win_to_3d_on_plane(
- t->ar, mat_basis[2], (float[2]){UNPACK2(t->mouse.imval)}, false, mat_basis[1])) {
+ t->region, mat_basis[2], (float[2]){UNPACK2(t->mouse.imval)}, false, mat_basis[1])) {
sub_v3_v3(mat_basis[1], mat_basis[3]);
normalize_v3(mat_basis[1]);
cross_v3_v3v3(mat_basis[0], mat_basis[1], mat_basis[2]);
@@ -1428,7 +1430,7 @@ void drawDial3d(const TransInfo *t)
mat_basis[3][3] = 1.0f;
copy_m4_m4(mat_final, mat_basis);
- scale *= ED_view3d_pixel_size_no_ui_scale(t->ar->regiondata, mat_final[3]);
+ scale *= ED_view3d_pixel_size_no_ui_scale(t->region->regiondata, mat_final[3]);
mul_mat3_m4_fl(mat_final, scale);
if (activeSnap(t) && (!transformModeUseSnap(t) ||
@@ -1554,8 +1556,8 @@ static int gizmo_modal(bContext *C,
return OPERATOR_RUNNING_MODAL;
}
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
struct TransformBounds tbounds;
if (ED_transform_calc_gizmo_stats(C,
@@ -1567,7 +1569,7 @@ static int gizmo_modal(bContext *C,
WM_gizmo_set_matrix_location(widget, rv3d->twmat[3]);
}
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_editor_overlays(region);
return OPERATOR_RUNNING_MODAL;
}
@@ -1701,8 +1703,8 @@ static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup)
gzgroup->customdata = ggd;
{
- ScrArea *sa = CTX_wm_area(C);
- const bToolRef *tref = sa->runtime.tool;
+ ScrArea *area = CTX_wm_area(C);
+ const bToolRef *tref = area->runtime.tool;
ggd->twtype = 0;
if (tref && STREQ(tref->idname, "builtin.move")) {
@@ -1737,10 +1739,10 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
GizmoGroup *ggd = gzgroup->customdata;
Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ScrArea *area = CTX_wm_area(C);
+ View3D *v3d = area->spacedata.first;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
struct TransformBounds tbounds;
if (scene->toolsettings->workspace_tool_type == SCE_WORKSPACE_TOOL_FALLBACK) {
@@ -1844,25 +1846,26 @@ static void WIDGETGROUP_gizmo_message_subscribe(const bContext *C,
{
Scene *scene = CTX_data_scene(C);
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_gizmo);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ gizmo_xform_message_subscribe(
+ gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_gizmo);
}
static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
GizmoGroup *ggd = gzgroup->customdata;
- // ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- // View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->regiondata;
+ // ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ // View3D *v3d = area->spacedata.first;
+ RegionView3D *rv3d = region->regiondata;
float viewinv_m3[3][3];
copy_m3_m4(viewinv_m3, rv3d->viewinv);
float idot[3];
/* when looking through a selected camera, the gizmo can be at the
* exact same position as the view, skip so we don't break selection */
- if (ggd->all_hidden || fabsf(ED_view3d_pixel_size(rv3d, rv3d->twmat[3])) < 1e-6f) {
+ if (ggd->all_hidden || fabsf(ED_view3d_pixel_size(rv3d, rv3d->twmat[3])) < 5e-7f) {
MAN_ITER_AXES_BEGIN (axis, axis_idx) {
WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
}
@@ -1997,13 +2000,13 @@ static bool WIDGETGROUP_gizmo_poll_generic(View3D *v3d)
static bool WIDGETGROUP_gizmo_poll_context(const struct bContext *C,
struct wmGizmoGroupType *UNUSED(gzgt))
{
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
+ ScrArea *area = CTX_wm_area(C);
+ View3D *v3d = area->spacedata.first;
if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
return false;
}
- const bToolRef *tref = sa->runtime.tool;
+ const bToolRef *tref = area->runtime.tool;
if (v3d->gizmo_flag & V3D_GIZMO_HIDE_CONTEXT) {
return false;
}
@@ -2025,8 +2028,8 @@ static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmo
return false;
}
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
+ ScrArea *area = CTX_wm_area(C);
+ View3D *v3d = area->spacedata.first;
if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
return false;
}
@@ -2168,8 +2171,8 @@ static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup
static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
Scene *scene = CTX_data_scene(C);
struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
@@ -2247,9 +2250,9 @@ static void WIDGETGROUP_xform_cage_message_subscribe(const bContext *C,
{
Scene *scene = CTX_data_scene(C);
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_cage);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_cage);
}
static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
@@ -2384,8 +2387,8 @@ static void WIDGETGROUP_xform_shear_setup(const bContext *UNUSED(C), wmGizmoGrou
static void WIDGETGROUP_xform_shear_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
struct TransformBounds tbounds;
@@ -2460,9 +2463,10 @@ static void WIDGETGROUP_xform_shear_message_subscribe(const bContext *C,
{
Scene *scene = CTX_data_scene(C);
bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_shear);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ gizmo_xform_message_subscribe(
+ gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_shear);
}
static void WIDGETGROUP_xform_shear_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c
index fb33471cf3f..e6e74668c2c 100644
--- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c
@@ -18,10 +18,10 @@
* \ingroup edmesh
*/
-#include "BLI_utildefines.h"
#include "BLI_array_utils.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -30,15 +30,15 @@
#include "RNA_define.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
+#include "ED_gizmo_library.h"
+#include "ED_gizmo_utils.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_view3d.h"
-#include "ED_gizmo_library.h"
-#include "ED_gizmo_utils.h"
#include "UI_resources.h"
@@ -469,11 +469,11 @@ static void gizmo_mesh_extrude_message_subscribe(const bContext *C,
struct wmMsgBus *mbus)
{
GizmoExtrudeGroup *ggd = gzgroup->customdata;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
/* Subscribe to view properties */
wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
+ .owner = region,
.user_data = gzgroup->parent_gzmap,
.notify = WM_gizmo_do_msg_notify_tag_refresh,
};
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 8dc403c45d2..078020e932e 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -18,8 +18,8 @@
* \ingroup edtransform
*/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#include "DNA_screen_types.h"
@@ -28,20 +28,24 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "WM_types.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "transform.h"
#include "MEM_guardedalloc.h"
-/* ************************** INPUT FROM MOUSE *************************** */
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for #MouseInput.apply
+ * \{ */
+/** Callback for #INPUT_VECTOR */
static void InputVector(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
convertViewVec(t, output, mval[0] - mi->imval[0], mval[1] - mi->imval[1]);
}
+/** Callback for #INPUT_SPRING */
static void InputSpring(TransInfo *UNUSED(t),
MouseInput *mi,
const double mval[2],
@@ -57,6 +61,7 @@ static void InputSpring(TransInfo *UNUSED(t),
output[0] = ratio;
}
+/** Callback for #INPUT_SPRING_FLIP */
static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
InputSpring(t, mi, mval, output);
@@ -70,12 +75,14 @@ static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2],
}
}
+/** Callback for #INPUT_SPRING_DELTA */
static void InputSpringDelta(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
InputSpring(t, mi, mval, output);
output[0] -= 1.0f;
}
+/** Callback for #INPUT_TRACKBALL */
static void InputTrackBall(TransInfo *UNUSED(t),
MouseInput *mi,
const double mval[2],
@@ -88,16 +95,18 @@ static void InputTrackBall(TransInfo *UNUSED(t),
output[1] *= mi->factor;
}
+/** Callback for #INPUT_HORIZONTAL_RATIO */
static void InputHorizontalRatio(TransInfo *t,
MouseInput *mi,
const double mval[2],
float output[3])
{
- const int winx = t->ar ? t->ar->winx : 1;
+ const int winx = t->region ? t->region->winx : 1;
output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f;
}
+/** Callback for #INPUT_HORIZONTAL_ABSOLUTE */
static void InputHorizontalAbsolute(TransInfo *t,
MouseInput *mi,
const double mval[2],
@@ -113,12 +122,13 @@ static void InputHorizontalAbsolute(TransInfo *t,
static void InputVerticalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- const int winy = t->ar ? t->ar->winy : 1;
+ const int winy = t->region ? t->region->winy : 1;
/* Flip so dragging up increases (matching viewport zoom). */
output[0] = ((mval[1] - mi->imval[1]) / winy) * -2.0f;
}
+/** Callback for #INPUT_VERTICAL_ABSOLUTE */
static void InputVerticalAbsolute(TransInfo *t,
MouseInput *mi,
const double mval[2],
@@ -133,38 +143,7 @@ static void InputVerticalAbsolute(TransInfo *t,
output[0] = dot_v3v3(t->viewinv[1], vec) * -2.0f;
}
-void setCustomPoints(TransInfo *UNUSED(t),
- MouseInput *mi,
- const int mval_start[2],
- const int mval_end[2])
-{
- int *data;
-
- mi->data = MEM_reallocN(mi->data, sizeof(int) * 4);
-
- data = mi->data;
-
- data[0] = mval_start[0];
- data[1] = mval_start[1];
- data[2] = mval_end[0];
- data[3] = mval_end[1];
-}
-
-void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2])
-{
- BLI_ASSERT_UNIT_V2(dir);
- const int win_axis = t->ar ?
- ((abs((int)(t->ar->winx * dir[0])) + abs((int)(t->ar->winy * dir[1]))) /
- 2) :
- 1;
- const int mval_start[2] = {
- mi->imval[0] + dir[0] * win_axis,
- mi->imval[1] + dir[1] * win_axis,
- };
- const int mval_end[2] = {mi->imval[0], mi->imval[1]};
- setCustomPoints(t, mi, mval_start, mval_end);
-}
-
+/** Callback for #INPUT_CUSTOM_RATIO_FLIP */
static void InputCustomRatioFlip(TransInfo *UNUSED(t),
MouseInput *mi,
const double mval[2],
@@ -191,6 +170,7 @@ static void InputCustomRatioFlip(TransInfo *UNUSED(t),
}
}
+/** Callback for #INPUT_CUSTOM_RATIO */
static void InputCustomRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
InputCustomRatioFlip(t, mi, mval, output);
@@ -202,6 +182,7 @@ struct InputAngle_Data {
double mval_prev[2];
};
+/** Callback for #INPUT_ANGLE */
static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
{
struct InputAngle_Data *data = mi->data;
@@ -270,6 +251,53 @@ static void InputAngleSpring(TransInfo *t, MouseInput *mi, const double mval[2],
output[1] = toutput[0];
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Custom 2D Start/End Coordinate API
+ *
+ * - #INPUT_CUSTOM_RATIO
+ * - #INPUT_CUSTOM_RATIO_FLIP
+ * \{ */
+
+void setCustomPoints(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const int mval_start[2],
+ const int mval_end[2])
+{
+ int *data;
+
+ mi->data = MEM_reallocN(mi->data, sizeof(int) * 4);
+
+ data = mi->data;
+
+ data[0] = mval_start[0];
+ data[1] = mval_start[1];
+ data[2] = mval_end[0];
+ data[3] = mval_end[1];
+}
+
+void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2])
+{
+ BLI_ASSERT_UNIT_V2(dir);
+ const int win_axis = t->region ? ((abs((int)(t->region->winx * dir[0])) +
+ abs((int)(t->region->winy * dir[1]))) /
+ 2) :
+ 1;
+ const int mval_start[2] = {
+ mi->imval[0] + dir[0] * win_axis,
+ mi->imval[1] + dir[1] * win_axis,
+ };
+ const int mval_end[2] = {mi->imval[0], mi->imval[1]};
+ setCustomPoints(t, mi, mval_start, mval_end);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Setup & Handle Mouse Input
+ * \{ */
+
void initMouseInput(TransInfo *UNUSED(t),
MouseInput *mi,
const float center[2],
@@ -476,8 +504,8 @@ eRedrawFlag handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event)
eRedrawFlag redraw = TREDRAW_NOTHING;
switch (event->type) {
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY:
if (event->val == KM_PRESS) {
t->modifiers |= MOD_PRECISION;
/* shift is modifier for higher precision transforn */
@@ -494,3 +522,5 @@ eRedrawFlag handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event)
return redraw;
}
+
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
new file mode 100644
index 00000000000..4c14c3aebd7
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode.c
@@ -0,0 +1,1264 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_nla.h"
+
+#include "RNA_access.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_snap.h"
+
+/* Own include. */
+#include "transform_mode.h"
+
+bool transdata_check_local_center(TransInfo *t, short around)
+{
+ return ((around == V3D_AROUND_LOCAL_ORIGINS) &&
+ ((t->flag & (T_OBJECT | T_POSE)) ||
+ /* implicit: (t->flag & T_EDIT) */
+ (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) ||
+ (t->spacetype == SPACE_GRAPH) ||
+ (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE))));
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Transform Locks
+ * \{ */
+
+void protectedTransBits(short protectflag, float vec[3])
+{
+ if (protectflag & OB_LOCK_LOCX) {
+ vec[0] = 0.0f;
+ }
+ if (protectflag & OB_LOCK_LOCY) {
+ vec[1] = 0.0f;
+ }
+ if (protectflag & OB_LOCK_LOCZ) {
+ vec[2] = 0.0f;
+ }
+}
+
+/* this function only does the delta rotation */
+static void protectedQuaternionBits(short protectflag, float quat[4], const float oldquat[4])
+{
+ /* check that protection flags are set */
+ if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) {
+ return;
+ }
+
+ if (protectflag & OB_LOCK_ROT4D) {
+ /* quaternions getting limited as 4D entities that they are... */
+ if (protectflag & OB_LOCK_ROTW) {
+ quat[0] = oldquat[0];
+ }
+ if (protectflag & OB_LOCK_ROTX) {
+ quat[1] = oldquat[1];
+ }
+ if (protectflag & OB_LOCK_ROTY) {
+ quat[2] = oldquat[2];
+ }
+ if (protectflag & OB_LOCK_ROTZ) {
+ quat[3] = oldquat[3];
+ }
+ }
+ else {
+ /* quaternions get limited with euler... (compatibility mode) */
+ float eul[3], oldeul[3], nquat[4], noldquat[4];
+ float qlen;
+
+ qlen = normalize_qt_qt(nquat, quat);
+ normalize_qt_qt(noldquat, oldquat);
+
+ quat_to_eul(eul, nquat);
+ quat_to_eul(oldeul, noldquat);
+
+ if (protectflag & OB_LOCK_ROTX) {
+ eul[0] = oldeul[0];
+ }
+ if (protectflag & OB_LOCK_ROTY) {
+ eul[1] = oldeul[1];
+ }
+ if (protectflag & OB_LOCK_ROTZ) {
+ eul[2] = oldeul[2];
+ }
+
+ eul_to_quat(quat, eul);
+
+ /* restore original quat size */
+ mul_qt_fl(quat, qlen);
+
+ /* quaternions flip w sign to accumulate rotations correctly */
+ if ((nquat[0] < 0.0f && quat[0] > 0.0f) || (nquat[0] > 0.0f && quat[0] < 0.0f)) {
+ mul_qt_fl(quat, -1.0f);
+ }
+ }
+}
+
+static void protectedRotateBits(short protectflag, float eul[3], const float oldeul[3])
+{
+ if (protectflag & OB_LOCK_ROTX) {
+ eul[0] = oldeul[0];
+ }
+ if (protectflag & OB_LOCK_ROTY) {
+ eul[1] = oldeul[1];
+ }
+ if (protectflag & OB_LOCK_ROTZ) {
+ eul[2] = oldeul[2];
+ }
+}
+
+/* this function only does the delta rotation */
+/* axis-angle is usually internally stored as quats... */
+static void protectedAxisAngleBits(
+ short protectflag, float axis[3], float *angle, float oldAxis[3], float oldAngle)
+{
+ /* check that protection flags are set */
+ if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) {
+ return;
+ }
+
+ if (protectflag & OB_LOCK_ROT4D) {
+ /* axis-angle getting limited as 4D entities that they are... */
+ if (protectflag & OB_LOCK_ROTW) {
+ *angle = oldAngle;
+ }
+ if (protectflag & OB_LOCK_ROTX) {
+ axis[0] = oldAxis[0];
+ }
+ if (protectflag & OB_LOCK_ROTY) {
+ axis[1] = oldAxis[1];
+ }
+ if (protectflag & OB_LOCK_ROTZ) {
+ axis[2] = oldAxis[2];
+ }
+ }
+ else {
+ /* axis-angle get limited with euler... */
+ float eul[3], oldeul[3];
+
+ axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, axis, *angle);
+ axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, oldAxis, oldAngle);
+
+ if (protectflag & OB_LOCK_ROTX) {
+ eul[0] = oldeul[0];
+ }
+ if (protectflag & OB_LOCK_ROTY) {
+ eul[1] = oldeul[1];
+ }
+ if (protectflag & OB_LOCK_ROTZ) {
+ eul[2] = oldeul[2];
+ }
+
+ eulO_to_axis_angle(axis, angle, eul, EULER_ORDER_DEFAULT);
+
+ /* When converting to axis-angle,
+ * we need a special exception for the case when there is no axis. */
+ if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) {
+ /* for now, rotate around y-axis then (so that it simply becomes the roll) */
+ axis[1] = 1.0f;
+ }
+ }
+}
+
+static void protectedSizeBits(short protectflag, float size[3])
+{
+ if (protectflag & OB_LOCK_SCALEX) {
+ size[0] = 1.0f;
+ }
+ if (protectflag & OB_LOCK_SCALEY) {
+ size[1] = 1.0f;
+ }
+ if (protectflag & OB_LOCK_SCALEZ) {
+ size[2] = 1.0f;
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform Limits
+ * \{ */
+
+void constraintTransLim(TransInfo *t, TransData *td)
+{
+ if (td->con) {
+ const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(
+ CONSTRAINT_TYPE_LOCLIMIT);
+ const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(
+ CONSTRAINT_TYPE_DISTLIMIT);
+
+ bConstraintOb cob = {NULL};
+ bConstraint *con;
+ float ctime = (float)(t->scene->r.cfra);
+
+ /* Make a temporary bConstraintOb for using these limit constraints
+ * - they only care that cob->matrix is correctly set ;-)
+ * - current space should be local
+ */
+ unit_m4(cob.matrix);
+ copy_v3_v3(cob.matrix[3], td->loc);
+
+ /* Evaluate valid constraints */
+ for (con = td->con; con; con = con->next) {
+ const bConstraintTypeInfo *cti = NULL;
+ ListBase targets = {NULL, NULL};
+
+ /* only consider constraint if enabled */
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
+ continue;
+ }
+ if (con->enforce == 0.0f) {
+ continue;
+ }
+
+ /* only use it if it's tagged for this purpose (and the right type) */
+ if (con->type == CONSTRAINT_TYPE_LOCLIMIT) {
+ bLocLimitConstraint *data = (bLocLimitConstraint *)con->data;
+
+ if ((data->flag2 & LIMIT_TRANSFORM) == 0) {
+ continue;
+ }
+ cti = ctiLoc;
+ }
+ else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) {
+ bDistLimitConstraint *data = (bDistLimitConstraint *)con->data;
+
+ if ((data->flag & LIMITDIST_TRANSFORM) == 0) {
+ continue;
+ }
+ cti = ctiDist;
+ }
+
+ if (cti) {
+ /* do space conversions */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
+ }
+ else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
+ /* skip... incompatible spacetype */
+ continue;
+ }
+
+ /* get constraint targets if needed */
+ BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime);
+
+ /* do constraint */
+ cti->evaluate_constraint(con, &cob, &targets);
+
+ /* convert spaces again */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->smtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
+ }
+
+ /* free targets list */
+ BLI_freelistN(&targets);
+ }
+ }
+
+ /* copy results from cob->matrix */
+ copy_v3_v3(td->loc, cob.matrix[3]);
+ }
+}
+
+static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
+{
+ /* Make a temporary bConstraintOb for use by limit constraints
+ * - they only care that cob->matrix is correctly set ;-)
+ * - current space should be local
+ */
+ memset(cob, 0, sizeof(bConstraintOb));
+ if (td->ext) {
+ if (td->ext->rotOrder == ROT_MODE_QUAT) {
+ /* quats */
+ /* objects and bones do normalization first too, otherwise
+ * we don't necessarily end up with a rotation matrix, and
+ * then conversion back to quat gives a different result */
+ float quat[4];
+ normalize_qt_qt(quat, td->ext->quat);
+ quat_to_mat4(cob->matrix, quat);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ /* axis angle */
+ axis_angle_to_mat4(cob->matrix, td->ext->rotAxis, *td->ext->rotAngle);
+ }
+ else {
+ /* eulers */
+ eulO_to_mat4(cob->matrix, td->ext->rot, td->ext->rotOrder);
+ }
+ }
+}
+
+static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
+{
+ if (td->con) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT);
+ bConstraintOb cob;
+ bConstraint *con;
+ bool do_limit = false;
+
+ /* Evaluate valid constraints */
+ for (con = td->con; con; con = con->next) {
+ /* only consider constraint if enabled */
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
+ continue;
+ }
+ if (con->enforce == 0.0f) {
+ continue;
+ }
+
+ /* we're only interested in Limit-Rotation constraints */
+ if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
+ bRotLimitConstraint *data = (bRotLimitConstraint *)con->data;
+
+ /* only use it if it's tagged for this purpose */
+ if ((data->flag2 & LIMIT_TRANSFORM) == 0) {
+ continue;
+ }
+
+ /* skip incompatible spacetypes */
+ if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) {
+ continue;
+ }
+
+ /* only do conversion if necessary, to preserve quats and eulers */
+ if (do_limit == false) {
+ constraintob_from_transdata(&cob, td);
+ do_limit = true;
+ }
+
+ /* do space conversions */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
+ }
+
+ /* do constraint */
+ cti->evaluate_constraint(con, &cob, NULL);
+
+ /* convert spaces again */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->smtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
+ }
+ }
+ }
+
+ if (do_limit) {
+ /* copy results from cob->matrix */
+ if (td->ext->rotOrder == ROT_MODE_QUAT) {
+ /* quats */
+ mat4_to_quat(td->ext->quat, cob.matrix);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ /* axis angle */
+ mat4_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, cob.matrix);
+ }
+ else {
+ /* eulers */
+ mat4_to_eulO(td->ext->rot, td->ext->rotOrder, cob.matrix);
+ }
+ }
+ }
+}
+
+static void constraintSizeLim(TransInfo *t, TransData *td)
+{
+ if (td->con && td->ext) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
+ bConstraintOb cob = {NULL};
+ bConstraint *con;
+ float size_sign[3], size_abs[3];
+ int i;
+
+ /* Make a temporary bConstraintOb for using these limit constraints
+ * - they only care that cob->matrix is correctly set ;-)
+ * - current space should be local
+ */
+ if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
+ /* scale val and reset size */
+ return; // TODO: fix this case
+ }
+ else {
+ /* Reset val if SINGLESIZE but using a constraint */
+ if (td->flag & TD_SINGLESIZE) {
+ return;
+ }
+
+ /* separate out sign to apply back later */
+ for (i = 0; i < 3; i++) {
+ size_sign[i] = signf(td->ext->size[i]);
+ size_abs[i] = fabsf(td->ext->size[i]);
+ }
+
+ size_to_mat4(cob.matrix, size_abs);
+ }
+
+ /* Evaluate valid constraints */
+ for (con = td->con; con; con = con->next) {
+ /* only consider constraint if enabled */
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
+ continue;
+ }
+ if (con->enforce == 0.0f) {
+ continue;
+ }
+
+ /* we're only interested in Limit-Scale constraints */
+ if (con->type == CONSTRAINT_TYPE_SIZELIMIT) {
+ bSizeLimitConstraint *data = con->data;
+
+ /* only use it if it's tagged for this purpose */
+ if ((data->flag2 & LIMIT_TRANSFORM) == 0) {
+ continue;
+ }
+
+ /* do space conversions */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
+ }
+ else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
+ /* skip... incompatible spacetype */
+ continue;
+ }
+
+ /* do constraint */
+ cti->evaluate_constraint(con, &cob, NULL);
+
+ /* convert spaces again */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->smtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
+ }
+ }
+ }
+
+ /* copy results from cob->matrix */
+ if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
+ /* scale val and reset size */
+ return; // TODO: fix this case
+ }
+ else {
+ /* Reset val if SINGLESIZE but using a constraint */
+ if (td->flag & TD_SINGLESIZE) {
+ return;
+ }
+
+ /* extrace scale from matrix and apply back sign */
+ mat4_to_size(td->ext->size, cob.matrix);
+ mul_v3_v3(td->ext->size, size_sign);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/* Transform (Rotation Utils) */
+
+/** \name Transform Rotation Utils
+ * \{ */
+/* Used by Transform Rotation and Transform Normal Rotation */
+void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final)
+{
+ size_t ofs = 0;
+
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ TIP_("Rot: %.2f%s %s"),
+ RAD2DEGF(final),
+ t->con.text,
+ t->proptext);
+ }
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
+ }
+}
+
+void postInputRotation(TransInfo *t, float values[3])
+{
+ float axis_final[3];
+ copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]);
+ if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
+ t->con.applyRot(t, NULL, NULL, axis_final, values);
+ }
+}
+
+/**
+ * Applies values of rotation to `td->loc` and `td->ext->quat`
+ * based on a rotation matrix (mat) and a pivot (center).
+ *
+ * Protected axis and other transform settings are taken into account.
+ */
+void ElementRotation_ex(TransInfo *t,
+ TransDataContainer *tc,
+ TransData *td,
+ const float mat[3][3],
+ const float *center)
+{
+ float vec[3], totmat[3][3], smat[3][3];
+ float eul[3], fmat[3][3], quat[4];
+
+ if (t->flag & T_POINTS) {
+ mul_m3_m3m3(totmat, mat, td->mtx);
+ mul_m3_m3m3(smat, td->smtx, totmat);
+
+ /* apply gpencil falloff */
+ if (t->options & CTX_GPENCIL_STROKES) {
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ float sx = smat[0][0];
+ float sy = smat[1][1];
+ float sz = smat[2][2];
+
+ mul_m3_fl(smat, gps->runtime.multi_frame_falloff);
+ /* fix scale */
+ smat[0][0] = sx;
+ smat[1][1] = sy;
+ smat[2][2] = sz;
+ }
+
+ sub_v3_v3v3(vec, td->iloc, center);
+ mul_m3_v3(smat, vec);
+
+ add_v3_v3v3(td->loc, vec, center);
+
+ sub_v3_v3v3(vec, td->loc, td->iloc);
+ protectedTransBits(td->protectflag, vec);
+ add_v3_v3v3(td->loc, td->iloc, vec);
+
+ if (td->flag & TD_USEQUAT) {
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
+ mat3_to_quat(quat, fmat); // Actual transform
+
+ if (td->ext->quat) {
+ mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
+
+ /* is there a reason not to have this here? -jahka */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
+ }
+ }
+ /**
+ * HACK WARNING
+ *
+ * This is some VERY ugly special case to deal with pose mode.
+ *
+ * The problem is that mtx and smtx include each bone orientation.
+ *
+ * That is needed to rotate each bone properly, HOWEVER, to calculate
+ * the translation component, we only need the actual armature object's
+ * matrix (and inverse). That is not all though. Once the proper translation
+ * has been computed, it has to be converted back into the bone's space.
+ */
+ else if (t->flag & T_POSE) {
+ // Extract and invert armature object matrix
+
+ if ((td->flag & TD_NO_LOC) == 0) {
+ sub_v3_v3v3(vec, td->center, center);
+
+ mul_m3_v3(tc->mat3, vec); // To Global space
+ mul_m3_v3(mat, vec); // Applying rotation
+ mul_m3_v3(tc->imat3, vec); // To Local space
+
+ add_v3_v3(vec, center);
+ /* vec now is the location where the object has to be */
+
+ sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location
+
+ /* special exception, see TD_PBONE_LOCAL_MTX definition comments */
+ if (td->flag & TD_PBONE_LOCAL_MTX_P) {
+ /* do nothing */
+ }
+ else if (td->flag & TD_PBONE_LOCAL_MTX_C) {
+ mul_m3_v3(tc->mat3, vec); // To Global space
+ mul_m3_v3(td->ext->l_smtx, vec); // To Pose space (Local Location)
+ }
+ else {
+ mul_m3_v3(tc->mat3, vec); // To Global space
+ mul_m3_v3(td->smtx, vec); // To Pose space
+ }
+
+ protectedTransBits(td->protectflag, vec);
+
+ add_v3_v3v3(td->loc, td->iloc, vec);
+
+ constraintTransLim(t, td);
+ }
+
+ /* rotation */
+ /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same,
+ * and ElementRotation() might be called in Translation context (with align snapping),
+ * we need to be sure to actually use the *rotation* matrix here...
+ * So no other way than storing it in some dedicated members of td->ext! */
+ if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */
+ /* euler or quaternion/axis-angle? */
+ if (td->ext->rotOrder == ROT_MODE_QUAT) {
+ mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
+
+ mat3_to_quat(quat, fmat); /* Actual transform */
+
+ mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
+ /* this function works on end result */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ /* calculate effect based on quats */
+ float iquat[4], tquat[4];
+
+ axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
+
+ mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
+ mat3_to_quat(quat, fmat); /* Actual transform */
+ mul_qt_qtqt(tquat, quat, iquat);
+
+ quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
+
+ /* this function works on end result */
+ protectedAxisAngleBits(td->protectflag,
+ td->ext->rotAxis,
+ td->ext->rotAngle,
+ td->ext->irotAxis,
+ td->ext->irotAngle);
+ }
+ else {
+ float eulmat[3][3];
+
+ mul_m3_m3m3(totmat, mat, td->ext->r_mtx);
+ mul_m3_m3m3(smat, td->ext->r_smtx, totmat);
+
+ /* calculate the total rotatation in eulers */
+ copy_v3_v3(eul, td->ext->irot);
+ eulO_to_mat3(eulmat, eul, td->ext->rotOrder);
+
+ /* mat = transform, obmat = bone rotation */
+ mul_m3_m3m3(fmat, smat, eulmat);
+
+ mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
+
+ /* and apply (to end result only) */
+ protectedRotateBits(td->protectflag, eul, td->ext->irot);
+ copy_v3_v3(td->ext->rot, eul);
+ }
+
+ constraintRotLim(t, td);
+ }
+ }
+ else {
+ if ((td->flag & TD_NO_LOC) == 0) {
+ /* translation */
+ sub_v3_v3v3(vec, td->center, center);
+ mul_m3_v3(mat, vec);
+ add_v3_v3(vec, center);
+ /* vec now is the location where the object has to be */
+ sub_v3_v3(vec, td->center);
+ mul_m3_v3(td->smtx, vec);
+
+ protectedTransBits(td->protectflag, vec);
+
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+
+ constraintTransLim(t, td);
+
+ /* rotation */
+ if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself
+ /* euler or quaternion? */
+ if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
+ /* can be called for texture space translate for example, then opt out */
+ if (td->ext->quat) {
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
+ mat3_to_quat(quat, fmat); // Actual transform
+
+ mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
+ /* this function works on end result */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ /* calculate effect based on quats */
+ float iquat[4], tquat[4];
+
+ axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
+
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
+ mat3_to_quat(quat, fmat); // Actual transform
+ mul_qt_qtqt(tquat, quat, iquat);
+
+ quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
+
+ /* this function works on end result */
+ protectedAxisAngleBits(td->protectflag,
+ td->ext->rotAxis,
+ td->ext->rotAngle,
+ td->ext->irotAxis,
+ td->ext->irotAngle);
+ }
+ else {
+ float obmat[3][3];
+
+ mul_m3_m3m3(totmat, mat, td->mtx);
+ mul_m3_m3m3(smat, td->smtx, totmat);
+
+ /* calculate the total rotatation in eulers */
+ add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */
+ eulO_to_mat3(obmat, eul, td->ext->rotOrder);
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
+
+ /* correct back for delta rot */
+ sub_v3_v3v3(eul, eul, td->ext->drot);
+
+ /* and apply */
+ protectedRotateBits(td->protectflag, eul, td->ext->irot);
+ copy_v3_v3(td->ext->rot, eul);
+ }
+
+ constraintRotLim(t, td);
+ }
+ }
+}
+
+void ElementRotation(
+ TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around)
+{
+ const float *center;
+
+ /* local constraint shouldn't alter center */
+ if (transdata_check_local_center(t, around)) {
+ center = td->center;
+ }
+ else {
+ center = tc->center_local;
+ }
+
+ ElementRotation_ex(t, tc, td, mat, center);
+}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/* Transform (Resize Utils) */
+
+/** \name Transform Resize Utils
+ * \{ */
+void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR])
+{
+ char tvec[NUM_STR_REP_LEN * 3];
+ size_t ofs = 0;
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
+ }
+
+ if (t->con.mode & CON_APPLY) {
+ switch (t->num.idx_max) {
+ case 0:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ TIP_("Scale: %s%s %s"),
+ &tvec[0],
+ t->con.text,
+ t->proptext);
+ break;
+ case 1:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ TIP_("Scale: %s : %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ t->con.text,
+ t->proptext);
+ break;
+ case 2:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ TIP_("Scale: %s : %s : %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ t->con.text,
+ t->proptext);
+ break;
+ }
+ }
+ else {
+ if (t->flag & T_2D_EDIT) {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ TIP_("Scale X: %s Y: %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ t->con.text,
+ t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ TIP_("Scale X: %s Y: %s Z: %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ t->con.text,
+ t->proptext);
+ }
+ }
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
+ }
+}
+
+/**
+ * \a smat is reference matrix only.
+ *
+ * \note this is a tricky area, before making changes see: T29633, T42444
+ */
+static void TransMat3ToSize(float mat[3][3], float smat[3][3], float size[3])
+{
+ float rmat[3][3];
+
+ mat3_to_rot_size(rmat, size, mat);
+
+ /* first tried with dotproduct... but the sign flip is crucial */
+ if (dot_v3v3(rmat[0], smat[0]) < 0.0f) {
+ size[0] = -size[0];
+ }
+ if (dot_v3v3(rmat[1], smat[1]) < 0.0f) {
+ size[1] = -size[1];
+ }
+ if (dot_v3v3(rmat[2], smat[2]) < 0.0f) {
+ size[2] = -size[2];
+ }
+}
+
+void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3])
+{
+ float tmat[3][3], smat[3][3], center[3];
+ float vec[3];
+
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(smat, mat, td->mtx);
+ mul_m3_m3m3(tmat, td->smtx, smat);
+ }
+ else {
+ copy_m3_m3(tmat, mat);
+ }
+
+ if (t->con.applySize) {
+ t->con.applySize(t, tc, td, tmat);
+ }
+
+ /* local constraint shouldn't alter center */
+ if (transdata_check_local_center(t, t->around)) {
+ copy_v3_v3(center, td->center);
+ }
+ else if (t->options & CTX_MOVIECLIP) {
+ if (td->flag & TD_INDIVIDUAL_SCALE) {
+ copy_v3_v3(center, td->center);
+ }
+ else {
+ copy_v3_v3(center, tc->center_local);
+ }
+ }
+ else {
+ copy_v3_v3(center, tc->center_local);
+ }
+
+ /* Size checked needed since the 3D cursor only uses rotation fields. */
+ if (td->ext && td->ext->size) {
+ float fsize[3];
+
+ if ((t->options & CTX_SCULPT) || t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) {
+ float obsizemat[3][3];
+ /* Reorient the size mat to fit the oriented object. */
+ mul_m3_m3m3(obsizemat, tmat, td->axismtx);
+ /* print_m3("obsizemat", obsizemat); */
+ TransMat3ToSize(obsizemat, td->axismtx, fsize);
+ /* print_v3("fsize", fsize); */
+ }
+ else {
+ mat3_to_size(fsize, tmat);
+ }
+
+ protectedSizeBits(td->protectflag, fsize);
+
+ if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */
+ if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
+ /* scale val and reset size */
+ *td->val = td->ival * (1 + (fsize[0] - 1) * td->factor);
+
+ td->ext->size[0] = td->ext->isize[0];
+ td->ext->size[1] = td->ext->isize[1];
+ td->ext->size[2] = td->ext->isize[2];
+ }
+ else {
+ /* Reset val if SINGLESIZE but using a constraint */
+ if (td->flag & TD_SINGLESIZE) {
+ *td->val = td->ival;
+ }
+
+ td->ext->size[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor);
+ td->ext->size[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor);
+ td->ext->size[2] = td->ext->isize[2] * (1 + (fsize[2] - 1) * td->factor);
+ }
+ }
+
+ constraintSizeLim(t, td);
+ }
+
+ /* For individual element center, Editmode need to use iloc */
+ if (t->flag & T_POINTS) {
+ sub_v3_v3v3(vec, td->iloc, center);
+ }
+ else {
+ sub_v3_v3v3(vec, td->center, center);
+ }
+
+ mul_m3_v3(tmat, vec);
+
+ add_v3_v3(vec, center);
+ if (t->flag & T_POINTS) {
+ sub_v3_v3(vec, td->iloc);
+ }
+ else {
+ sub_v3_v3(vec, td->center);
+ }
+
+ /* grease pencil falloff */
+ if (t->options & CTX_GPENCIL_STROKES) {
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
+
+ /* scale stroke thickness */
+ if (td->val) {
+ snapGridIncrement(t, t->values_final);
+ applyNumInput(&t->num, t->values_final);
+
+ float ratio = t->values_final[0];
+ *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff;
+ CLAMP_MIN(*td->val, 0.001f);
+ }
+ }
+ else {
+ mul_v3_fl(vec, td->factor);
+ }
+
+ if (t->flag & (T_OBJECT | T_POSE)) {
+ mul_m3_v3(td->smtx, vec);
+ }
+
+ protectedTransBits(td->protectflag, vec);
+ if (td->loc) {
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+
+ constraintTransLim(t, td);
+}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/* Transform (Frame Utils) */
+
+/** \name Transform Frame Utils
+ * \{ */
+
+/* This function returns the snapping 'mode' for Animation Editors only
+ * We cannot use the standard snapping due to NLA-strip scaling complexities.
+ */
+// XXX these modifier checks should be keymappable
+short getAnimEdit_SnapMode(TransInfo *t)
+{
+ short autosnap = SACTSNAP_OFF;
+
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
+
+ if (saction) {
+ autosnap = saction->autosnap;
+ }
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
+
+ if (sipo) {
+ autosnap = sipo->autosnap;
+ }
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ SpaceNla *snla = (SpaceNla *)t->area->spacedata.first;
+
+ if (snla) {
+ autosnap = snla->autosnap;
+ }
+ }
+ else {
+ autosnap = SACTSNAP_OFF;
+ }
+
+ /* toggle autosnap on/off
+ * - when toggling on, prefer nearest frame over 1.0 frame increments
+ */
+ if (t->modifiers & MOD_SNAP_INVERT) {
+ if (autosnap) {
+ autosnap = SACTSNAP_OFF;
+ }
+ else {
+ autosnap = SACTSNAP_FRAME;
+ }
+ }
+
+ return autosnap;
+}
+
+/* This function is used by Animation Editor specific transform functions to do
+ * the Snap Keyframe to Nearest Frame/Marker
+ */
+void doAnimEdit_SnapFrame(
+ TransInfo *t, TransData *td, TransData2D *td2d, AnimData *adt, short autosnap)
+{
+ if (autosnap != SACTSNAP_OFF) {
+ float val;
+
+ /* convert frame to nla-action time (if needed) */
+ if (adt && (t->spacetype != SPACE_SEQ)) {
+ val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP);
+ }
+ else {
+ val = *(td->val);
+ }
+
+ snapFrameTransform(t, autosnap, true, val, &val);
+
+ /* convert frame out of nla-action time */
+ if (adt && (t->spacetype != SPACE_SEQ)) {
+ *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
+ }
+ else {
+ *(td->val) = val;
+ }
+ }
+
+ /* If the handles are to be moved too
+ * (as side-effect of keyframes moving, to keep the general effect)
+ * offset them by the same amount so that the general angles are maintained
+ * (i.e. won't change while handles are free-to-roam and keyframes are snap-locked).
+ */
+ if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
+ td2d->h1[0] = td2d->ih1[0] + *td->val - td->ival;
+ }
+ if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
+ td2d->h2[0] = td2d->ih2[0] + *td->val - td->ival;
+ }
+}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform Mode Initialization
+ * \{ */
+
+void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
+{
+ t->mode = mode;
+
+ switch (mode) {
+ case TFM_TRANSLATION:
+ initTranslation(t);
+ break;
+ case TFM_ROTATION:
+ initRotation(t);
+ break;
+ case TFM_RESIZE:
+ initResize(t);
+ break;
+ case TFM_SKIN_RESIZE:
+ initSkinResize(t);
+ break;
+ case TFM_TOSPHERE:
+ initToSphere(t);
+ break;
+ case TFM_SHEAR:
+ initShear(t);
+ break;
+ case TFM_BEND:
+ initBend(t);
+ break;
+ case TFM_SHRINKFATTEN:
+ initShrinkFatten(t);
+ break;
+ case TFM_TILT:
+ initTilt(t);
+ break;
+ case TFM_CURVE_SHRINKFATTEN:
+ initCurveShrinkFatten(t);
+ break;
+ case TFM_MASK_SHRINKFATTEN:
+ initMaskShrinkFatten(t);
+ break;
+ case TFM_GPENCIL_SHRINKFATTEN:
+ initGPShrinkFatten(t);
+ break;
+ case TFM_TRACKBALL:
+ initTrackball(t);
+ break;
+ case TFM_PUSHPULL:
+ initPushPull(t);
+ break;
+ case TFM_CREASE:
+ initCrease(t);
+ break;
+ case TFM_BONESIZE: { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */
+ /* Note: we have to pick one, use the active object. */
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
+ bArmature *arm = tc->poseobj->data;
+ if (arm->drawtype == ARM_ENVELOPE) {
+ initBoneEnvelope(t);
+ t->mode = TFM_BONE_ENVELOPE_DIST;
+ }
+ else {
+ initBoneSize(t);
+ }
+ break;
+ }
+ case TFM_BONE_ENVELOPE:
+ initBoneEnvelope(t);
+ break;
+ case TFM_BONE_ENVELOPE_DIST:
+ initBoneEnvelope(t);
+ t->mode = TFM_BONE_ENVELOPE_DIST;
+ break;
+ case TFM_EDGE_SLIDE:
+ case TFM_VERT_SLIDE: {
+ const bool use_even = (op ? RNA_boolean_get(op->ptr, "use_even") : false);
+ const bool flipped = (op ? RNA_boolean_get(op->ptr, "flipped") : false);
+ const bool use_clamp = (op ? RNA_boolean_get(op->ptr, "use_clamp") : true);
+ if (mode == TFM_EDGE_SLIDE) {
+ const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true);
+ initEdgeSlide_ex(t, use_double_side, use_even, flipped, use_clamp);
+ }
+ else {
+ initVertSlide_ex(t, use_even, flipped, use_clamp);
+ }
+ break;
+ }
+ case TFM_BONE_ROLL:
+ initBoneRoll(t);
+ break;
+ case TFM_TIME_TRANSLATE:
+ initTimeTranslate(t);
+ break;
+ case TFM_TIME_SLIDE:
+ initTimeSlide(t);
+ break;
+ case TFM_TIME_SCALE:
+ initTimeScale(t);
+ break;
+ case TFM_TIME_DUPLICATE:
+ /* same as TFM_TIME_EXTEND, but we need the mode info for later
+ * so that duplicate-culling will work properly
+ */
+ if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
+ initTranslation(t);
+ }
+ else {
+ initTimeTranslate(t);
+ }
+ break;
+ case TFM_TIME_EXTEND:
+ /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation
+ * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION
+ * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement)
+ * depending on which editor this was called from
+ */
+ if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
+ initTranslation(t);
+ }
+ else {
+ initTimeTranslate(t);
+ }
+ break;
+ case TFM_BAKE_TIME:
+ initBakeTime(t);
+ break;
+ case TFM_MIRROR:
+ initMirror(t);
+ break;
+ case TFM_BWEIGHT:
+ initBevelWeight(t);
+ break;
+ case TFM_ALIGN:
+ initAlign(t);
+ break;
+ case TFM_SEQ_SLIDE:
+ initSeqSlide(t);
+ break;
+ case TFM_NORMAL_ROTATION:
+ initNormalRotation(t);
+ break;
+ case TFM_GPENCIL_OPACITY:
+ initGPOpacity(t);
+ break;
+ }
+
+ /* TODO(germano): Some of these operations change the `t->mode`.
+ * This can be bad for Redo.
+ * BLI_assert(t->mode == mode); */
+}
+
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h
new file mode 100644
index 00000000000..6180f6d3477
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode.h
@@ -0,0 +1,160 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ * \brief transform modes used by different operators.
+ */
+
+#ifndef __TRANSFORM_MODE_H__
+#define __TRANSFORM_MODE_H__
+
+struct AnimData;
+struct LinkNode;
+struct TransData;
+struct TransDataContainer;
+struct TransInfo;
+struct wmOperator;
+
+/* header of TransDataEdgeSlideVert, TransDataEdgeSlideEdge */
+typedef struct TransDataGenericSlideVert {
+ struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
+ float co_orig_3d[3];
+} TransDataGenericSlideVert;
+
+/* transform_mode.c */
+bool transdata_check_local_center(TransInfo *t, short around);
+void protectedTransBits(short protectflag, float vec[3]);
+void constraintTransLim(TransInfo *t, TransData *td);
+void postInputRotation(TransInfo *t, float values[3]);
+void headerRotation(TransInfo *t, char *str, float final);
+void ElementRotation_ex(TransInfo *t,
+ TransDataContainer *tc,
+ TransData *td,
+ const float mat[3][3],
+ const float *center);
+void ElementRotation(
+ TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around);
+void headerResize(TransInfo *t, const float vec[3], char *str);
+void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3]);
+short getAnimEdit_SnapMode(TransInfo *t);
+void doAnimEdit_SnapFrame(
+ TransInfo *t, TransData *td, TransData2D *td2d, struct AnimData *adt, short autosnap);
+void transform_mode_init(TransInfo *t, struct wmOperator *op, const int mode);
+
+/* transform_mode_align.c */
+void initAlign(TransInfo *t);
+
+/* transform_mode_baketime.c */
+void initBakeTime(TransInfo *t);
+
+/* transform_mode_bbone_resize.c */
+void initBoneSize(TransInfo *t);
+
+/* transform_mode_bend.c */
+void initBend(TransInfo *t);
+
+/* transform_mode_boneenvelope.c */
+void initBoneEnvelope(TransInfo *t);
+
+/* transform_mode_boneroll.c */
+void initBoneRoll(TransInfo *t);
+
+/* transform_mode_curveshrinkfatten.c */
+void initCurveShrinkFatten(TransInfo *t);
+
+/* transform_mode_edge_bevelweight.c */
+void initBevelWeight(TransInfo *t);
+
+/* transform_mode_edge_crease.c */
+void initCrease(TransInfo *t);
+
+/* transform_mode_edge_rotate_normal.c */
+void initNormalRotation(TransInfo *t);
+
+/* transform_mode_edge_seq_slide.c */
+void initSeqSlide(TransInfo *t);
+
+/* transform_mode_edge_slide.c */
+void projectEdgeSlideData(TransInfo *t, bool is_final);
+void drawEdgeSlide(TransInfo *t);
+void doEdgeSlide(TransInfo *t, float perc);
+void initEdgeSlide_ex(
+ TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp);
+void initEdgeSlide(TransInfo *t);
+
+/* transform_mode_gpopacity.c */
+void initGPOpacity(TransInfo *t);
+
+/* transform_mode_gpshrinkfatten.c */
+void initGPShrinkFatten(TransInfo *t);
+
+/* transform_mode_maskshrinkfatten.c */
+void initMaskShrinkFatten(TransInfo *t);
+
+/* transform_mode_mirror.c */
+void initMirror(TransInfo *t);
+
+/* transform_mode_push_pull.c */
+void initPushPull(TransInfo *t);
+
+/* transform_mode_resize.c */
+void initResize(TransInfo *t);
+
+/* transform_mode_rotate.c */
+void initRotation(TransInfo *t);
+
+/* transform_mode_shear.c */
+void initShear(TransInfo *t);
+
+/* transform_mode_shrink_fatten.c */
+void initShrinkFatten(TransInfo *t);
+
+/* transform_mode_skin_resize.c */
+void initSkinResize(TransInfo *t);
+
+/* transform_mode_tilt.c */
+void initTilt(TransInfo *t);
+
+/* transform_mode_timescale.c */
+void initTimeScale(TransInfo *t);
+
+/* transform_mode_timeslide.c */
+void initTimeSlide(TransInfo *t);
+
+/* transform_mode_timetranslate.c */
+void initTimeTranslate(TransInfo *t);
+
+/* transform_mode_tosphere.c */
+void initToSphere(TransInfo *t);
+
+/* transform_mode_trackball.c */
+void initTrackball(TransInfo *t);
+
+/* transform_mode_translate.c */
+void initTranslation(TransInfo *t);
+
+/* transform_mode_vert_slide.c */
+void projectVertSlideData(TransInfo *t, bool is_final);
+void drawVertSlide(TransInfo *t);
+void doVertSlide(TransInfo *t, float perc);
+void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp);
+void initVertSlide(TransInfo *t);
+#endif
diff --git a/source/blender/editors/transform/transform_mode_align.c b/source/blender/editors/transform/transform_mode_align.c
new file mode 100644
index 00000000000..9bce793809b
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_align.c
@@ -0,0 +1,96 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "ED_screen.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Align) */
+
+/** \name Transform Align
+ * \{ */
+
+static void applyAlign(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float center[3];
+ int i;
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ /* saving original center */
+ copy_v3_v3(center, tc->center_local);
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float mat[3][3], invmat[3][3];
+
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ /* around local centers */
+ if (t->flag & (T_OBJECT | T_POSE)) {
+ copy_v3_v3(tc->center_local, td->center);
+ }
+ else {
+ if (t->settings->selectmode & SCE_SELECT_FACE) {
+ copy_v3_v3(tc->center_local, td->center);
+ }
+ }
+
+ invert_m3_m3(invmat, td->axismtx);
+
+ mul_m3_m3m3(mat, t->spacemtx, invmat);
+
+ ElementRotation(t, tc, td, mat, t->around);
+ }
+ /* restoring original center */
+ copy_v3_v3(tc->center_local, center);
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, TIP_("Align"));
+}
+
+void initAlign(TransInfo *t)
+{
+ t->flag |= T_NO_CONSTRAINT;
+
+ t->transform = applyAlign;
+
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_baketime.c b/source/blender/editors/transform/transform_mode_baketime.c
new file mode 100644
index 00000000000..bb8fd0df13d
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_baketime.c
@@ -0,0 +1,140 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Bake-Time) */
+
+/** \name Transform Bake-Time
+ * \{ */
+
+static void applyBakeTime(TransInfo *t, const int mval[2])
+{
+ float time;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ float fac = 0.1f;
+
+ /* XXX, disable precision for now,
+ * this isn't even accessible by the user */
+#if 0
+ if (t->mouse.precision) {
+ /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
+ time = (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac;
+ time += 0.1f * ((float)(t->center2d[0] * fac - mval[0]) - time);
+ }
+ else
+#endif
+ {
+ time = (float)(t->center2d[0] - mval[0]) * fac;
+ }
+
+ snapGridIncrement(t, &time);
+
+ applyNumInput(&t->num, &time);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ if (time >= 0.0f) {
+ BLI_snprintf(str, sizeof(str), TIP_("Time: +%s %s"), c, t->proptext);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Time: %s %s"), c, t->proptext);
+ }
+ }
+ else {
+ /* default header print */
+ if (time >= 0.0f) {
+ BLI_snprintf(str, sizeof(str), TIP_("Time: +%.3f %s"), time, t->proptext);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Time: %.3f %s"), time, t->proptext);
+ }
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (td->val) {
+ *td->val = td->ival + time * td->factor;
+ if (td->ext->size && *td->val < *td->ext->size) {
+ *td->val = *td->ext->size;
+ }
+ if (td->ext->quat && *td->val > *td->ext->quat) {
+ *td->val = *td->ext->quat;
+ }
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initBakeTime(TransInfo *t)
+{
+ t->transform = applyBakeTime;
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE; /* Don't think this uses units? */
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_bbone_resize.c b/source/blender/editors/transform/transform_mode_bbone_resize.c
new file mode 100644
index 00000000000..c81049ac379
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_bbone_resize.c
@@ -0,0 +1,184 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_constraints.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (EditBone (B-bone) width scaling) */
+
+/** \name Transform B-bone width scaling
+ * \{ */
+
+static void headerBoneSize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR])
+{
+ char tvec[NUM_STR_REP_LEN * 3];
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
+ }
+
+ /* hmm... perhaps the y-axis values don't need to be shown? */
+ if (t->con.mode & CON_APPLY) {
+ if (t->num.idx_max == 0) {
+ BLI_snprintf(
+ str, UI_MAX_DRAW_STR, TIP_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext);
+ }
+ else {
+ BLI_snprintf(str,
+ UI_MAX_DRAW_STR,
+ TIP_("ScaleB: %s : %s : %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ t->con.text,
+ t->proptext);
+ }
+ }
+ else {
+ BLI_snprintf(str,
+ UI_MAX_DRAW_STR,
+ TIP_("ScaleB X: %s Y: %s Z: %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ t->con.text,
+ t->proptext);
+ }
+}
+
+static void ElementBoneSize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3])
+{
+ float tmat[3][3], smat[3][3], oldy;
+ float sizemat[3][3];
+
+ mul_m3_m3m3(smat, mat, td->mtx);
+ mul_m3_m3m3(tmat, td->smtx, smat);
+
+ if (t->con.applySize) {
+ t->con.applySize(t, tc, td, tmat);
+ }
+
+ /* we've tucked the scale in loc */
+ oldy = td->iloc[1];
+ size_to_mat3(sizemat, td->iloc);
+ mul_m3_m3m3(tmat, tmat, sizemat);
+ mat3_to_size(td->loc, tmat);
+ td->loc[1] = oldy;
+}
+
+static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ if (t->flag & T_INPUT_IS_VALUES_FINAL) {
+ copy_v3_v3(t->values_final, t->values);
+ }
+ else {
+ float ratio = t->values[0];
+
+ copy_v3_fl(t->values_final, ratio);
+
+ snapGridIncrement(t, t->values_final);
+
+ if (applyNumInput(&t->num, t->values_final)) {
+ constraintNumInput(t, t->values_final);
+ }
+ }
+
+ size_to_mat3(mat, t->values_final);
+
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, NULL, mat);
+ }
+
+ copy_m3_m3(t->mat, mat); // used in gizmo
+
+ headerBoneSize(t, t->values_final, str);
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ ElementBoneSize(t, tc, td, mat);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initBoneSize(TransInfo *t)
+{
+ t->mode = TFM_BONESIZE;
+ t->transform = applyBoneSize;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+
+ t->idx_max = 2;
+ t->num.idx_max = 2;
+ t->num.val_flag[0] |= NUM_NULL_ONE;
+ t->num.val_flag[1] |= NUM_NULL_ONE;
+ t->num.val_flag[2] |= NUM_NULL_ONE;
+ t->num.flag |= NUM_AFFECT_ALL;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
+ t->num.unit_type[2] = B_UNIT_NONE;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_bend.c b/source/blender/editors/transform/transform_mode_bend.c
new file mode 100644
index 00000000000..721d226050a
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_bend.c
@@ -0,0 +1,308 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_gpencil_types.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Bend) */
+
+/** \name Transform Bend
+ * \{ */
+
+struct BendCustomData {
+ /* All values are in global space. */
+ float warp_sta[3];
+ float warp_end[3];
+
+ float warp_nor[3];
+ float warp_tan[3];
+
+ /* for applying the mouse distance */
+ float warp_init_dist;
+};
+
+static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event)
+{
+ eRedrawFlag status = TREDRAW_NOTHING;
+
+ if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
+ status = TREDRAW_HARD;
+ }
+
+ return status;
+}
+
+static void Bend(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float vec[3];
+ float pivot_global[3];
+ float warp_end_radius_global[3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
+ const struct BendCustomData *data = t->custom.mode.data;
+ const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0;
+
+ union {
+ struct {
+ float angle, scale;
+ };
+ float vector[2];
+ } values;
+
+ /* amount of radians for bend */
+ copy_v2_v2(values.vector, t->values);
+
+#if 0
+ snapGrid(t, angle_rad);
+#else
+ /* hrmf, snapping radius is using 'angle' steps, need to convert to something else
+ * this isnt essential but nicer to give reasonable snapping values for radius */
+ if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) {
+ const float radius_snap = 0.1f;
+ const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap;
+ values.scale *= snap_hack;
+ snapGridIncrement(t, values.vector);
+ values.scale /= snap_hack;
+ }
+#endif
+
+ if (applyNumInput(&t->num, values.vector)) {
+ values.scale = values.scale / data->warp_init_dist;
+ }
+
+ copy_v2_v2(t->values_final, values.vector);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN * 2];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ BLI_snprintf(str,
+ sizeof(str),
+ TIP_("Bend Angle: %s Radius: %s Alt, Clamp %s"),
+ &c[0],
+ &c[NUM_STR_REP_LEN],
+ WM_bool_as_string(is_clamp));
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(str,
+ sizeof(str),
+ TIP_("Bend Angle: %.3f Radius: %.4f, Alt, Clamp %s"),
+ RAD2DEGF(values.angle),
+ values.scale * data->warp_init_dist,
+ WM_bool_as_string(is_clamp));
+ }
+
+ values.angle *= -1.0f;
+ values.scale *= data->warp_init_dist;
+
+ /* calc 'data->warp_end' from 'data->warp_end_init' */
+ copy_v3_v3(warp_end_radius_global, data->warp_end);
+ dist_ensure_v3_v3fl(warp_end_radius_global, data->warp_sta, values.scale);
+ /* done */
+
+ /* calculate pivot */
+ copy_v3_v3(pivot_global, data->warp_sta);
+ if (values.angle > 0.0f) {
+ madd_v3_v3fl(pivot_global,
+ data->warp_tan,
+ -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle));
+ }
+ else {
+ madd_v3_v3fl(pivot_global,
+ data->warp_tan,
+ +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle));
+ }
+
+ /* TODO(campbell): xform, compensate object center. */
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+
+ float warp_sta_local[3];
+ float warp_end_local[3];
+ float warp_end_radius_local[3];
+ float pivot_local[3];
+
+ if (tc->use_local_mat) {
+ sub_v3_v3v3(warp_sta_local, data->warp_sta, tc->mat[3]);
+ sub_v3_v3v3(warp_end_local, data->warp_end, tc->mat[3]);
+ sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]);
+ sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]);
+ }
+ else {
+ copy_v3_v3(warp_sta_local, data->warp_sta);
+ copy_v3_v3(warp_end_local, data->warp_end);
+ copy_v3_v3(warp_end_radius_local, warp_end_radius_global);
+ copy_v3_v3(pivot_local, pivot_global);
+ }
+
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float mat[3][3];
+ float delta[3];
+ float fac, fac_scaled;
+
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (UNLIKELY(values.angle == 0.0f)) {
+ copy_v3_v3(td->loc, td->iloc);
+ continue;
+ }
+
+ copy_v3_v3(vec, td->iloc);
+ mul_m3_v3(td->mtx, vec);
+
+ fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local);
+ if (is_clamp) {
+ CLAMP(fac, 0.0f, 1.0f);
+ }
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* grease pencil multiframe falloff */
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ if (gps != NULL) {
+ fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff;
+ }
+ else {
+ fac_scaled = fac * td->factor;
+ }
+ }
+ else {
+ fac_scaled = fac * td->factor;
+ }
+
+ axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled);
+ interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled);
+ sub_v3_v3(delta, warp_sta_local);
+
+ /* delta is subtracted, rotation adds back this offset */
+ sub_v3_v3(vec, delta);
+
+ sub_v3_v3(vec, pivot_local);
+ mul_m3_v3(mat, vec);
+ add_v3_v3(vec, pivot_local);
+
+ mul_m3_v3(td->smtx, vec);
+
+ /* rotation */
+ if ((t->flag & T_POINTS) == 0) {
+ ElementRotation(t, tc, td, mat, V3D_AROUND_LOCAL_ORIGINS);
+ }
+
+ /* location */
+ copy_v3_v3(td->loc, vec);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initBend(TransInfo *t)
+{
+ const float mval_fl[2] = {UNPACK2(t->mval)};
+ const float *curs;
+ float tvec[3];
+ struct BendCustomData *data;
+
+ t->mode = TFM_BEND;
+ t->transform = Bend;
+ t->handleEvent = handleEventBend;
+
+ setInputPostFct(&t->mouse, postInputRotation);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING);
+
+ t->idx_max = 1;
+ t->num.idx_max = 1;
+ t->snap[0] = 0.0f;
+ t->snap[1] = SNAP_INCREMENTAL_ANGLE;
+ t->snap[2] = t->snap[1] * 0.2;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
+ t->num.unit_type[1] = B_UNIT_LENGTH;
+
+ t->flag |= T_NO_CONSTRAINT;
+
+ // copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
+ if ((t->flag & T_OVERRIDE_CENTER) == 0) {
+ calculateCenterCursor(t, t->center_global);
+ }
+ calculateCenterLocal(t, t->center_global);
+
+ t->val = 0.0f;
+
+ data = MEM_callocN(sizeof(*data), __func__);
+
+ curs = t->scene->cursor.location;
+ copy_v3_v3(data->warp_sta, curs);
+ ED_view3d_win_to_3d(
+ (View3D *)t->area->spacedata.first, t->region, curs, mval_fl, data->warp_end);
+
+ copy_v3_v3(data->warp_nor, t->viewinv[2]);
+ normalize_v3(data->warp_nor);
+
+ /* tangent */
+ sub_v3_v3v3(tvec, data->warp_end, data->warp_sta);
+ cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor);
+ normalize_v3(data->warp_tan);
+
+ data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
+
+ t->custom.mode.data = data;
+ t->custom.mode.use_free = true;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_boneenvelope.c b/source/blender/editors/transform/transform_mode_boneenvelope.c
new file mode 100644
index 00000000000..aa20a5ade95
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_boneenvelope.c
@@ -0,0 +1,121 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Bone Envelope) */
+
+/** \name Transform Bone Envelope
+ * \{ */
+
+static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ ratio = t->values[0];
+
+ snapGridIncrement(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ t->values_final[0] = ratio;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), TIP_("Envelope: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Envelope: %3f"), ratio);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (td->val) {
+ /* if the old/original value was 0.0f, then just use ratio */
+ if (td->ival) {
+ *td->val = td->ival * ratio;
+ }
+ else {
+ *td->val = ratio;
+ }
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initBoneEnvelope(TransInfo *t)
+{
+ t->mode = TFM_BONE_ENVELOPE;
+ t->transform = applyBoneEnvelope;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+}
+
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_boneroll.c b/source/blender/editors/transform/transform_mode_boneroll.c
new file mode 100644
index 00000000000..0564a946148
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_boneroll.c
@@ -0,0 +1,115 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (EditBone Roll) */
+
+/** \name Transform EditBone Roll
+ * \{ */
+
+static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
+{
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ float final;
+
+ final = t->values[0];
+
+ snapGridIncrement(t, &final);
+
+ applyNumInput(&t->num, &final);
+
+ t->values_final[0] = final;
+
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ BLI_snprintf(str, sizeof(str), TIP_("Roll: %s"), &c[0]);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Roll: %.2f"), RAD2DEGF(final));
+ }
+
+ /* set roll values */
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ *(td->val) = td->ival - final;
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initBoneRoll(TransInfo *t)
+{
+ t->mode = TFM_BONE_ROLL;
+ t->transform = applyBoneRoll;
+
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
+
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
new file mode 100644
index 00000000000..057f13ac068
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
@@ -0,0 +1,124 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Curve Shrink/Fatten) */
+
+/** \name Transform Curve Shrink/Fatten
+ * \{ */
+
+static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ ratio = t->values[0];
+
+ snapGridIncrement(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ t->values_final[0] = ratio;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), TIP_("Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Shrink/Fatten: %3f"), ratio);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (td->val) {
+ *td->val = td->ival * ratio;
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ if (*td->val <= 0.0f) {
+ *td->val = 0.001f;
+ }
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initCurveShrinkFatten(TransInfo *t)
+{
+ t->mode = TFM_CURVE_SHRINKFATTEN;
+ t->transform = applyCurveShrinkFatten;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
+ t->num.val_flag[0] |= NUM_NO_ZERO;
+#endif
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c
new file mode 100644
index 00000000000..5db7895232c
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c
@@ -0,0 +1,130 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Bevel Weight) */
+
+/** \name Transform Bevel Weight
+ * \{ */
+
+static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float weight;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ weight = t->values[0];
+
+ CLAMP_MAX(weight, 1.0f);
+
+ snapGridIncrement(t, &weight);
+
+ applyNumInput(&t->num, &weight);
+
+ t->values_final[0] = weight;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ if (weight >= 0.0f) {
+ BLI_snprintf(str, sizeof(str), TIP_("Bevel Weight: +%s %s"), c, t->proptext);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Bevel Weight: %s %s"), c, t->proptext);
+ }
+ }
+ else {
+ /* default header print */
+ if (weight >= 0.0f) {
+ BLI_snprintf(str, sizeof(str), TIP_("Bevel Weight: +%.3f %s"), weight, t->proptext);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Bevel Weight: %.3f %s"), weight, t->proptext);
+ }
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->val) {
+ *td->val = td->ival + weight * td->factor;
+ if (*td->val < 0.0f) {
+ *td->val = 0.0f;
+ }
+ if (*td->val > 1.0f) {
+ *td->val = 1.0f;
+ }
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initBevelWeight(TransInfo *t)
+{
+ t->mode = TFM_BWEIGHT;
+ t->transform = applyBevelWeight;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c
new file mode 100644
index 00000000000..4a92a57fef6
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_edge_crease.c
@@ -0,0 +1,134 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Crease) */
+
+/** \name Transform Crease
+ * \{ */
+
+static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float crease;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ crease = t->values[0];
+
+ CLAMP_MAX(crease, 1.0f);
+
+ snapGridIncrement(t, &crease);
+
+ applyNumInput(&t->num, &crease);
+
+ t->values_final[0] = crease;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ if (crease >= 0.0f) {
+ BLI_snprintf(str, sizeof(str), TIP_("Crease: +%s %s"), c, t->proptext);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Crease: %s %s"), c, t->proptext);
+ }
+ }
+ else {
+ /* default header print */
+ if (crease >= 0.0f) {
+ BLI_snprintf(str, sizeof(str), TIP_("Crease: +%.3f %s"), crease, t->proptext);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Crease: %.3f %s"), crease, t->proptext);
+ }
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (td->val) {
+ *td->val = td->ival + crease * td->factor;
+ if (*td->val < 0.0f) {
+ *td->val = 0.0f;
+ }
+ if (*td->val > 1.0f) {
+ *td->val = 1.0f;
+ }
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initCrease(TransInfo *t)
+{
+ t->mode = TFM_CREASE;
+ t->transform = applyCrease;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c
new file mode 100644
index 00000000000..fde0d5b187e
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c
@@ -0,0 +1,156 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_editmesh.h"
+#include "BKE_mesh.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Normal Rotation) */
+
+/** \name Transform Normal Rotation
+ * \{ */
+
+static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm)
+{
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
+ // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ tc->custom.mode.data = lnors_ed_arr;
+ tc->custom.mode.free_cb = freeCustomNormalArray;
+}
+
+void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
+{
+ BMLoopNorEditDataArray *lnors_ed_arr = custom_data->data;
+
+ if (t->state == TRANS_CANCEL) {
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+
+ /* Restore custom loop normal on cancel */
+ 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], lnor_ed->niloc, lnor_ed->clnors_data);
+ }
+ }
+
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+
+ tc->custom.mode.data = NULL;
+ tc->custom.mode.free_cb = NULL;
+}
+
+/* Works by getting custom normal from clnor_data, transform, then store */
+static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2]))
+{
+ char str[UI_MAX_DRAW_STR];
+
+ float axis_final[3];
+ copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]);
+
+ if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
+ t->con.applyRot(t, NULL, NULL, axis_final, NULL);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+
+ BMLoopNorEditDataArray *lnors_ed_arr = tc->custom.mode.data;
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ float axis[3];
+ float mat[3][3];
+ float angle = t->values[0];
+ copy_v3_v3(axis, axis_final);
+
+ snapGridIncrement(t, &angle);
+
+ applySnapping(t, &angle);
+
+ applyNumInput(&t->num, &angle);
+
+ headerRotation(t, str, angle);
+
+ axis_angle_normalized_to_mat3(mat, axis, angle);
+
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ mul_v3_m3v3(lnor_ed->nloc, mat, 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);
+ }
+
+ t->values_final[0] = angle;
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initNormalRotation(TransInfo *t)
+{
+ t->mode = TFM_NORMAL_ROTATION;
+ t->transform = applyNormalRotation;
+
+ setInputPostFct(&t->mouse, postInputRotation);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
+
+ copy_v3_fl(t->num.val_inc, t->snap[2]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+
+ BKE_editmesh_ensure_autosmooth(em, tc->obedit->data);
+ BKE_editmesh_lnorspace_update(em, tc->obedit->data);
+
+ storeCustomLNorValue(tc, bm);
+ }
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
new file mode 100644
index 00000000000..ee91459dcdd
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
@@ -0,0 +1,147 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Sequencer Slide) */
+
+/** \name Transform Sequencer Slide
+ * \{ */
+
+static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRAW_STR])
+{
+ char tvec[NUM_STR_REP_LEN * 3];
+ size_t ofs = 0;
+
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]);
+ }
+
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text);
+
+ if (t->keymap) {
+ wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE);
+ if (kmi) {
+ ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs);
+ }
+ }
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ TIP_(" or Alt) Expand to fit %s"),
+ WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
+}
+
+static void applySeqSlideValue(TransInfo *t, const float val[2])
+{
+ int i;
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor);
+ }
+ }
+}
+
+static void applySeqSlide(TransInfo *t, const int mval[2])
+{
+ char str[UI_MAX_DRAW_STR];
+
+ snapSequenceBounds(t, mval);
+
+ if (t->con.mode & CON_APPLY) {
+ float pvec[3] = {0.0f, 0.0f, 0.0f};
+ float tvec[3];
+ t->con.applyVec(t, NULL, NULL, t->values, tvec, pvec);
+ copy_v3_v3(t->values_final, tvec);
+ }
+ else {
+ // snapGridIncrement(t, t->values);
+ applyNumInput(&t->num, t->values);
+ copy_v3_v3(t->values_final, t->values);
+ }
+
+ t->values_final[0] = floorf(t->values_final[0] + 0.5f);
+ t->values_final[1] = floorf(t->values_final[1] + 0.5f);
+
+ headerSeqSlide(t, t->values_final, str);
+ applySeqSlideValue(t, t->values_final);
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initSeqSlide(TransInfo *t)
+{
+ t->transform = applySeqSlide;
+
+ initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
+
+ t->idx_max = 1;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ t->snap[0] = 0.0f;
+ t->snap[1] = floorf(t->scene->r.frs_sec / t->scene->r.frs_sec_base);
+ t->snap[2] = 10.0f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ /* Would be nice to have a time handling in units as well
+ * (supporting frames in addition to "natural" time...). */
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c
new file mode 100644
index 00000000000..5613a782529
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_edge_slide.c
@@ -0,0 +1,1498 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_utildefines_stack.h"
+
+#include "BKE_context.h"
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_bvh.h"
+#include "BKE_unit.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_convert.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Edge Slide) */
+
+/** \name Transform Edge Slide
+ * \{ */
+
+typedef struct TransDataEdgeSlideVert {
+ /** #TransDataGenericSlideVert (header) */
+ struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
+ float v_co_orig[3];
+ /* end generic */
+
+ float edge_len;
+
+ struct BMVert *v_side[2];
+
+ /* add origvert.co to get the original locations */
+ float dir_side[2][3];
+
+ int loop_nr;
+} TransDataEdgeSlideVert;
+
+typedef struct EdgeSlideData {
+ TransDataEdgeSlideVert *sv;
+ int totsv;
+
+ int mval_start[2], mval_end[2];
+ int curr_sv_index;
+
+ /** when un-clamped - use this index: #TransDataEdgeSlideVert.dir_side */
+ int curr_side_unclamp;
+} EdgeSlideData;
+
+typedef struct EdgeSlideParams {
+ float perc;
+
+ bool use_even;
+ bool flipped;
+} EdgeSlideParams;
+
+/**
+ * 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 = edgeSlideFirstGet(t);
+
+ setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
+
+ /* setCustomPoints isn't normally changing as the mouse moves,
+ * in this case apply mouse input immediately so we don't refresh
+ * with the value from the previous points */
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+}
+
+static BMEdge *get_other_edge(BMVert *v, BMEdge *e)
+{
+ BMIter iter;
+ BMEdge *e_iter;
+
+ BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT) && e_iter != e) {
+ return e_iter;
+ }
+ }
+
+ return NULL;
+}
+
+/* interpoaltes along a line made up of 2 segments (used for edge slide) */
+static void interp_line_v3_v3v3v3(
+ float p[3], const float v1[3], const float v2[3], const float v3[3], float t)
+{
+ float t_mid, t_delta;
+
+ /* could be pre-calculated */
+ t_mid = line_point_factor_v3(v2, v1, v3);
+
+ t_delta = t - t_mid;
+ if (t_delta < 0.0f) {
+ if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) {
+ copy_v3_v3(p, v2);
+ }
+ else {
+ interp_v3_v3v3(p, v1, v2, t / t_mid);
+ }
+ }
+ else {
+ t = t - t_mid;
+ t_mid = 1.0f - t_mid;
+
+ if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) {
+ copy_v3_v3(p, v3);
+ }
+ else {
+ interp_v3_v3v3(p, v2, v3, t / t_mid);
+ }
+ }
+}
+
+/**
+ * Find the closest point on the ngon on the opposite side.
+ * used to set the edge slide distance for ngons.
+ */
+static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, const float plane_no[3], float r_co[3])
+{
+ /* skip adjacent edges */
+ BMLoop *l_first = l_tmp->next;
+ BMLoop *l_last = l_tmp->prev;
+ BMLoop *l_iter;
+ float dist = FLT_MAX;
+ bool found = false;
+
+ l_iter = l_first;
+ do {
+ float tvec[3];
+ if (isect_line_plane_v3(tvec, l_iter->v->co, l_iter->next->v->co, l_tmp->v->co, plane_no)) {
+ const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co);
+ /* allow some overlap to avoid missing the intersection because of float precision */
+ if ((fac > -FLT_EPSILON) && (fac < 1.0f + FLT_EPSILON)) {
+ /* likelihood of multiple intersections per ngon is quite low,
+ * it would have to loop back on its self, but better support it
+ * so check for the closest opposite edge */
+ const float tdist = len_v3v3(l_tmp->v->co, tvec);
+ if (tdist < dist) {
+ copy_v3_v3(r_co, tvec);
+ dist = tdist;
+ found = true;
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_last);
+
+ return found;
+}
+
+/**
+ * Given 2 edges and a loop, step over the loops
+ * and calculate a direction to slide along.
+ *
+ * \param r_slide_vec: the direction to slide,
+ * the length of the vector defines the slide distance.
+ */
+static BMLoop *get_next_loop(
+ BMVert *v, BMLoop *l, BMEdge *e_prev, BMEdge *e_next, float r_slide_vec[3])
+{
+ BMLoop *l_first;
+ float vec_accum[3] = {0.0f, 0.0f, 0.0f};
+ float vec_accum_len = 0.0f;
+ int i = 0;
+
+ BLI_assert(BM_edge_share_vert(e_prev, e_next) == v);
+ BLI_assert(BM_vert_in_edge(l->e, v));
+
+ l_first = l;
+ do {
+ l = BM_loop_other_edge_loop(l, v);
+
+ if (l->e == e_next) {
+ if (i) {
+ normalize_v3_length(vec_accum, vec_accum_len / (float)i);
+ }
+ else {
+ /* When there is no edge to slide along,
+ * we must slide along the vector defined by the face we're attach to */
+ BMLoop *l_tmp = BM_face_vert_share_loop(l_first->f, v);
+
+ BLI_assert(ELEM(l_tmp->e, e_prev, e_next) && ELEM(l_tmp->prev->e, e_prev, e_next));
+
+ if (l_tmp->f->len == 4) {
+ /* we could use code below, but in this case
+ * sliding diagonally across the quad works well */
+ sub_v3_v3v3(vec_accum, l_tmp->next->next->v->co, v->co);
+ }
+ else {
+ float tdir[3];
+ BM_loop_calc_face_direction(l_tmp, tdir);
+ cross_v3_v3v3(vec_accum, l_tmp->f->no, tdir);
+#if 0
+ /* rough guess, we can do better! */
+ normalize_v3_length(vec_accum,
+ (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f);
+#else
+ /* be clever, check the opposite ngon edge to slide into.
+ * this gives best results */
+ {
+ float tvec[3];
+ float dist;
+
+ if (bm_loop_calc_opposite_co(l_tmp, tdir, tvec)) {
+ dist = len_v3v3(l_tmp->v->co, tvec);
+ }
+ else {
+ dist = (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f;
+ }
+
+ normalize_v3_length(vec_accum, dist);
+ }
+#endif
+ }
+ }
+
+ copy_v3_v3(r_slide_vec, vec_accum);
+ return l;
+ }
+ else {
+ /* accumulate the normalized edge vector,
+ * normalize so some edges don't skew the result */
+ float tvec[3];
+ sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co);
+ vec_accum_len += normalize_v3(tvec);
+ add_v3_v3(vec_accum, tvec);
+ i += 1;
+ }
+
+ if (BM_loop_other_edge_loop(l, v)->e == e_next) {
+ if (i) {
+ normalize_v3_length(vec_accum, vec_accum_len / (float)i);
+ }
+
+ copy_v3_v3(r_slide_vec, vec_accum);
+ return BM_loop_other_edge_loop(l, v);
+ }
+
+ } while ((l != l->radial_next) && ((l = l->radial_next) != l_first));
+
+ if (i) {
+ normalize_v3_length(vec_accum, vec_accum_len / (float)i);
+ }
+
+ copy_v3_v3(r_slide_vec, vec_accum);
+
+ return NULL;
+}
+
+/**
+ * Calculate screenspace `mval_start` / `mval_end`, optionally slide direction.
+ */
+static void calcEdgeSlide_mval_range(TransInfo *t,
+ TransDataContainer *tc,
+ EdgeSlideData *sld,
+ const int *sv_table,
+ const int loop_nr,
+ const float mval[2],
+ const bool use_occlude_geometry,
+ const bool use_calc_direction)
+{
+ TransDataEdgeSlideVert *sv;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ ARegion *region = t->region;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
+ float projectMat[4][4];
+ BMBVHTree *bmbvh;
+
+ /* only for use_calc_direction */
+ float(*loop_dir)[3] = NULL, *loop_maxdist = NULL;
+
+ float mval_start[2], mval_end[2];
+ float mval_dir[3], dist_best_sq;
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* background mode support */
+ v3d = t->area ? t->area->spacedata.first : NULL;
+ rv3d = t->region ? t->region->regiondata : NULL;
+ }
+
+ if (!rv3d) {
+ /* ok, let's try to survive this */
+ unit_m4(projectMat);
+ }
+ else {
+ ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat);
+ }
+
+ if (use_occlude_geometry) {
+ bmbvh = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false);
+ }
+ else {
+ bmbvh = NULL;
+ }
+
+ /* find mouse vectors, the global one, and one per loop in case we have
+ * multiple loops selected, in case they are oriented different */
+ zero_v3(mval_dir);
+ dist_best_sq = -1.0f;
+
+ if (use_calc_direction) {
+ loop_dir = MEM_callocN(sizeof(float[3]) * loop_nr, "sv loop_dir");
+ loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist");
+ copy_vn_fl(loop_maxdist, loop_nr, -1.0f);
+ }
+
+ sv = &sld->sv[0];
+ for (int i = 0; i < sld->totsv; i++, sv++) {
+ BMIter iter_other;
+ BMEdge *e;
+ BMVert *v = sv->v;
+
+ UNUSED_VARS_NDEBUG(sv_table); /* silence warning */
+ BLI_assert(i == sv_table[BM_elem_index_get(v)]);
+
+ /* search cross edges for visible edge to the mouse cursor,
+ * then use the shared vertex to calculate screen vector*/
+ BM_ITER_ELEM (e, &iter_other, v, BM_EDGES_OF_VERT) {
+ /* screen-space coords */
+ float sco_a[3], sco_b[3];
+ float dist_sq;
+ int l_nr;
+
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ continue;
+ }
+
+ /* This test is only relevant if object is not wire-drawn! See [#32068]. */
+ bool is_visible = !use_occlude_geometry ||
+ BMBVH_EdgeVisible(bmbvh, e, t->depsgraph, region, v3d, tc->obedit);
+
+ if (!is_visible && !use_calc_direction) {
+ continue;
+ }
+
+ if (sv->v_side[1]) {
+ ED_view3d_project_float_v3_m4(region, sv->v_side[1]->co, sco_b, projectMat);
+ }
+ else {
+ add_v3_v3v3(sco_b, v->co, sv->dir_side[1]);
+ ED_view3d_project_float_v3_m4(region, sco_b, sco_b, projectMat);
+ }
+
+ if (sv->v_side[0]) {
+ ED_view3d_project_float_v3_m4(region, sv->v_side[0]->co, sco_a, projectMat);
+ }
+ else {
+ add_v3_v3v3(sco_a, v->co, sv->dir_side[0]);
+ ED_view3d_project_float_v3_m4(region, sco_a, sco_a, projectMat);
+ }
+
+ /* global direction */
+ dist_sq = dist_squared_to_line_segment_v2(mval, sco_b, sco_a);
+ if (is_visible) {
+ if ((dist_best_sq == -1.0f) ||
+ /* intentionally use 2d size on 3d vector */
+ (dist_sq < dist_best_sq && (len_squared_v2v2(sco_b, sco_a) > 0.1f))) {
+ dist_best_sq = dist_sq;
+ sub_v3_v3v3(mval_dir, sco_b, sco_a);
+ }
+ }
+
+ if (use_calc_direction) {
+ /* per loop direction */
+ l_nr = sv->loop_nr;
+ if (loop_maxdist[l_nr] == -1.0f || dist_sq < loop_maxdist[l_nr]) {
+ loop_maxdist[l_nr] = dist_sq;
+ sub_v3_v3v3(loop_dir[l_nr], sco_b, sco_a);
+ }
+ }
+ }
+ }
+
+ if (use_calc_direction) {
+ int i;
+ sv = &sld->sv[0];
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ /* switch a/b if loop direction is different from global direction */
+ int l_nr = sv->loop_nr;
+ if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) {
+ swap_v3_v3(sv->dir_side[0], sv->dir_side[1]);
+ SWAP(BMVert *, sv->v_side[0], sv->v_side[1]);
+ }
+ }
+
+ MEM_freeN(loop_dir);
+ MEM_freeN(loop_maxdist);
+ }
+
+ /* possible all of the edge loops are pointing directly at the view */
+ if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) {
+ mval_dir[0] = 0.0f;
+ mval_dir[1] = 100.0f;
+ }
+
+ /* zero out start */
+ zero_v2(mval_start);
+
+ /* dir holds a vector along edge loop */
+ copy_v2_v2(mval_end, mval_dir);
+ mul_v2_fl(mval_end, 0.5f);
+
+ sld->mval_start[0] = t->mval[0] + mval_start[0];
+ sld->mval_start[1] = t->mval[1] + mval_start[1];
+
+ sld->mval_end[0] = t->mval[0] + mval_end[0];
+ sld->mval_end[1] = t->mval[1] + mval_end[1];
+
+ if (bmbvh) {
+ BKE_bmbvh_free(bmbvh);
+ }
+}
+
+static void calcEdgeSlide_even(TransInfo *t,
+ TransDataContainer *tc,
+ EdgeSlideData *sld,
+ const float mval[2])
+{
+ TransDataEdgeSlideVert *sv = sld->sv;
+
+ if (sld->totsv > 0) {
+ ARegion *region = t->region;
+ RegionView3D *rv3d = NULL;
+ float projectMat[4][4];
+
+ int i = 0;
+
+ float v_proj[2];
+ float dist_sq = 0;
+ float dist_min_sq = FLT_MAX;
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* background mode support */
+ rv3d = t->region ? t->region->regiondata : NULL;
+ }
+
+ if (!rv3d) {
+ /* ok, let's try to survive this */
+ unit_m4(projectMat);
+ }
+ else {
+ ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat);
+ }
+
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ /* Set length */
+ sv->edge_len = len_v3v3(sv->dir_side[0], sv->dir_side[1]);
+
+ ED_view3d_project_float_v2_m4(region, sv->v->co, v_proj, projectMat);
+ dist_sq = len_squared_v2v2(mval, v_proj);
+ if (dist_sq < dist_min_sq) {
+ dist_min_sq = dist_sq;
+ sld->curr_sv_index = i;
+ }
+ }
+ }
+ else {
+ sld->curr_sv_index = 0;
+ }
+}
+
+static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *tc)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMEdge *e;
+ BMVert *v;
+ TransDataEdgeSlideVert *sv_array;
+ int sv_tot;
+ int *sv_table; /* BMVert -> sv_array index */
+ EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
+ float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
+ int numsel, i, loop_nr;
+ bool use_occlude_geometry = false;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
+
+ sld->curr_sv_index = 0;
+
+ /*ensure valid selection*/
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BMIter iter2;
+ numsel = 0;
+ BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ /* BMESH_TODO: this is probably very evil,
+ * set v->e to a selected edge*/
+ v->e = e;
+
+ numsel++;
+ }
+ }
+
+ if (numsel == 0 || numsel > 2) {
+ MEM_freeN(sld);
+ return false; /* invalid edge selection */
+ }
+ }
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ /* note, any edge with loops can work, but we won't get predictable results, so bail out */
+ if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) {
+ /* can edges with at least once face user */
+ MEM_freeN(sld);
+ return false;
+ }
+ }
+ }
+
+ sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__);
+
+#define INDEX_UNSET -1
+#define INDEX_INVALID -2
+
+ {
+ int j = 0;
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ sv_table[i] = INDEX_UNSET;
+ j += 1;
+ }
+ else {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ sv_table[i] = INDEX_INVALID;
+ }
+ BM_elem_index_set(v, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ if (!j) {
+ MEM_freeN(sld);
+ MEM_freeN(sv_table);
+ return false;
+ }
+ sv_tot = j;
+ }
+
+ sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * sv_tot, "sv_array");
+ loop_nr = 0;
+
+ STACK_DECLARE(sv_array);
+ STACK_INIT(sv_array, sv_tot);
+
+ while (1) {
+ float vec_a[3], vec_b[3];
+ BMLoop *l_a, *l_b;
+ BMLoop *l_a_prev, *l_b_prev;
+ BMVert *v_first;
+ /* If this succeeds call get_next_loop()
+ * which calculates the direction to slide based on clever checks.
+ *
+ * otherwise we simply use 'e_dir' as an edge-rail.
+ * (which is better when the attached edge is a boundary, see: T40422)
+ */
+#define EDGESLIDE_VERT_IS_INNER(v, e_dir) \
+ ((BM_edge_is_boundary(e_dir) == false) && (BM_vert_edge_count_nonwire(v) == 2))
+
+ v = NULL;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ break;
+ }
+ }
+
+ if (!v) {
+ break;
+ }
+
+ if (!v->e) {
+ continue;
+ }
+
+ v_first = v;
+
+ /*walk along the edge loop*/
+ e = v->e;
+
+ /*first, rewind*/
+ do {
+ e = get_other_edge(v, e);
+ if (!e) {
+ e = v->e;
+ break;
+ }
+
+ if (!BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG)) {
+ break;
+ }
+
+ v = BM_edge_other_vert(e, v);
+ } while (e != v_first->e);
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ l_a = e->l;
+ l_b = e->l->radial_next;
+
+ /* regarding e_next, use get_next_loop()'s improved interpolation where possible */
+ {
+ BMEdge *e_next = get_other_edge(v, e);
+ if (e_next) {
+ get_next_loop(v, l_a, e, e_next, vec_a);
+ }
+ else {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v);
+ if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
+ get_next_loop(v, l_a, e, l_tmp->e, vec_a);
+ }
+ else {
+ sub_v3_v3v3(vec_a, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
+ }
+ }
+ }
+
+ /* !BM_edge_is_boundary(e); */
+ if (l_b != l_a) {
+ BMEdge *e_next = get_other_edge(v, e);
+ if (e_next) {
+ get_next_loop(v, l_b, e, e_next, vec_b);
+ }
+ else {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v);
+ if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
+ get_next_loop(v, l_b, e, l_tmp->e, vec_b);
+ }
+ else {
+ sub_v3_v3v3(vec_b, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
+ }
+ }
+ }
+ else {
+ l_b = NULL;
+ }
+
+ l_a_prev = NULL;
+ l_b_prev = NULL;
+
+#define SV_FROM_VERT(v) \
+ ((sv_table[BM_elem_index_get(v)] == INDEX_UNSET) ? \
+ ((void)(sv_table[BM_elem_index_get(v)] = STACK_SIZE(sv_array)), \
+ STACK_PUSH_RET_PTR(sv_array)) : \
+ (&sv_array[sv_table[BM_elem_index_get(v)]]))
+
+ /*iterate over the loop*/
+ v_first = v;
+ do {
+ bool l_a_ok_prev;
+ bool l_b_ok_prev;
+ TransDataEdgeSlideVert *sv;
+ BMVert *v_prev;
+ BMEdge *e_prev;
+
+ /* XXX, 'sv' will initialize multiple times, this is suspicious. see [#34024] */
+ BLI_assert(v != NULL);
+ BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID);
+ sv = SV_FROM_VERT(v);
+ sv->v = v;
+ copy_v3_v3(sv->v_co_orig, v->co);
+ sv->loop_nr = loop_nr;
+
+ if (l_a || l_a_prev) {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_a ? l_a : l_a_prev, v);
+ sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v);
+ copy_v3_v3(sv->dir_side[0], vec_a);
+ }
+
+ if (l_b || l_b_prev) {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_b ? l_b : l_b_prev, v);
+ sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v);
+ copy_v3_v3(sv->dir_side[1], vec_b);
+ }
+
+ v_prev = v;
+ v = BM_edge_other_vert(e, v);
+
+ e_prev = e;
+ e = get_other_edge(v, e);
+
+ if (!e) {
+ BLI_assert(v != NULL);
+
+ BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID);
+ sv = SV_FROM_VERT(v);
+
+ sv->v = v;
+ copy_v3_v3(sv->v_co_orig, v->co);
+ sv->loop_nr = loop_nr;
+
+ if (l_a) {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v);
+ sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v);
+ if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
+ get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_side[0]);
+ }
+ else {
+ sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co);
+ }
+ }
+
+ if (l_b) {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v);
+ sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v);
+ if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
+ get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_side[1]);
+ }
+ else {
+ sub_v3_v3v3(sv->dir_side[1], sv->v_side[1]->co, v->co);
+ }
+ }
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ BM_elem_flag_disable(v_prev, BM_ELEM_TAG);
+
+ break;
+ }
+ l_a_ok_prev = (l_a != NULL);
+ l_b_ok_prev = (l_b != NULL);
+
+ l_a_prev = l_a;
+ l_b_prev = l_b;
+
+ if (l_a) {
+ l_a = get_next_loop(v, l_a, e_prev, e, vec_a);
+ }
+ else {
+ zero_v3(vec_a);
+ }
+
+ if (l_b) {
+ l_b = get_next_loop(v, l_b, e_prev, e, vec_b);
+ }
+ else {
+ zero_v3(vec_b);
+ }
+
+ if (l_a && l_b) {
+ /* pass */
+ }
+ else {
+ if (l_a || l_b) {
+ /* find the opposite loop if it was missing previously */
+ if (l_a == NULL && l_b && (l_b->radial_next != l_b)) {
+ l_a = l_b->radial_next;
+ }
+ else if (l_b == NULL && l_a && (l_a->radial_next != l_a)) {
+ l_b = l_a->radial_next;
+ }
+ }
+ else if (e->l != NULL) {
+ /* if there are non-contiguous faces, we can still recover
+ * the loops of the new edges faces */
+
+ /* note!, the behavior in this case means edges may move in opposite directions,
+ * this could be made to work more usefully. */
+
+ if (l_a_ok_prev) {
+ l_a = e->l;
+ l_b = (l_a->radial_next != l_a) ? l_a->radial_next : NULL;
+ }
+ else if (l_b_ok_prev) {
+ l_b = e->l;
+ l_a = (l_b->radial_next != l_b) ? l_b->radial_next : NULL;
+ }
+ }
+
+ if (!l_a_ok_prev && l_a) {
+ get_next_loop(v, l_a, e, e_prev, vec_a);
+ }
+ if (!l_b_ok_prev && l_b) {
+ get_next_loop(v, l_b, e, e_prev, vec_b);
+ }
+ }
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ BM_elem_flag_disable(v_prev, BM_ELEM_TAG);
+ } while ((e != v_first->e) && (l_a || l_b));
+
+#undef SV_FROM_VERT
+#undef INDEX_UNSET
+#undef INDEX_INVALID
+
+ loop_nr++;
+
+#undef EDGESLIDE_VERT_IS_INNER
+ }
+
+ /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
+
+ BLI_assert(STACK_SIZE(sv_array) == sv_tot);
+
+ sld->sv = sv_array;
+ sld->totsv = sv_tot;
+
+ /* use for visibility checks */
+ if (t->spacetype == SPACE_VIEW3D) {
+ v3d = t->area ? t->area->spacedata.first : NULL;
+ rv3d = t->region ? t->region->regiondata : NULL;
+ use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE &&
+ !XRAY_ENABLED(v3d));
+ }
+
+ calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true);
+
+ if (rv3d) {
+ calcEdgeSlide_even(t, tc, sld, mval);
+ }
+
+ tc->custom.mode.data = sld;
+
+ MEM_freeN(sv_table);
+
+ return true;
+}
+
+/**
+ * A simple version of #createEdgeSlideVerts_double_side
+ * Which assumes the longest unselected.
+ */
+static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *tc)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMEdge *e;
+ TransDataEdgeSlideVert *sv_array;
+ int sv_tot;
+ int *sv_table; /* BMVert -> sv_array index */
+ EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
+ float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
+ int loop_nr;
+ bool use_occlude_geometry = false;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* background mode support */
+ v3d = t->area ? t->area->spacedata.first : NULL;
+ rv3d = t->region ? t->region->regiondata : NULL;
+ }
+
+ sld->curr_sv_index = 0;
+ /* ensure valid selection */
+ {
+ int i = 0, j = 0;
+ BMVert *v;
+
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ float len_sq_max = -1.0f;
+ BMIter iter2;
+ BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ float len_sq = BM_edge_calc_length_squared(e);
+ if (len_sq > len_sq_max) {
+ len_sq_max = len_sq;
+ v->e = e;
+ }
+ }
+ }
+
+ if (len_sq_max != -1.0f) {
+ j++;
+ }
+ }
+ BM_elem_index_set(v, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ if (!j) {
+ MEM_freeN(sld);
+ return false;
+ }
+
+ sv_tot = j;
+ }
+
+ BLI_assert(sv_tot != 0);
+ /* over alloc */
+ sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * bm->totvertsel, "sv_array");
+
+ /* same loop for all loops, weak but we dont connect loops in this case */
+ loop_nr = 1;
+
+ sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__);
+
+ {
+ int i = 0, j = 0;
+ BMVert *v;
+
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ sv_table[i] = -1;
+ if ((v->e != NULL) && (BM_elem_flag_test(v, BM_ELEM_SELECT))) {
+ if (BM_elem_flag_test(v->e, BM_ELEM_SELECT) == 0) {
+ TransDataEdgeSlideVert *sv;
+ sv = &sv_array[j];
+ sv->v = v;
+ copy_v3_v3(sv->v_co_orig, v->co);
+ sv->v_side[0] = BM_edge_other_vert(v->e, v);
+ sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co);
+ sv->loop_nr = 0;
+ sv_table[i] = j;
+ j += 1;
+ }
+ }
+ }
+ }
+
+ /* check for wire vertices,
+ * interpolate the directions of wire verts between non-wire verts */
+ if (sv_tot != bm->totvert) {
+ const int sv_tot_nowire = sv_tot;
+ TransDataEdgeSlideVert *sv_iter = sv_array;
+
+ for (int i = 0; i < sv_tot_nowire; i++, sv_iter++) {
+ BMIter eiter;
+ BM_ITER_ELEM (e, &eiter, sv_iter->v, BM_EDGES_OF_VERT) {
+ /* walk over wire */
+ TransDataEdgeSlideVert *sv_end = NULL;
+ BMEdge *e_step = e;
+ BMVert *v = sv_iter->v;
+ int j;
+
+ j = sv_tot;
+
+ while (1) {
+ BMVert *v_other = BM_edge_other_vert(e_step, v);
+ int endpoint = ((sv_table[BM_elem_index_get(v_other)] != -1) +
+ (BM_vert_is_edge_pair(v_other) == false));
+
+ if ((BM_elem_flag_test(e_step, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(v_other, BM_ELEM_SELECT)) &&
+ (endpoint == 0)) {
+ /* scan down the list */
+ TransDataEdgeSlideVert *sv;
+ BLI_assert(sv_table[BM_elem_index_get(v_other)] == -1);
+ sv_table[BM_elem_index_get(v_other)] = j;
+ sv = &sv_array[j];
+ sv->v = v_other;
+ copy_v3_v3(sv->v_co_orig, v_other->co);
+ copy_v3_v3(sv->dir_side[0], sv_iter->dir_side[0]);
+ j++;
+
+ /* advance! */
+ v = v_other;
+ e_step = BM_DISK_EDGE_NEXT(e_step, v_other);
+ }
+ else {
+ if ((endpoint == 2) && (sv_tot != j)) {
+ BLI_assert(BM_elem_index_get(v_other) != -1);
+ sv_end = &sv_array[sv_table[BM_elem_index_get(v_other)]];
+ }
+ break;
+ }
+ }
+
+ if (sv_end) {
+ int sv_tot_prev = sv_tot;
+ const float *co_src = sv_iter->v->co;
+ const float *co_dst = sv_end->v->co;
+ const float *dir_src = sv_iter->dir_side[0];
+ const float *dir_dst = sv_end->dir_side[0];
+ sv_tot = j;
+
+ while (j-- != sv_tot_prev) {
+ float factor;
+ factor = line_point_factor_v3(sv_array[j].v->co, co_src, co_dst);
+ interp_v3_v3v3(sv_array[j].dir_side[0], dir_src, dir_dst, factor);
+ }
+ }
+ }
+ }
+ }
+
+ /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
+
+ sld->sv = sv_array;
+ sld->totsv = sv_tot;
+
+ /* use for visibility checks */
+ if (t->spacetype == SPACE_VIEW3D) {
+ v3d = t->area ? t->area->spacedata.first : NULL;
+ rv3d = t->region ? t->region->regiondata : NULL;
+ use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE &&
+ !XRAY_ENABLED(v3d));
+ }
+
+ calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, false);
+
+ if (rv3d) {
+ calcEdgeSlide_even(t, tc, sld, mval);
+ }
+
+ tc->custom.mode.data = sld;
+
+ MEM_freeN(sv_table);
+
+ return true;
+}
+
+void projectEdgeSlideData(TransInfo *t, bool is_final)
+{
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ EdgeSlideData *sld = tc->custom.mode.data;
+
+ if (sld == NULL) {
+ continue;
+ }
+
+ trans_mesh_customdata_correction_apply(tc, is_final);
+ }
+}
+
+static void freeEdgeSlideVerts(TransInfo *UNUSED(t),
+ TransDataContainer *UNUSED(tc),
+ TransCustomData *custom_data)
+{
+ EdgeSlideData *sld = custom_data->data;
+
+ if (sld == NULL) {
+ return;
+ }
+
+ MEM_freeN(sld->sv);
+ MEM_freeN(sld);
+
+ custom_data->data = NULL;
+}
+
+static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event)
+{
+ if (t->mode == TFM_EDGE_SLIDE) {
+ EdgeSlideParams *slp = t->custom.mode.data;
+
+ if (slp) {
+ switch (event->type) {
+ case EVT_EKEY:
+ if (event->val == KM_PRESS) {
+ slp->use_even = !slp->use_even;
+ calcEdgeSlideCustomPoints(t);
+ return TREDRAW_HARD;
+ }
+ break;
+ case EVT_FKEY:
+ if (event->val == KM_PRESS) {
+ slp->flipped = !slp->flipped;
+ calcEdgeSlideCustomPoints(t);
+ return TREDRAW_HARD;
+ }
+ break;
+ case EVT_CKEY:
+ /* use like a modifier key */
+ if (event->val == KM_PRESS) {
+ t->flag ^= T_ALT_TRANSFORM;
+ calcEdgeSlideCustomPoints(t);
+ return TREDRAW_HARD;
+ }
+ break;
+ case EVT_MODAL_MAP:
+#if 0
+ switch (event->val) {
+ case TFM_MODAL_EDGESLIDE_DOWN:
+ sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
+ return TREDRAW_HARD;
+ case TFM_MODAL_EDGESLIDE_UP:
+ sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
+ return TREDRAW_HARD;
+ }
+#endif
+ break;
+ case MOUSEMOVE:
+ calcEdgeSlideCustomPoints(t);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return TREDRAW_NOTHING;
+}
+
+void drawEdgeSlide(TransInfo *t)
+{
+ if ((t->mode == TFM_EDGE_SLIDE) && edgeSlideFirstGet(t)) {
+ const EdgeSlideParams *slp = t->custom.mode.data;
+ EdgeSlideData *sld = edgeSlideFirstGet(t);
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+
+ /* Even mode */
+ if ((slp->use_even == true) || (is_clamp == false)) {
+ const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
+
+ GPU_depth_test(false);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ GPU_matrix_push();
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (slp->use_even == true) {
+ float co_a[3], co_b[3], co_mark[3];
+ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ const float fac = (slp->perc + 1.0f) / 2.0f;
+ const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
+ const float guide_size = ctrl_size - 0.5f;
+ const int alpha_shade = -30;
+
+ add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]);
+ add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]);
+
+ GPU_line_width(line_size);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBeginAtMost(GPU_PRIM_LINES, 4);
+ if (curr_sv->v_side[0]) {
+ immVertex3fv(pos, curr_sv->v_side[0]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
+ }
+ if (curr_sv->v_side[1]) {
+ immVertex3fv(pos, curr_sv->v_side[1]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
+ }
+ immEnd();
+
+ {
+ float *co_test = NULL;
+ if (slp->flipped) {
+ if (curr_sv->v_side[1]) {
+ co_test = curr_sv->v_side[1]->co;
+ }
+ }
+ else {
+ if (curr_sv->v_side[0]) {
+ co_test = curr_sv->v_side[0]->co;
+ }
+ }
+
+ if (co_test != NULL) {
+ immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
+ GPU_point_size(ctrl_size);
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, co_test);
+ immEnd();
+ }
+ }
+
+ immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
+ GPU_point_size(guide_size);
+ immBegin(GPU_PRIM_POINTS, 1);
+ interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
+ immVertex3fv(pos, co_mark);
+ immEnd();
+ }
+ else {
+ if (is_clamp == false) {
+ const int side_index = sld->curr_side_unclamp;
+ TransDataEdgeSlideVert *sv;
+ int i;
+ const int alpha_shade = -160;
+
+ GPU_line_width(line_size);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBegin(GPU_PRIM_LINES, sld->totsv * 2);
+
+ /* TODO(campbell): Loop over all verts */
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float a[3], b[3];
+
+ if (!is_zero_v3(sv->dir_side[side_index])) {
+ copy_v3_v3(a, sv->dir_side[side_index]);
+ }
+ else {
+ copy_v3_v3(a, sv->dir_side[!side_index]);
+ }
+
+ mul_v3_fl(a, 100.0f);
+ negate_v3_v3(b, a);
+ add_v3_v3(a, sv->v_co_orig);
+ add_v3_v3(b, sv->v_co_orig);
+
+ immVertex3fv(pos, a);
+ immVertex3fv(pos, b);
+ }
+ immEnd();
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ immUnbindProgram();
+
+ GPU_matrix_pop();
+
+ GPU_blend(false);
+
+ GPU_depth_test(true);
+ }
+ }
+}
+
+void doEdgeSlide(TransInfo *t, float perc)
+{
+ EdgeSlideParams *slp = t->custom.mode.data;
+ EdgeSlideData *sld_active = edgeSlideFirstGet(t);
+
+ slp->perc = perc;
+
+ if (slp->use_even == false) {
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ if (is_clamp) {
+ const int side_index = (perc < 0.0f);
+ 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);
+ }
+ sld->curr_side_unclamp = side_index;
+ }
+ }
+ else {
+ const float perc_init = fabsf(perc) *
+ ((sld_active->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1);
+ 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];
+ float perc_final = perc_init;
+ if (!is_zero_v3(sv->dir_side[side_index])) {
+ copy_v3_v3(dir_flip, sv->dir_side[side_index]);
+ }
+ else {
+ copy_v3_v3(dir_flip, sv->dir_side[!side_index]);
+ perc_final *= -1;
+ }
+ madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, dir_flip, perc_final);
+ }
+ }
+ }
+ }
+ else {
+ /**
+ * Implementation note, even mode ignores the starting positions and uses
+ * only the a/b verts, this could be changed/improved so the distance is
+ * still met but the verts are moved along their original path (which may not be straight),
+ * however how it works now is OK and matches 2.4x - Campbell
+ *
+ * \note `len_v3v3(curr_sv->dir_side[0], curr_sv->dir_side[1])`
+ * is the same as the distance between the original vert locations,
+ * same goes for the lines below.
+ */
+ TransDataEdgeSlideVert *curr_sv = &sld_active->sv[sld_active->curr_sv_index];
+ const float curr_length_perc = curr_sv->edge_len *
+ (((slp->flipped ? perc : -perc) + 1.0f) / 2.0f);
+
+ float co_a[3];
+ float co_b[3];
+
+ 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) {
+ const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len;
+
+ add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]);
+ add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]);
+
+ if (slp->flipped) {
+ interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac);
+ }
+ else {
+ interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
+{
+ char str[UI_MAX_DRAW_STR];
+ size_t ofs = 0;
+ float final;
+ EdgeSlideParams *slp = t->custom.mode.data;
+ bool flipped = slp->flipped;
+ bool use_even = slp->use_even;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num));
+
+ final = t->values[0];
+
+ snapGridIncrement(t, &final);
+
+ /* only do this so out of range values are not displayed */
+ if (is_constrained) {
+ CLAMP(final, -1.0f, 1.0f);
+ }
+
+ applyNumInput(&t->num, &final);
+
+ t->values_final[0] = final;
+
+ /* header string */
+ ofs += BLI_strncpy_rlen(str + ofs, TIP_("Edge Slide: "), sizeof(str) - ofs);
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final);
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, TIP_("(E)ven: %s, "), WM_bool_as_string(use_even));
+ if (use_even) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, TIP_("(F)lipped: %s, "), WM_bool_as_string(flipped));
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, TIP_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
+ /* done with header string */
+
+ /* do stuff here */
+ doEdgeSlide(t, final);
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initEdgeSlide_ex(
+ TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp)
+{
+ EdgeSlideData *sld;
+ bool ok = false;
+
+ t->mode = TFM_EDGE_SLIDE;
+ t->transform = applyEdgeSlide;
+ t->handleEvent = handleEventEdgeSlide;
+
+ {
+ EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
+ slp->use_even = use_even;
+ slp->flipped = flipped;
+ /* happens to be best for single-sided */
+ if (use_double_side == false) {
+ slp->flipped = !flipped;
+ }
+ slp->perc = 0.0f;
+
+ if (!use_clamp) {
+ t->flag |= T_ALT_TRANSFORM;
+ }
+
+ t->custom.mode.data = slp;
+ t->custom.mode.use_free = true;
+ }
+
+ if (use_double_side) {
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ ok |= createEdgeSlideVerts_double_side(t, tc);
+ }
+ }
+ else {
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ ok |= createEdgeSlideVerts_single_side(t, tc);
+ }
+ }
+
+ if (!ok) {
+ t->state = TRANS_CANCEL;
+ return;
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ sld = tc->custom.mode.data;
+ if (!sld) {
+ continue;
+ }
+ tc->custom.mode.free_cb = freeEdgeSlideVerts;
+ }
+
+ trans_mesh_customdata_correction_init(t);
+
+ /* set custom point first if you want value to be initialized by init */
+ calcEdgeSlideCustomPoints(t);
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+}
+
+void initEdgeSlide(TransInfo *t)
+{
+ initEdgeSlide_ex(t, true, false, false, true);
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_gpopacity.c b/source/blender/editors/transform/transform_mode_gpopacity.c
new file mode 100644
index 00000000000..267d297a31c
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_gpopacity.c
@@ -0,0 +1,120 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (GPencil Opacity) */
+
+/** \name Transform GPencil Strokes Opacity
+ * \{ */
+
+static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ ratio = t->values[0];
+
+ snapGridIncrement(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ t->values_final[0] = ratio;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), TIP_("Opacity: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Opacity: %3f"), ratio);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (td->val) {
+ *td->val = td->ival * ratio;
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ CLAMP(*td->val, 0.0f, 1.0f);
+ }
+ }
+ }
+
+ ED_area_status_text(t->area, str);
+}
+
+void initGPOpacity(TransInfo *t)
+{
+ t->mode = TFM_GPENCIL_OPACITY;
+ t->transform = applyGPOpacity;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
+ t->num.val_flag[0] |= NUM_NO_ZERO;
+#endif
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
new file mode 100644
index 00000000000..7c49d107703
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
@@ -0,0 +1,122 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (GPencil Shrink/Fatten) */
+
+/** \name Transform GPencil Strokes Shrink/Fatten
+ * \{ */
+
+static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ ratio = t->values[0];
+
+ snapGridIncrement(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ t->values_final[0] = ratio;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), TIP_("Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Shrink/Fatten: %3f"), ratio);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (td->val) {
+ *td->val = td->ival * ratio;
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ if (*td->val <= 0.0f) {
+ *td->val = 0.001f;
+ }
+ }
+ }
+ }
+
+ ED_area_status_text(t->area, str);
+}
+
+void initGPShrinkFatten(TransInfo *t)
+{
+ t->mode = TFM_GPENCIL_SHRINKFATTEN;
+ t->transform = applyGPShrinkFatten;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
+ t->num.val_flag[0] |= NUM_NO_ZERO;
+#endif
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
new file mode 100644
index 00000000000..e42439920db
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
@@ -0,0 +1,154 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Mask Shrink/Fatten) */
+
+/** \name Transform Mask Shrink/Fatten
+ * \{ */
+
+static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float ratio;
+ int i;
+ bool initial_feather = false;
+ char str[UI_MAX_DRAW_STR];
+
+ ratio = t->values[0];
+
+ snapGridIncrement(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ t->values_final[0] = ratio;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), TIP_("Feather Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Feather Shrink/Fatten: %3f"), ratio);
+ }
+
+ /* detect if no points have feather yet */
+ if (ratio > 1.0f) {
+ initial_feather = true;
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (td->ival >= 0.001f) {
+ initial_feather = false;
+ }
+ }
+ }
+ }
+
+ /* apply shrink/fatten */
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (td = tc->data, i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (td->val) {
+ if (initial_feather) {
+ *td->val = td->ival + (ratio - 1.0f) * 0.01f;
+ }
+ else {
+ *td->val = td->ival * ratio;
+ }
+
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ if (*td->val <= 0.0f) {
+ *td->val = 0.001f;
+ }
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initMaskShrinkFatten(TransInfo *t)
+{
+ t->mode = TFM_MASK_SHRINKFATTEN;
+ t->transform = applyMaskShrinkFatten;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
+ t->num.val_flag[0] |= NUM_NO_ZERO;
+#endif
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c
new file mode 100644
index 00000000000..dae17374481
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_mirror.c
@@ -0,0 +1,129 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Mirror) */
+
+/** \name Transform Mirror
+ * \{ */
+
+static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float size[3], mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
+ copy_v3_v3(t->values_final, t->values);
+
+ /* OPTIMIZATION:
+ * This still recalculates transformation on mouse move
+ * while it should only recalculate on constraint change. */
+
+ /* if an axis has been selected */
+ if (t->con.mode & CON_APPLY) {
+ size[0] = size[1] = size[2] = -1;
+
+ size_to_mat3(mat, size);
+
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, NULL, mat);
+ }
+
+ BLI_snprintf(str, sizeof(str), TIP_("Mirror%s"), t->con.text);
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ ElementResize(t, tc, td, mat);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+ }
+ else {
+ size[0] = size[1] = size[2] = 1;
+
+ size_to_mat3(mat, size);
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ ElementResize(t, tc, td, mat);
+ }
+ }
+
+ recalcData(t);
+
+ if (t->flag & T_2D_EDIT) {
+ ED_area_status_text(t->area, TIP_("Select a mirror axis (X, Y)"));
+ }
+ else {
+ ED_area_status_text(t->area, TIP_("Select a mirror axis (X, Y, Z)"));
+ }
+ }
+}
+
+void initMirror(TransInfo *t)
+{
+ t->transform = applyMirror;
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ t->flag |= T_NULL_ONE;
+ if ((t->flag & T_EDIT) == 0) {
+ t->flag |= T_NO_ZERO;
+ }
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_push_pull.c b/source/blender/editors/transform/transform_mode_push_pull.c
new file mode 100644
index 00000000000..6eb038ea9b0
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_push_pull.c
@@ -0,0 +1,137 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_constraints.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Push/Pull) */
+
+/** \name Transform Push/Pull
+ * \{ */
+
+static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float vec[3], axis_global[3];
+ float distance;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ distance = t->values[0];
+
+ snapGridIncrement(t, &distance);
+
+ applyNumInput(&t->num, &distance);
+
+ t->values_final[0] = distance;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ BLI_snprintf(str, sizeof(str), TIP_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext);
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(
+ str, sizeof(str), TIP_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext);
+ }
+
+ if (t->con.applyRot && t->con.mode & CON_APPLY) {
+ t->con.applyRot(t, NULL, NULL, axis_global, NULL);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ sub_v3_v3v3(vec, tc->center_local, td->center);
+ if (t->con.applyRot && t->con.mode & CON_APPLY) {
+ float axis[3];
+ copy_v3_v3(axis, axis_global);
+ t->con.applyRot(t, tc, td, axis, NULL);
+
+ mul_m3_v3(td->smtx, axis);
+ if (isLockConstraint(t)) {
+ float dvec[3];
+ project_v3_v3v3(dvec, vec, axis);
+ sub_v3_v3(vec, dvec);
+ }
+ else {
+ project_v3_v3v3(vec, vec, axis);
+ }
+ }
+ normalize_v3_length(vec, distance * td->factor);
+
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initPushPull(TransInfo *t)
+{
+ t->mode = TFM_PUSHPULL;
+ t->transform = applyPushPull;
+
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_LENGTH;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c
new file mode 100644
index 00000000000..00644b9bfdc
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_resize.c
@@ -0,0 +1,170 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "transform.h"
+#include "transform_constraints.h"
+#include "transform_convert.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Resize) */
+
+/** \name Transform Resize
+ * \{ */
+
+static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ if (t->flag & T_INPUT_IS_VALUES_FINAL) {
+ copy_v3_v3(t->values_final, t->values);
+ }
+ else {
+ float ratio = t->values[0];
+
+ copy_v3_fl(t->values_final, ratio);
+
+ snapGridIncrement(t, t->values_final);
+
+ if (applyNumInput(&t->num, t->values_final)) {
+ constraintNumInput(t, t->values_final);
+ }
+
+ applySnapping(t, t->values_final);
+ }
+
+ size_to_mat3(mat, t->values_final);
+ if (t->con.mode & CON_APPLY) {
+ t->con.applySize(t, NULL, NULL, mat);
+
+ /* Only so we have re-usable value with redo. */
+ float pvec[3] = {0.0f, 0.0f, 0.0f};
+ int j = 0;
+ for (i = 0; i < 3; i++) {
+ if (!(t->con.mode & (CON_AXIS0 << i))) {
+ t->values_final[i] = 1.0f;
+ }
+ else {
+ pvec[j++] = t->values_final[i];
+ }
+ }
+ headerResize(t, pvec, str);
+ }
+ else {
+ headerResize(t, t->values_final, str);
+ }
+
+ copy_m3_m3(t->mat, mat); // used in gizmo
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ ElementResize(t, tc, td, mat);
+ }
+ }
+
+ /* evil hack - redo resize if cliping needed */
+ if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values_final, 1)) {
+ size_to_mat3(mat, t->values_final);
+
+ if (t->con.mode & CON_APPLY) {
+ t->con.applySize(t, NULL, NULL, mat);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ ElementResize(t, tc, td, mat);
+ }
+
+ /* In proportional edit it can happen that */
+ /* vertices in the radius of the brush end */
+ /* outside the clipping area */
+ /* XXX HACK - dg */
+ if (t->flag & T_PROP_EDIT_ALL) {
+ clipUVData(t);
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initResize(TransInfo *t)
+{
+ t->mode = TFM_RESIZE;
+ t->transform = applyResize;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+
+ t->flag |= T_NULL_ONE;
+ t->num.val_flag[0] |= NUM_NULL_ONE;
+ t->num.val_flag[1] |= NUM_NULL_ONE;
+ t->num.val_flag[2] |= NUM_NULL_ONE;
+ t->num.flag |= NUM_AFFECT_ALL;
+ if ((t->flag & T_EDIT) == 0) {
+ t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
+ t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[1] |= NUM_NO_ZERO;
+ t->num.val_flag[2] |= NUM_NO_ZERO;
+#endif
+ }
+
+ t->idx_max = 2;
+ t->num.idx_max = 2;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
+ t->num.unit_type[2] = B_UNIT_NONE;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c
new file mode 100644
index 00000000000..f52bfda0d14
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_rotate.c
@@ -0,0 +1,198 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Rotation) */
+
+/** \name Transform Rotation
+ * \{ */
+
+static float large_rotation_limit(float angle)
+{
+ /* Limit rotation to 1001 turns max
+ * (otherwise iterative handling of 'large' rotations would become too slow). */
+ const float angle_max = (float)(M_PI * 2000.0);
+ if (fabsf(angle) > angle_max) {
+ const float angle_sign = angle < 0.0f ? -1.0f : 1.0f;
+ angle = angle_sign * (fmodf(fabsf(angle), (float)(M_PI * 2.0)) + angle_max);
+ }
+ return angle;
+}
+
+static void applyRotationValue(TransInfo *t,
+ float angle,
+ float axis[3],
+ const bool is_large_rotation)
+{
+ float mat[3][3];
+ int i;
+
+ const float angle_sign = angle < 0.0f ? -1.0f : 1.0f;
+ /* We cannot use something too close to 180°, or 'continuous' rotation may fail
+ * due to computing error... */
+ const float angle_step = angle_sign * (float)(0.9 * M_PI);
+
+ if (is_large_rotation) {
+ /* Just in case, calling code should have already done that in practice
+ * (for UI feedback reasons). */
+ angle = large_rotation_limit(angle);
+ }
+
+ axis_angle_normalized_to_mat3(mat, axis, angle);
+ /* Counter for needed updates (when we need to update to non-default matrix,
+ * we also need another update on next iteration to go back to default matrix,
+ * hence the '2' value used here, instead of a mere boolean). */
+ short do_update_matrix = 0;
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ float angle_final = angle;
+ if (t->con.applyRot) {
+ t->con.applyRot(t, tc, td, axis, NULL);
+ angle_final = angle * td->factor;
+ /* Even though final angle might be identical to orig value,
+ * we have to update the rotation matrix in that case... */
+ do_update_matrix = 2;
+ }
+ else if (t->flag & T_PROP_EDIT) {
+ angle_final = angle * td->factor;
+ }
+
+ /* Rotation is very likely to be above 180°, we need to do rotation by steps.
+ * Note that this is only needed when doing 'absolute' rotation
+ * (i.e. from initial rotation again, typically when using numinput).
+ * regular incremental rotation (from mouse/widget/...) will be called often enough,
+ * hence steps are small enough to be properly handled without that complicated trick.
+ * Note that we can only do that kind of stepped rotation if we have initial rotation values
+ * (and access to some actual rotation value storage).
+ * Otherwise, just assume it's useless (e.g. in case of mesh/UV/etc. editing).
+ * Also need to be in Euler rotation mode, the others never allow more than one turn anyway.
+ */
+ if (is_large_rotation && td->ext != NULL && td->ext->rotOrder == ROT_MODE_EUL) {
+ copy_v3_v3(td->ext->rot, td->ext->irot);
+ for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final);
+ angle_progress += angle_step) {
+ axis_angle_normalized_to_mat3(mat, axis, angle_progress);
+ ElementRotation(t, tc, td, mat, t->around);
+ }
+ do_update_matrix = 2;
+ }
+ else if (angle_final != angle) {
+ do_update_matrix = 2;
+ }
+
+ if (do_update_matrix > 0) {
+ axis_angle_normalized_to_mat3(mat, axis, angle_final);
+ do_update_matrix--;
+ }
+
+ ElementRotation(t, tc, td, mat, t->around);
+ }
+ }
+}
+
+static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
+{
+ char str[UI_MAX_DRAW_STR];
+
+ float final;
+
+ final = t->values[0];
+
+ snapGridIncrement(t, &final);
+
+ float axis_final[3];
+ copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]);
+
+ if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
+ t->con.applyRot(t, NULL, NULL, axis_final, NULL);
+ }
+
+ applySnapping(t, &final);
+
+ if (applyNumInput(&t->num, &final)) {
+ /* We have to limit the amount of turns to a reasonable number here,
+ * to avoid things getting *very* slow, see how applyRotationValue() handles those... */
+ final = large_rotation_limit(final);
+ }
+
+ t->values_final[0] = final;
+
+ headerRotation(t, str, final);
+
+ const bool is_large_rotation = hasNumInput(&t->num);
+ applyRotationValue(t, final, axis_final, is_large_rotation);
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initRotation(TransInfo *t)
+{
+ t->mode = TFM_ROTATION;
+ t->transform = applyRotation;
+
+ setInputPostFct(&t->mouse, postInputRotation);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
+
+ copy_v3_fl(t->num.val_inc, t->snap[2]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
+
+ if (t->flag & T_2D_EDIT) {
+ t->flag |= T_NO_CONSTRAINT;
+ }
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c
new file mode 100644
index 00000000000..da34bf50ba3
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_shear.c
@@ -0,0 +1,248 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "DNA_gpencil_types.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "WM_types.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Shear) */
+
+/** \name Transform Shear
+ * \{ */
+
+static void initShear_mouseInputMode(TransInfo *t)
+{
+ float dir[3];
+ bool dir_flip = false;
+ copy_v3_v3(dir, t->spacemtx[t->orient_axis_ortho]);
+
+ /* Needed for axis aligned view gizmo. */
+ if (t->orientation.types[t->orientation.index] == V3D_ORIENT_VIEW) {
+ if (t->orient_axis_ortho == 0) {
+ if (t->center2d[1] < t->mouse.imval[1]) {
+ dir_flip = !dir_flip;
+ }
+ }
+ else if (t->orient_axis_ortho == 1) {
+ if (t->center2d[0] < t->mouse.imval[0]) {
+ dir_flip = !dir_flip;
+ }
+ }
+ }
+
+ /* Without this, half the gizmo handles move in the opposite direction. */
+ if ((t->orient_axis_ortho + 1) % 3 != t->orient_axis) {
+ dir_flip = !dir_flip;
+ }
+
+ if (dir_flip) {
+ negate_v3(dir);
+ }
+
+ mul_mat3_m4_v3(t->viewmat, dir);
+ if (normalize_v2(dir) == 0.0f) {
+ dir[0] = 1.0f;
+ }
+ setCustomPointsFromDirection(t, &t->mouse, dir);
+
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
+}
+
+static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event)
+{
+ eRedrawFlag status = TREDRAW_NOTHING;
+
+ if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
+ /* Use custom.mode.data pointer to signal Shear direction */
+ do {
+ t->orient_axis_ortho = (t->orient_axis_ortho + 1) % 3;
+ } while (t->orient_axis_ortho == t->orient_axis);
+
+ initShear_mouseInputMode(t);
+
+ status = TREDRAW_HARD;
+ }
+ else if (event->type == EVT_XKEY && event->val == KM_PRESS) {
+ t->orient_axis_ortho = (t->orient_axis + 1) % 3;
+ initShear_mouseInputMode(t);
+
+ status = TREDRAW_HARD;
+ }
+ else if (event->type == EVT_YKEY && event->val == KM_PRESS) {
+ t->orient_axis_ortho = (t->orient_axis + 2) % 3;
+ initShear_mouseInputMode(t);
+
+ status = TREDRAW_HARD;
+ }
+
+ return status;
+}
+
+static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float vec[3];
+ float smat[3][3], tmat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3];
+ float value;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+ const bool is_local_center = transdata_check_local_center(t, t->around);
+
+ value = t->values[0];
+
+ snapGridIncrement(t, &value);
+
+ applyNumInput(&t->num, &value);
+
+ t->values_final[0] = value;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ BLI_snprintf(str, sizeof(str), TIP_("Shear: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(str,
+ sizeof(str),
+ TIP_("Shear: %.3f %s (Press X or Y to set shear axis)"),
+ value,
+ t->proptext);
+ }
+
+ unit_m3(smat);
+ smat[1][0] = value;
+
+ copy_v3_v3(axismat_inv[0], t->spacemtx[t->orient_axis_ortho]);
+ copy_v3_v3(axismat_inv[2], t->spacemtx[t->orient_axis]);
+ cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]);
+ invert_m3_m3(axismat, axismat_inv);
+
+ mul_m3_series(totmat, axismat_inv, smat, axismat);
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ const float *center, *co;
+
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (t->flag & T_EDIT) {
+ mul_m3_series(tmat, td->smtx, totmat, td->mtx);
+ }
+ else {
+ copy_m3_m3(tmat, totmat);
+ }
+
+ if (is_local_center) {
+ center = td->center;
+ co = td->loc;
+ }
+ else {
+ center = tc->center_local;
+ co = td->center;
+ }
+
+ sub_v3_v3v3(vec, co, center);
+
+ mul_m3_v3(tmat, vec);
+
+ add_v3_v3(vec, center);
+ sub_v3_v3(vec, co);
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* grease pencil multiframe falloff */
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ if (gps != NULL) {
+ mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
+ }
+ else {
+ mul_v3_fl(vec, td->factor);
+ }
+ }
+ else {
+ mul_v3_fl(vec, td->factor);
+ }
+
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initShear(TransInfo *t)
+{
+ t->mode = TFM_SHEAR;
+ t->transform = applyShear;
+ t->handleEvent = handleEventShear;
+
+ if (t->orient_axis == t->orient_axis_ortho) {
+ t->orient_axis = 2;
+ t->orient_axis_ortho = 1;
+ }
+
+ initShear_mouseInputMode(t);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE; /* Don't think we have any unit here? */
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c
new file mode 100644
index 00000000000..ed082e86b6d
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c
@@ -0,0 +1,146 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Shrink-Fatten) */
+
+/** \name Transform Shrink-Fatten
+ * \{ */
+
+static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float distance;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+ size_t ofs = 0;
+
+ distance = -t->values[0];
+
+ snapGridIncrement(t, &distance);
+
+ applyNumInput(&t->num, &distance);
+
+ t->values_final[0] = -distance;
+
+ /* header print for NumInput */
+ ofs += BLI_strncpy_rlen(str + ofs, TIP_("Shrink/Fatten:"), sizeof(str) - ofs);
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", c);
+ }
+ else {
+ /* default header print */
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %.4f", distance);
+ }
+
+ if (t->proptext[0]) {
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", t->proptext);
+ }
+ ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs);
+
+ if (t->keymap) {
+ wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE);
+ if (kmi) {
+ ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs);
+ }
+ }
+ BLI_snprintf(str + ofs,
+ sizeof(str) - ofs,
+ TIP_(" or Alt) Even Thickness %s"),
+ WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
+ /* done with header string */
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float tdistance; /* temp dist */
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ /* get the final offset */
+ tdistance = distance * td->factor;
+ if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) {
+ tdistance *= td->ext->isize[0]; /* shell factor */
+ }
+
+ madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initShrinkFatten(TransInfo *t)
+{
+ // If not in mesh edit mode, fallback to Resize
+ if ((t->flag & T_EDIT) == 0 || (t->obedit_type != OB_MESH)) {
+ initResize(t);
+ }
+ else {
+ t->mode = TFM_SHRINKFATTEN;
+ t->transform = applyShrinkFatten;
+
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_LENGTH;
+
+ t->flag |= T_NO_CONSTRAINT;
+ }
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c
new file mode 100644
index 00000000000..b53dbb55c62
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_skin_resize.c
@@ -0,0 +1,141 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "transform.h"
+#include "transform_constraints.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Skin) */
+
+/** \name Transform Skin
+ * \{ */
+
+static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ if (t->flag & T_INPUT_IS_VALUES_FINAL) {
+ copy_v3_v3(t->values_final, t->values);
+ }
+ else {
+ copy_v3_fl(t->values_final, t->values[0]);
+
+ snapGridIncrement(t, t->values_final);
+
+ if (applyNumInput(&t->num, t->values_final)) {
+ constraintNumInput(t, t->values_final);
+ }
+
+ applySnapping(t, t->values_final);
+ }
+
+ size_to_mat3(mat, t->values_final);
+
+ headerResize(t, t->values_final, str);
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float tmat[3][3], smat[3][3];
+ float fsize[3];
+
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(smat, mat, td->mtx);
+ mul_m3_m3m3(tmat, td->smtx, smat);
+ }
+ else {
+ copy_m3_m3(tmat, mat);
+ }
+
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, NULL, tmat);
+ }
+
+ mat3_to_size(fsize, tmat);
+ td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor);
+ td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initSkinResize(TransInfo *t)
+{
+ t->mode = TFM_SKIN_RESIZE;
+ t->transform = applySkinResize;
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+
+ t->flag |= T_NULL_ONE;
+ t->num.val_flag[0] |= NUM_NULL_ONE;
+ t->num.val_flag[1] |= NUM_NULL_ONE;
+ t->num.val_flag[2] |= NUM_NULL_ONE;
+ t->num.flag |= NUM_AFFECT_ALL;
+ if ((t->flag & T_EDIT) == 0) {
+ t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
+ t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[1] |= NUM_NO_ZERO;
+ t->num.val_flag[2] |= NUM_NO_ZERO;
+#endif
+ }
+
+ t->idx_max = 2;
+ t->num.idx_max = 2;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
+ t->num.unit_type[2] = B_UNIT_NONE;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_tilt.c b/source/blender/editors/transform/transform_mode_tilt.c
new file mode 100644
index 00000000000..2f56f4bd162
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_tilt.c
@@ -0,0 +1,119 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Tilt) */
+
+/** \name Transform Tilt
+ * \{ */
+
+static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
+{
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ float final;
+
+ final = t->values[0];
+
+ snapGridIncrement(t, &final);
+
+ applyNumInput(&t->num, &final);
+
+ t->values_final[0] = final;
+
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ BLI_snprintf(str, sizeof(str), TIP_("Tilt: %s° %s"), &c[0], t->proptext);
+
+ /* XXX For some reason, this seems needed for this op, else RNA prop is not updated... :/ */
+ t->values_final[0] = final;
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), TIP_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (td->val) {
+ *td->val = td->ival + final * td->factor;
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initTilt(TransInfo *t)
+{
+ t->mode = TFM_TILT;
+ t->transform = applyTilt;
+
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
+
+ copy_v3_fl(t->num.val_inc, t->snap[2]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
+
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_timescale.c b/source/blender/editors/transform/transform_mode_timescale.c
new file mode 100644
index 00000000000..ce46cc36276
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_timescale.c
@@ -0,0 +1,158 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "DNA_anim_types.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_nla.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Animation Time Scale) */
+
+/** \name Transform Animation Time Scale
+ * \{ */
+
+static void headerTimeScale(TransInfo *t, char str[UI_MAX_DRAW_STR])
+{
+ char tvec[NUM_STR_REP_LEN * 3];
+
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values_final[0]);
+ }
+
+ BLI_snprintf(str, UI_MAX_DRAW_STR, TIP_("ScaleX: %s"), &tvec[0]);
+}
+
+static void applyTimeScaleValue(TransInfo *t, float value)
+{
+ Scene *scene = t->scene;
+ const short autosnap = getAnimEdit_SnapMode(t);
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ TransData2D *td2d = tc->data_2d;
+ for (int i = 0; i < tc->data_len; i++, td++, td2d++) {
+ /* it is assumed that td->extra is a pointer to the AnimData,
+ * whose active action is where this keyframe comes from
+ * (this is only valid when not in NLA)
+ */
+ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+ float startx = CFRA;
+ float fac = value;
+
+ /* take proportional editing into account */
+ fac = ((fac - 1.0f) * td->factor) + 1;
+
+ /* check if any need to apply nla-mapping */
+ if (adt) {
+ startx = BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP);
+ }
+
+ /* now, calculate the new value */
+ *(td->val) = ((td->ival - startx) * fac) + startx;
+
+ /* apply nearest snapping */
+ doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
+ }
+ }
+}
+
+static void applyTimeScale(TransInfo *t, const int UNUSED(mval[2]))
+{
+ char str[UI_MAX_DRAW_STR];
+
+ /* handle numeric-input stuff */
+ t->vec[0] = t->values[0];
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values_final[0] = t->vec[0];
+ headerTimeScale(t, str);
+
+ applyTimeScaleValue(t, t->values_final[0]);
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initTimeScale(TransInfo *t)
+{
+ float center[2];
+
+ /* this tool is only really available in the Action Editor
+ * AND NLA Editor (for strip scaling)
+ */
+ if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA) == 0) {
+ t->state = TRANS_CANCEL;
+ }
+
+ t->mode = TFM_TIME_SCALE;
+ t->transform = applyTimeScale;
+
+ /* recalculate center2d to use CFRA and mouse Y, since that's
+ * what is used in time scale */
+ if ((t->flag & T_OVERRIDE_CENTER) == 0) {
+ t->center_global[0] = t->scene->r.cfra;
+ projectFloatView(t, t->center_global, center);
+ center[1] = t->mouse.imval[1];
+ }
+
+ /* force a reinit with the center2d used here */
+ initMouseInput(t, &t->mouse, center, t->mouse.imval, false);
+
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+
+ t->flag |= T_NULL_ONE;
+ t->num.val_flag[0] |= NUM_NULL_ONE;
+
+ /* num-input has max of (n-1) */
+ t->idx_max = 0;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ /* initialize snap like for everything else */
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_timeslide.c b/source/blender/editors/transform/transform_mode_timeslide.c
new file mode 100644
index 00000000000..43e14a26930
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_timeslide.c
@@ -0,0 +1,236 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_nla.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Animation Time Slide) */
+
+/** \name Transform Animation Time Slide
+ * \{ */
+
+static void headerTimeSlide(TransInfo *t, const float sval, char str[UI_MAX_DRAW_STR])
+{
+ char tvec[NUM_STR_REP_LEN * 3];
+
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ const float *range = t->custom.mode.data;
+ float minx = range[0];
+ float maxx = range[1];
+ float cval = t->values_final[0];
+ float val;
+
+ val = 2.0f * (cval - sval) / (maxx - minx);
+ CLAMP(val, -1.0f, 1.0f);
+
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
+ }
+
+ BLI_snprintf(str, UI_MAX_DRAW_STR, TIP_("TimeSlide: %s"), &tvec[0]);
+}
+
+static void applyTimeSlideValue(TransInfo *t, float sval, float cval)
+{
+ int i;
+ const float *range = t->custom.mode.data;
+ float minx = range[0];
+ float maxx = range[1];
+
+ /* set value for drawing black line */
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
+ saction->timeslide = cval;
+ }
+
+ /* It doesn't matter whether we apply to t->data or
+ * t->data2d, but t->data2d is more convenient. */
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ /* it is assumed that td->extra is a pointer to the AnimData,
+ * whose active action is where this keyframe comes from
+ * (this is only valid when not in NLA)
+ */
+ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+
+ /* only apply to data if in range */
+ if ((sval > minx) && (sval < maxx)) {
+ float cvalc = CLAMPIS(cval, minx, maxx);
+ float ival = td->ival;
+ float timefac;
+
+ /* NLA mapping magic here works as follows:
+ * - "ival" goes from strip time to global time
+ * - calculation is performed into td->val in global time
+ * (since sval and min/max are all in global time)
+ * - "td->val" then gets put back into strip time
+ */
+ if (adt) {
+ /* strip to global */
+ ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP);
+ }
+
+ /* left half? */
+ if (ival < sval) {
+ timefac = (sval - ival) / (sval - minx);
+ *(td->val) = cvalc - timefac * (cvalc - minx);
+ }
+ else {
+ timefac = (ival - sval) / (maxx - sval);
+ *(td->val) = cvalc + timefac * (maxx - cvalc);
+ }
+
+ if (adt) {
+ /* global to strip */
+ *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP);
+ }
+ }
+ }
+ }
+}
+
+static void applyTimeSlide(TransInfo *t, const int mval[2])
+{
+ View2D *v2d = (View2D *)t->view;
+ float cval[2], sval[2];
+ const float *range = t->custom.mode.data;
+ float minx = range[0];
+ float maxx = range[1];
+ char str[UI_MAX_DRAW_STR];
+
+ /* calculate mouse co-ordinates */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]);
+ UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &sval[0], &sval[1]);
+
+ /* t->values_final[0] stores cval[0], which is the current mouse-pointer location (in frames) */
+ // XXX Need to be able to repeat this
+ /* t->values_final[0] = cval[0]; */ /* UNUSED (reset again later). */
+
+ /* handle numeric-input stuff */
+ t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx);
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values_final[0] = (maxx - minx) * t->vec[0] / 2.0f + sval[0];
+
+ headerTimeSlide(t, sval[0], str);
+ applyTimeSlideValue(t, sval[0], t->values_final[0]);
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initTimeSlide(TransInfo *t)
+{
+ /* this tool is only really available in the Action Editor... */
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
+
+ /* set flag for drawing stuff */
+ saction->flag |= SACTION_MOVING;
+ }
+ else {
+ t->state = TRANS_CANCEL;
+ }
+
+ t->mode = TFM_TIME_SLIDE;
+ t->transform = applyTimeSlide;
+
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ {
+ Scene *scene = t->scene;
+ float *range;
+ t->custom.mode.data = range = MEM_mallocN(sizeof(float[2]), "TimeSlide Min/Max");
+ t->custom.mode.use_free = true;
+
+ float min = 999999999.0f, max = -999999999.0f;
+ int i;
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+ float val = *(td->val);
+
+ /* strip/action time to global (mapped) time */
+ if (adt) {
+ val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP);
+ }
+
+ if (min > val) {
+ min = val;
+ }
+ if (max < val) {
+ max = val;
+ }
+ }
+ }
+
+ if (min == max) {
+ /* just use the current frame ranges */
+ min = (float)PSFRA;
+ max = (float)PEFRA;
+ }
+
+ range[0] = min;
+ range[1] = max;
+ }
+
+ /* num-input has max of (n-1) */
+ t->idx_max = 0;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ /* initialize snap like for everything else */
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ /* No time unit supporting frames currently... */
+ t->num.unit_type[0] = B_UNIT_NONE;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_timetranslate.c b/source/blender/editors/transform/transform_mode_timetranslate.c
new file mode 100644
index 00000000000..c514df497bc
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_timetranslate.c
@@ -0,0 +1,167 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "DNA_anim_types.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_nla.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Animation Translation) */
+
+/** \name Transform Animation Translation
+ * \{ */
+
+static void headerTimeTranslate(TransInfo *t, char str[UI_MAX_DRAW_STR])
+{
+ char tvec[NUM_STR_REP_LEN * 3];
+ int ofs = 0;
+
+ /* if numeric input is active, use results from that, otherwise apply snapping to result */
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ const short autosnap = getAnimEdit_SnapMode(t);
+ float val = t->values_final[0];
+
+ float snap_val;
+ snapFrameTransform(t, autosnap, false, val, &snap_val);
+
+ if (autosnap == SACTSNAP_FRAME) {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.2f (%.4f)", snap_val, val);
+ }
+ else if (autosnap == SACTSNAP_SECOND) {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.2f sec (%.4f)", snap_val, val);
+ }
+ else if (autosnap == SACTSNAP_TSTEP) {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f sec", snap_val);
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", snap_val);
+ }
+ }
+
+ ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, TIP_("DeltaX: %s"), &tvec[0]);
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
+ }
+}
+
+static void applyTimeTranslateValue(TransInfo *t, const float deltax)
+{
+ const short autosnap = getAnimEdit_SnapMode(t);
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ TransData2D *td2d = tc->data_2d;
+ /* It doesn't matter whether we apply to t->data or
+ * t->data2d, but t->data2d is more convenient. */
+ for (int i = 0; i < tc->data_len; i++, td++, td2d++) {
+ /* It is assumed that td->extra is a pointer to the AnimData,
+ * whose active action is where this keyframe comes from.
+ * (this is only valid when not in NLA)
+ * (also: masks and gpencil dont have animadata)
+ */
+ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+
+ /* apply nearest snapping */
+ *(td->val) = td->ival + deltax * td->factor;
+ doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
+ }
+ }
+}
+
+static void applyTimeTranslate(TransInfo *t, const int mval[2])
+{
+ View2D *v2d = (View2D *)t->view;
+ char str[UI_MAX_DRAW_STR];
+
+ /* calculate translation amount from mouse movement - in 'time-grid space' */
+ if (t->flag & T_MODAL) {
+ float cval[2], sval[2];
+ UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
+ UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[0], &sval[0], &sval[1]);
+
+ /* we only need to calculate effect for time (applyTimeTranslate only needs that) */
+ t->values[0] = cval[0] - sval[0];
+ }
+
+ /* handle numeric-input stuff */
+ t->vec[0] = t->values[0];
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values_final[0] = t->vec[0];
+ headerTimeTranslate(t, str);
+
+ applyTimeTranslateValue(t, t->values_final[0]);
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initTimeTranslate(TransInfo *t)
+{
+ /* this tool is only really available in the Action Editor... */
+ if (!ELEM(t->spacetype, SPACE_ACTION, SPACE_SEQ)) {
+ t->state = TRANS_CANCEL;
+ }
+
+ t->transform = applyTimeTranslate;
+
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ /* num-input has max of (n-1) */
+ t->idx_max = 0;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ /* initialize snap like for everything else */
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ /* No time unit supporting frames currently... */
+ t->num.unit_type[0] = B_UNIT_NONE;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_tosphere.c b/source/blender/editors/transform/transform_mode_tosphere.c
new file mode 100644
index 00000000000..841ccf41365
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_tosphere.c
@@ -0,0 +1,139 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (ToSphere) */
+
+/** \name Transform ToSphere
+ * \{ */
+
+static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
+{
+ float vec[3];
+ float ratio, radius;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ ratio = t->values[0];
+
+ snapGridIncrement(t, &ratio);
+
+ applyNumInput(&t->num, &ratio);
+
+ CLAMP(ratio, 0.0f, 1.0f);
+
+ t->values_final[0] = ratio;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ BLI_snprintf(str, sizeof(str), TIP_("To Sphere: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(str, sizeof(str), TIP_("To Sphere: %.4f %s"), ratio, t->proptext);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float tratio;
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ sub_v3_v3v3(vec, td->iloc, tc->center_local);
+
+ radius = normalize_v3(vec);
+
+ tratio = ratio * td->factor;
+
+ mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio);
+
+ add_v3_v3v3(td->loc, tc->center_local, vec);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initToSphere(TransInfo *t)
+{
+ int i;
+
+ t->mode = TFM_TOSPHERE;
+ t->transform = applyToSphere;
+
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->num.val_flag[0] |= NUM_NULL_ONE | NUM_NO_NEGATIVE;
+ t->flag |= T_NO_CONSTRAINT;
+
+ // Calculate average radius
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ t->val += len_v3v3(tc->center_local, td->iloc);
+ }
+ }
+
+ t->val /= (float)t->data_len_all;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_trackball.c b/source/blender/editors/transform/transform_mode_trackball.c
new file mode 100644
index 00000000000..c6e0b205204
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_trackball.c
@@ -0,0 +1,170 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Rotation - Trackball) */
+
+/** \name Transform Rotation - Trackball
+ * \{ */
+
+static void applyTrackballValue(TransInfo *t,
+ const float axis1[3],
+ const float axis2[3],
+ const float angles[2])
+{
+ float mat[3][3];
+ float axis[3];
+ float angle;
+ int i;
+
+ mul_v3_v3fl(axis, axis1, angles[0]);
+ madd_v3_v3fl(axis, axis2, angles[1]);
+ angle = normalize_v3(axis);
+ axis_angle_normalized_to_mat3(mat, axis, angle);
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if (t->flag & T_PROP_EDIT) {
+ axis_angle_normalized_to_mat3(mat, axis, td->factor * angle);
+ }
+
+ ElementRotation(t, tc, td, mat, t->around);
+ }
+ }
+}
+
+static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
+{
+ char str[UI_MAX_DRAW_STR];
+ size_t ofs = 0;
+ float axis1[3], axis2[3];
+#if 0 /* UNUSED */
+ float mat[3][3], totmat[3][3], smat[3][3];
+#endif
+ float phi[2];
+
+ copy_v3_v3(axis1, t->persinv[0]);
+ copy_v3_v3(axis2, t->persinv[1]);
+ normalize_v3(axis1);
+ normalize_v3(axis2);
+
+ copy_v2_v2(phi, t->values);
+
+ snapGridIncrement(t, phi);
+
+ applyNumInput(&t->num, phi);
+
+ copy_v2_v2(t->values_final, phi);
+
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN * 2];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ ofs += BLI_snprintf(str + ofs,
+ sizeof(str) - ofs,
+ TIP_("Trackball: %s %s %s"),
+ &c[0],
+ &c[NUM_STR_REP_LEN],
+ t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ sizeof(str) - ofs,
+ TIP_("Trackball: %.2f %.2f %s"),
+ RAD2DEGF(phi[0]),
+ RAD2DEGF(phi[1]),
+ t->proptext);
+ }
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
+ }
+
+#if 0 /* UNUSED */
+ axis_angle_normalized_to_mat3(smat, axis1, phi[0]);
+ axis_angle_normalized_to_mat3(totmat, axis2, phi[1]);
+
+ mul_m3_m3m3(mat, smat, totmat);
+
+ // TRANSFORM_FIX_ME
+ //copy_m3_m3(t->mat, mat); // used in gizmo
+#endif
+
+ applyTrackballValue(t, axis1, axis2, phi);
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initTrackball(TransInfo *t)
+{
+ t->mode = TFM_TRACKBALL;
+ t->transform = applyTrackball;
+
+ initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL);
+
+ t->idx_max = 1;
+ t->num.idx_max = 1;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
+
+ copy_v3_fl(t->num.val_inc, t->snap[2]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
+ t->num.unit_type[1] = B_UNIT_ROTATION;
+
+ t->flag |= T_NO_CONSTRAINT;
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
new file mode 100644
index 00000000000..0a7d8bd90d3
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -0,0 +1,412 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_gpencil_types.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_unit.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+
+#include "UI_interface.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_convert.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Translation) */
+
+/** \name Transform Translation
+ * \{ */
+
+static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR])
+{
+ size_t ofs = 0;
+ char tvec[NUM_STR_REP_LEN * 3];
+ char distvec[NUM_STR_REP_LEN];
+ char autoik[NUM_STR_REP_LEN];
+ float dist;
+
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ dist = len_v3(t->num.val);
+ }
+ else {
+ float dvec[3];
+
+ copy_v3_v3(dvec, vec);
+ applyAspectRatio(t, dvec);
+
+ dist = len_v3(vec);
+ if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ bUnit_AsString2(&tvec[NUM_STR_REP_LEN * i],
+ NUM_STR_REP_LEN,
+ dvec[i] * t->scene->unit.scale_length,
+ 4,
+ B_UNIT_LENGTH,
+ &t->scene->unit,
+ true);
+ }
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]);
+ }
+ }
+
+ if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
+ bUnit_AsString2(distvec,
+ sizeof(distvec),
+ dist * t->scene->unit.scale_length,
+ 4,
+ B_UNIT_LENGTH,
+ &t->scene->unit,
+ false);
+ }
+ else if (dist > 1e10f || dist < -1e10f) {
+ /* prevent string buffer overflow */
+ BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist);
+ }
+ else {
+ BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist);
+ }
+
+ if (t->flag & T_AUTOIK) {
+ short chainlen = t->settings->autoik_chainlen;
+
+ if (chainlen) {
+ BLI_snprintf(autoik, NUM_STR_REP_LEN, TIP_("AutoIK-Len: %d"), chainlen);
+ }
+ else {
+ autoik[0] = '\0';
+ }
+ }
+ else {
+ autoik[0] = '\0';
+ }
+
+ if (t->con.mode & CON_APPLY) {
+ switch (t->num.idx_max) {
+ case 0:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "D: %s (%s)%s %s %s",
+ &tvec[0],
+ distvec,
+ t->con.text,
+ t->proptext,
+ autoik);
+ break;
+ case 1:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "D: %s D: %s (%s)%s %s %s",
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ distvec,
+ t->con.text,
+ t->proptext,
+ autoik);
+ break;
+ case 2:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "D: %s D: %s D: %s (%s)%s %s %s",
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ distvec,
+ t->con.text,
+ t->proptext,
+ autoik);
+ break;
+ }
+ }
+ else {
+ if (t->flag & T_2D_EDIT) {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "Dx: %s Dy: %s (%s)%s %s",
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ distvec,
+ t->con.text,
+ t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "Dx: %s Dy: %s Dz: %s (%s)%s %s %s",
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ distvec,
+ t->con.text,
+ t->proptext,
+ autoik);
+ }
+ }
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" Proportional size: %.2f"), t->prop_size);
+ }
+
+ if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->area->spacedata.first;
+
+ if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
+ const char *str_old = BLI_strdup(str);
+ const char *str_dir = (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) ? TIP_("right") :
+ TIP_("left");
+ char str_km[64];
+
+ WM_modalkeymap_items_to_string(
+ t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, str_km, sizeof(str_km));
+
+ ofs += BLI_snprintf(str,
+ UI_MAX_DRAW_STR,
+ TIP_("Auto-offset set to %s - press %s to toggle direction | %s"),
+ str_dir,
+ str_km,
+ str_old);
+
+ MEM_freeN((void *)str_old);
+ }
+ }
+}
+
+static void applyTranslationValue(TransInfo *t, const float vec[3])
+{
+ const bool apply_snap_align_rotation = usingSnappingNormal(
+ t); // && (t->tsnap.status & POINT_INIT);
+ float tvec[3];
+
+ /* The ideal would be "apply_snap_align_rotation" only when a snap point is found
+ * so, maybe inside this function is not the best place to apply this rotation.
+ * but you need "handle snapping rotation before doing the translation" (really?) */
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+
+ float pivot[3];
+ if (apply_snap_align_rotation) {
+ copy_v3_v3(pivot, t->tsnap.snapTarget);
+ /* The pivot has to be in local-space (see T49494) */
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->imat, pivot);
+ }
+ }
+
+ TransData *td = tc->data;
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION) {
+ break;
+ }
+
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ float rotate_offset[3] = {0};
+ bool use_rotate_offset = false;
+
+ /* handle snapping rotation before doing the translation */
+ if (apply_snap_align_rotation) {
+ float mat[3][3];
+
+ if (validSnappingNormal(t)) {
+ const float *original_normal;
+
+ /* In pose mode, we want to align normals with Y axis of bones... */
+ if (t->flag & T_POSE) {
+ original_normal = td->axismtx[1];
+ }
+ else {
+ original_normal = td->axismtx[2];
+ }
+
+ rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal);
+ }
+ else {
+ unit_m3(mat);
+ }
+
+ ElementRotation_ex(t, tc, td, mat, pivot);
+
+ if (td->loc) {
+ use_rotate_offset = true;
+ sub_v3_v3v3(rotate_offset, td->loc, td->iloc);
+ }
+ }
+
+ if (t->con.applyVec) {
+ float pvec[3];
+ t->con.applyVec(t, tc, td, vec, tvec, pvec);
+ }
+ else {
+ copy_v3_v3(tvec, vec);
+ }
+
+ mul_m3_v3(td->smtx, tvec);
+
+ if (use_rotate_offset) {
+ add_v3_v3(tvec, rotate_offset);
+ }
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* grease pencil multiframe falloff */
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ if (gps != NULL) {
+ mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff);
+ }
+ else {
+ mul_v3_fl(tvec, td->factor);
+ }
+ }
+ else {
+ /* proportional editing falloff */
+ mul_v3_fl(tvec, td->factor);
+ }
+
+ protectedTransBits(td->protectflag, tvec);
+
+ if (td->loc) {
+ add_v3_v3v3(td->loc, td->iloc, tvec);
+ }
+
+ constraintTransLim(t, td);
+ }
+ }
+}
+
+static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
+{
+ char str[UI_MAX_DRAW_STR];
+ float values_final[3];
+
+ if (t->flag & T_INPUT_IS_VALUES_FINAL) {
+ copy_v3_v3(t->values_final, t->values);
+ }
+ else {
+ copy_v3_v3(t->values_final, t->values);
+ if ((t->con.mode & CON_APPLY) == 0) {
+ snapGridIncrement(t, t->values_final);
+ }
+
+ if (applyNumInput(&t->num, t->values_final)) {
+ removeAspectRatio(t, t->values_final);
+ }
+
+ applySnapping(t, t->values_final);
+ }
+ copy_v3_v3(values_final, t->values_final);
+
+ if (t->con.mode & CON_APPLY) {
+ float pvec[3] = {0.0f, 0.0f, 0.0f};
+ t->con.applyVec(t, NULL, NULL, t->values_final, values_final, pvec);
+ headerTranslation(t, pvec, str);
+
+ /* only so we have re-usable value with redo, see T46741. */
+ mul_v3_m3v3(t->values_final, t->con.imtx, values_final);
+ }
+ else {
+ headerTranslation(t, t->values_final, str);
+ copy_v3_v3(values_final, t->values_final);
+ }
+
+ /* don't use 't->values' now on */
+
+ applyTranslationValue(t, values_final);
+
+ /* evil hack - redo translation if clipping needed */
+ if (t->flag & T_CLIP_UV && clipUVTransform(t, values_final, 0)) {
+ applyTranslationValue(t, values_final);
+
+ /* In proportional edit it can happen that */
+ /* vertices in the radius of the brush end */
+ /* outside the clipping area */
+ /* XXX HACK - dg */
+ if (t->flag & T_PROP_EDIT_ALL) {
+ clipUVData(t);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initTranslation(TransInfo *t)
+{
+ if (t->spacetype == SPACE_ACTION) {
+ /* this space uses time translate */
+ BKE_report(t->reports,
+ RPT_ERROR,
+ "Use 'Time_Translate' transform mode instead of 'Translation' mode "
+ "for translating keyframes in Dope Sheet Editor");
+ t->state = TRANS_CANCEL;
+ }
+
+ t->transform = applyTranslation;
+
+ initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
+
+ t->idx_max = (t->flag & T_2D_EDIT) ? 1 : 2;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ copy_v3_v3(t->snap, t->snap_spatial);
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* Handling units makes only sense in 3Dview... See T38877. */
+ t->num.unit_type[0] = B_UNIT_LENGTH;
+ t->num.unit_type[1] = B_UNIT_LENGTH;
+ t->num.unit_type[2] = B_UNIT_LENGTH;
+ }
+ else {
+ /* SPACE_GRAPH, SPACE_ACTION, etc. could use some time units, when we have them... */
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
+ t->num.unit_type[2] = B_UNIT_NONE;
+ }
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c
new file mode 100644
index 00000000000..7bee48337f9
--- /dev/null
+++ b/source/blender/editors/transform/transform_mode_vert_slide.c
@@ -0,0 +1,666 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_editmesh.h"
+#include "BKE_unit.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "BLT_translation.h"
+
+#include "transform.h"
+#include "transform_convert.h"
+#include "transform_mode.h"
+#include "transform_snap.h"
+
+/* -------------------------------------------------------------------- */
+/* Transform (Vert Slide) */
+
+/** \name Transform Vert Slide
+ * \{ */
+
+typedef struct TransDataVertSlideVert {
+ /** #TransDataGenericSlideVert (header) */
+ struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
+ float co_orig_3d[3];
+ /* end generic */
+
+ float (*co_link_orig_3d)[3];
+ int co_link_tot;
+ int co_link_curr;
+} TransDataVertSlideVert;
+
+typedef struct VertSlideData {
+ TransDataVertSlideVert *sv;
+ int totsv;
+ int curr_sv_index;
+
+ /* result of ED_view3d_ob_project_mat_get */
+ float proj_mat[4][4];
+} VertSlideData;
+
+typedef struct VertSlideParams {
+ float perc;
+
+ bool use_even;
+ bool flipped;
+} VertSlideParams;
+
+static void calcVertSlideCustomPoints(struct TransInfo *t)
+{
+ VertSlideParams *slp = t->custom.mode.data;
+ VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
+
+ const float *co_orig_3d = sv->co_orig_3d;
+ const float *co_curr_3d = sv->co_link_orig_3d[sv->co_link_curr];
+
+ float co_curr_2d[2], co_orig_2d[2];
+
+ int mval_ofs[2], mval_start[2], mval_end[2];
+
+ ED_view3d_project_float_v2_m4(t->region, co_orig_3d, co_orig_2d, sld->proj_mat);
+ ED_view3d_project_float_v2_m4(t->region, co_curr_3d, co_curr_2d, sld->proj_mat);
+
+ ARRAY_SET_ITEMS(mval_ofs, t->mouse.imval[0] - co_orig_2d[0], t->mouse.imval[1] - co_orig_2d[1]);
+ ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]);
+ ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]);
+
+ if (slp->flipped && slp->use_even) {
+ setCustomPoints(t, &t->mouse, mval_start, mval_end);
+ }
+ else {
+ setCustomPoints(t, &t->mouse, mval_end, mval_start);
+ }
+
+ /* setCustomPoints isn't normally changing as the mouse moves,
+ * in this case apply mouse input immediately so we don't refresh
+ * with the value from the previous points */
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+}
+
+/**
+ * Run once when initializing vert slide to find the reference edge
+ */
+static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
+{
+ /* Active object may have no selected vertices. */
+ VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ float mval_fl[2] = {UNPACK2(mval)};
+ TransDataVertSlideVert *sv;
+
+ /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */
+ float dist_sq = 0.0f;
+ float dist_min_sq = FLT_MAX;
+ int i;
+
+ for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
+ float co_2d[2];
+
+ ED_view3d_project_float_v2_m4(t->region, sv->co_orig_3d, co_2d, sld->proj_mat);
+
+ dist_sq = len_squared_v2v2(mval_fl, co_2d);
+ if (dist_sq < dist_min_sq) {
+ dist_min_sq = dist_sq;
+ sld->curr_sv_index = i;
+ }
+ }
+}
+
+/**
+ * Run while moving the mouse to slide along the edge matching the mouse direction
+ */
+static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2])
+{
+ VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ float imval_fl[2] = {UNPACK2(t->mouse.imval)};
+ float mval_fl[2] = {UNPACK2(mval)};
+
+ float dir[3];
+ TransDataVertSlideVert *sv;
+ int i;
+
+ /* note: we could save a matrix-multiply for each vertex
+ * by finding the closest edge in local-space.
+ * However this skews the outcome with non-uniform-scale. */
+
+ /* first get the direction of the original mouse position */
+ sub_v2_v2v2(dir, imval_fl, mval_fl);
+ ED_view3d_win_to_delta(t->region, dir, dir, t->zfac);
+ normalize_v3(dir);
+
+ for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
+ if (sv->co_link_tot > 1) {
+ float dir_dot_best = -FLT_MAX;
+ int co_link_curr_best = -1;
+ int j;
+
+ for (j = 0; j < sv->co_link_tot; j++) {
+ float tdir[3];
+ float dir_dot;
+
+ sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]);
+ mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, tdir);
+ project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]);
+
+ normalize_v3(tdir);
+ dir_dot = dot_v3v3(dir, tdir);
+ if (dir_dot > dir_dot_best) {
+ dir_dot_best = dir_dot;
+ co_link_curr_best = j;
+ }
+ }
+
+ if (co_link_curr_best != -1) {
+ sv->co_link_curr = co_link_curr_best;
+ }
+ }
+ }
+}
+
+static bool createVertSlideVerts(TransInfo *t, TransDataContainer *tc)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMIter eiter;
+ BMEdge *e;
+ BMVert *v;
+ TransDataVertSlideVert *sv_array;
+ VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
+ int j;
+
+ sld->curr_sv_index = 0;
+
+ j = 0;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ bool ok = false;
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) {
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ ok = true;
+ break;
+ }
+ }
+ }
+
+ if (ok) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ j += 1;
+ }
+ else {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+ }
+
+ if (!j) {
+ MEM_freeN(sld);
+ return false;
+ }
+
+ sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array");
+
+ j = 0;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ int k;
+ sv_array[j].v = v;
+ copy_v3_v3(sv_array[j].co_orig_3d, v->co);
+
+ k = 0;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ k++;
+ }
+ }
+
+ sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k,
+ __func__);
+ sv_array[j].co_link_tot = k;
+
+ k = 0;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co);
+ k++;
+ }
+ }
+ j++;
+ }
+ }
+
+ sld->sv = sv_array;
+ sld->totsv = j;
+
+ tc->custom.mode.data = sld;
+
+ /* most likely will be set below */
+ unit_m4(sld->proj_mat);
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* view vars */
+ RegionView3D *rv3d = NULL;
+ ARegion *region = t->region;
+
+ rv3d = region ? region->regiondata : NULL;
+ if (rv3d) {
+ ED_view3d_ob_project_mat_get(rv3d, tc->obedit, sld->proj_mat);
+ }
+ }
+
+ /* XXX, calc vert slide across all objects */
+ if (tc == t->data_container) {
+ calcVertSlideMouseActiveVert(t, t->mval);
+ calcVertSlideMouseActiveEdges(t, t->mval);
+ }
+
+ return true;
+}
+
+static void freeVertSlideVerts(TransInfo *UNUSED(t),
+ TransDataContainer *UNUSED(tc),
+ TransCustomData *custom_data)
+{
+ VertSlideData *sld = custom_data->data;
+
+ if (!sld) {
+ return;
+ }
+
+ if (sld->totsv > 0) {
+ TransDataVertSlideVert *sv = sld->sv;
+ int i = 0;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ MEM_freeN(sv->co_link_orig_3d);
+ }
+ }
+
+ MEM_freeN(sld->sv);
+ MEM_freeN(sld);
+
+ custom_data->data = NULL;
+}
+
+static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event)
+{
+ if (t->mode == TFM_VERT_SLIDE) {
+ VertSlideParams *slp = t->custom.mode.data;
+
+ if (slp) {
+ switch (event->type) {
+ case EVT_EKEY:
+ if (event->val == KM_PRESS) {
+ slp->use_even = !slp->use_even;
+ if (slp->flipped) {
+ calcVertSlideCustomPoints(t);
+ }
+ return TREDRAW_HARD;
+ }
+ break;
+ case EVT_FKEY:
+ if (event->val == KM_PRESS) {
+ slp->flipped = !slp->flipped;
+ calcVertSlideCustomPoints(t);
+ return TREDRAW_HARD;
+ }
+ break;
+ case EVT_CKEY:
+ /* use like a modifier key */
+ if (event->val == KM_PRESS) {
+ t->flag ^= T_ALT_TRANSFORM;
+ calcVertSlideCustomPoints(t);
+ return TREDRAW_HARD;
+ }
+ break;
+#if 0
+ case EVT_MODAL_MAP:
+ switch (event->val) {
+ case TFM_MODAL_EDGESLIDE_DOWN:
+ sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
+ break;
+ case TFM_MODAL_EDGESLIDE_UP:
+ sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
+ break;
+ }
+ break;
+#endif
+ case MOUSEMOVE: {
+ /* don't recalculate the best edge */
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ if (is_clamp) {
+ calcVertSlideMouseActiveEdges(t, event->mval);
+ }
+ calcVertSlideCustomPoints(t);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ return TREDRAW_NOTHING;
+}
+
+void projectVertSlideData(TransInfo *t, bool is_final)
+{
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ trans_mesh_customdata_correction_apply(tc, is_final);
+ }
+}
+
+void drawVertSlide(TransInfo *t)
+{
+ if ((t->mode == TFM_VERT_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
+ const VertSlideParams *slp = t->custom.mode.data;
+ VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+
+ /* Non-Prop mode */
+ {
+ TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ TransDataVertSlideVert *sv;
+ const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
+ const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
+ const int alpha_shade = -160;
+ int i;
+
+ GPU_depth_test(false);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ GPU_matrix_push();
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+
+ GPU_line_width(line_size);
+
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+
+ immBegin(GPU_PRIM_LINES, sld->totsv * 2);
+ if (is_clamp) {
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ immVertex3fv(shdr_pos, sv->co_orig_3d);
+ immVertex3fv(shdr_pos, sv->co_link_orig_3d[sv->co_link_curr]);
+ }
+ }
+ else {
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float a[3], b[3];
+ sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
+ mul_v3_fl(a, 100.0f);
+ negate_v3_v3(b, a);
+ add_v3_v3(a, sv->co_orig_3d);
+ add_v3_v3(b, sv->co_orig_3d);
+
+ immVertex3fv(shdr_pos, a);
+ immVertex3fv(shdr_pos, b);
+ }
+ }
+ immEnd();
+
+ GPU_point_size(ctrl_size);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(shdr_pos,
+ (slp->flipped && slp->use_even) ?
+ curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
+ curr_sv->co_orig_3d);
+ immEnd();
+
+ immUnbindProgram();
+
+ /* direction from active vertex! */
+ if ((t->mval[0] != t->mouse.imval[0]) || (t->mval[1] != t->mouse.imval[1])) {
+ float zfac;
+ float mval_ofs[2];
+ float co_orig_3d[3];
+ float co_dest_3d[3];
+
+ mval_ofs[0] = t->mval[0] - t->mouse.imval[0];
+ mval_ofs[1] = t->mval[1] - t->mouse.imval[1];
+
+ mul_v3_m4v3(
+ co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d);
+ zfac = ED_view3d_calc_zfac(t->region->regiondata, co_orig_3d, NULL);
+
+ ED_view3d_win_to_delta(t->region, mval_ofs, co_dest_3d, zfac);
+
+ invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat,
+ TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d);
+
+ add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
+
+ GPU_line_width(1.0f);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, curr_sv->co_orig_3d);
+ immVertex3fv(shdr_pos, co_dest_3d);
+ immEnd();
+
+ immUnbindProgram();
+ }
+
+ GPU_matrix_pop();
+
+ GPU_depth_test(true);
+ }
+ }
+}
+
+void doVertSlide(TransInfo *t, float perc)
+{
+ VertSlideParams *slp = t->custom.mode.data;
+
+ slp->perc = perc;
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ VertSlideData *sld = tc->custom.mode.data;
+ TransDataVertSlideVert *svlist = sld->sv, *sv;
+ int i;
+
+ sv = svlist;
+
+ if (slp->use_even == false) {
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc);
+ }
+ }
+ else {
+ TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index];
+ const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d,
+ sv_curr->co_link_orig_3d[sv_curr->co_link_curr]);
+ const float tperc = perc * edge_len_curr;
+
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float edge_len;
+ float dir[3];
+
+ sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
+ edge_len = normalize_v3(dir);
+
+ if (edge_len > FLT_EPSILON) {
+ if (slp->flipped) {
+ madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc);
+ }
+ else {
+ madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc);
+ }
+ }
+ else {
+ copy_v3_v3(sv->v->co, sv->co_orig_3d);
+ }
+ }
+ }
+ }
+}
+
+static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
+{
+ char str[UI_MAX_DRAW_STR];
+ size_t ofs = 0;
+ float final;
+ VertSlideParams *slp = t->custom.mode.data;
+ const bool flipped = slp->flipped;
+ const bool use_even = slp->use_even;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num));
+
+ final = t->values[0];
+
+ snapGridIncrement(t, &final);
+
+ /* only do this so out of range values are not displayed */
+ if (is_constrained) {
+ CLAMP(final, 0.0f, 1.0f);
+ }
+
+ applyNumInput(&t->num, &final);
+
+ t->values_final[0] = final;
+
+ /* header string */
+ ofs += BLI_strncpy_rlen(str + ofs, TIP_("Vert Slide: "), sizeof(str) - ofs);
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final);
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, TIP_("(E)ven: %s, "), WM_bool_as_string(use_even));
+ if (use_even) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, TIP_("(F)lipped: %s, "), WM_bool_as_string(flipped));
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, TIP_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
+ /* done with header string */
+
+ /* do stuff here */
+ doVertSlide(t, final);
+
+ recalcData(t);
+
+ ED_area_status_text(t->area, str);
+}
+
+void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
+{
+
+ t->mode = TFM_VERT_SLIDE;
+ t->transform = applyVertSlide;
+ t->handleEvent = handleEventVertSlide;
+
+ {
+ VertSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
+ slp->use_even = use_even;
+ slp->flipped = flipped;
+ slp->perc = 0.0f;
+
+ if (!use_clamp) {
+ t->flag |= T_ALT_TRANSFORM;
+ }
+
+ t->custom.mode.data = slp;
+ t->custom.mode.use_free = true;
+ }
+
+ bool ok = false;
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ ok |= createVertSlideVerts(t, tc);
+ VertSlideData *sld = tc->custom.mode.data;
+ if (sld) {
+ tc->custom.mode.free_cb = freeVertSlideVerts;
+ }
+ }
+
+ if (ok == false) {
+ t->state = TRANS_CANCEL;
+ return;
+ }
+
+ trans_mesh_customdata_correction_init(t);
+
+ /* set custom point first if you want value to be initialized by init */
+ calcVertSlideCustomPoints(t);
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
+
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+}
+
+void initVertSlide(TransInfo *t)
+{
+ initVertSlide_ex(t, false, false, true);
+}
+/** \} */
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 09992e8be0e..d643244e6ca 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -30,10 +30,10 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_report.h"
#include "BKE_editmesh.h"
+#include "BKE_global.h"
#include "BKE_layer.h"
+#include "BKE_report.h"
#include "BKE_scene.h"
#include "RNA_access.h"
@@ -42,8 +42,8 @@
#include "WM_api.h"
#include "WM_message.h"
-#include "WM_types.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -75,6 +75,7 @@ static const char OP_PUSH_PULL[] = "TRANSFORM_OT_push_pull";
static const char OP_TILT[] = "TRANSFORM_OT_tilt";
static const char OP_TRACKBALL[] = "TRANSFORM_OT_trackball";
static const char OP_MIRROR[] = "TRANSFORM_OT_mirror";
+static const char OP_BONE_SIZE[] = "TRANSFORM_OT_bbone_resize";
static const char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide";
static const char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide";
static const char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease";
@@ -94,6 +95,7 @@ static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot);
static void TRANSFORM_OT_tilt(struct wmOperatorType *ot);
static void TRANSFORM_OT_trackball(struct wmOperatorType *ot);
static void TRANSFORM_OT_mirror(struct wmOperatorType *ot);
+static void TRANSFORM_OT_bbone_resize(struct wmOperatorType *ot);
static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot);
static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot);
static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot);
@@ -114,6 +116,7 @@ static TransformModeItem transform_modes[] = {
{OP_TILT, TFM_TILT, TRANSFORM_OT_tilt},
{OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball},
{OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror},
+ {OP_BONE_SIZE, TFM_BONESIZE, TRANSFORM_OT_bbone_resize},
{OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide},
{OP_VERT_SLIDE, TFM_VERT_SLIDE, TRANSFORM_OT_vert_slide},
{OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease},
@@ -220,6 +223,9 @@ static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op))
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ WM_msg_publish_rna_prop(mbus, &scene->id, scene, Scene, transform_orientation_slots);
+
return OPERATOR_FINISHED;
}
@@ -230,12 +236,11 @@ static int delete_orientation_invoke(bContext *C, wmOperator *op, const wmEvent
static bool delete_orientation_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
-
if (ED_operator_areaactive(C) == 0) {
return 0;
}
+ Scene *scene = CTX_data_scene(C);
return ((scene->orientation_slots[SCE_ORIENT_DEFAULT].type >= V3D_ORIENT_CUSTOM) &&
(scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom != -1));
}
@@ -261,6 +266,7 @@ static int create_orientation_exec(bContext *C, wmOperator *op)
const bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
const bool use_view = RNA_boolean_get(op->ptr, "use_view");
View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
RNA_string_get(op->ptr, "name", name);
@@ -271,10 +277,18 @@ static int create_orientation_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite);
+ if (!BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite)) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to create orientation");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (use) {
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ WM_msg_publish_rna_prop(mbus, &scene->id, scene, Scene, transform_orientation_slots);
+ WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
+ }
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, CTX_data_scene(C));
return OPERATOR_FINISHED;
}
@@ -702,6 +716,15 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation");
RNA_def_property_flag(prop, PROP_HIDDEN);
}
+
+ if (flags & P_POST_TRANSFORM) {
+ prop = RNA_def_boolean(ot->srna,
+ "use_automerge_and_split",
+ 0,
+ "Auto Merge & Split",
+ "Forces the use of Auto Merge & Split");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
}
static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
@@ -727,7 +750,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
Transform_Properties(ot,
P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP |
- P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT);
+ P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT | P_POST_TRANSFORM);
}
static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
@@ -890,8 +913,8 @@ static bool transform_shear_poll(bContext *C)
return false;
}
- ScrArea *sa = CTX_wm_area(C);
- return sa && !ELEM(sa->spacetype, SPACE_ACTION);
+ ScrArea *area = CTX_wm_area(C);
+ return area && !ELEM(area->spacetype, SPACE_ACTION);
}
static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
@@ -1015,6 +1038,30 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
}
+static void TRANSFORM_OT_bbone_resize(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Scale B-Bone";
+ ot->description = "Scale selected bendy bones display size";
+ ot->idname = OP_BONE_SIZE;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editarmature;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_translation(
+ ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "Display Size", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_MIRROR);
+}
+
static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -1221,8 +1268,8 @@ static int transform_from_gizmo_invoke(bContext *C,
{
bToolRef *tref = WM_toolsystem_ref_from_context(C);
if (tref) {
- ARegion *ar = CTX_wm_region(C);
- wmGizmoMap *gzmap = ar->gizmo_map;
+ ARegion *region = CTX_wm_region(C);
+ wmGizmoMap *gzmap = region->gizmo_map;
wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_xform_gizmo") : NULL;
if (gzgroup != NULL) {
PointerRNA gzg_ptr;
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 1952a2c862e..81c63278366 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -18,9 +18,9 @@
* \ingroup edtransform
*/
-#include <string.h>
-#include <stddef.h>
#include <ctype.h>
+#include <stddef.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -34,15 +34,15 @@
#include "DNA_view3d_types.h"
#include "DNA_workspace_types.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BKE_action.h"
-#include "BKE_curve.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
#include "BKE_report.h"
@@ -296,7 +296,7 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa
return true;
}
-void BIF_createTransformOrientation(bContext *C,
+bool BIF_createTransformOrientation(bContext *C,
ReportList *reports,
const char *name,
const bool use_view,
@@ -333,6 +333,7 @@ void BIF_createTransformOrientation(bContext *C,
if (activate && ts != NULL) {
BIF_selectTransformOrientation(C, ts);
}
+ return (ts != NULL);
}
TransformOrientation *addMatrixSpace(bContext *C,
@@ -406,14 +407,19 @@ bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3]
return true;
}
-static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it)
+/* Updates all `BONE_TRANSFORM` flags.
+ * Returns total number of bones with `BONE_TRANSFORM`.
+ * Note: `transform_convert_pose_transflags_update` has a similar logic. */
+static int armature_bone_transflags_update_recursive(bArmature *arm,
+ ListBase *lb,
+ const bool do_it)
{
Bone *bone;
bool do_next;
int total = 0;
for (bone = lb->first; bone; bone = bone->next) {
- bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
+ bone->flag &= ~BONE_TRANSFORM;
do_next = do_it;
if (do_it) {
if (bone->layer & arm->layer) {
@@ -426,18 +432,18 @@ static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it)
}
}
}
- total += count_bone_select(arm, &bone->childbase, do_next);
+ total += armature_bone_transflags_update_recursive(arm, &bone->childbase, do_next);
}
return total;
}
-void initTransformOrientation(bContext *C, TransInfo *t)
+void initTransformOrientation(bContext *C, TransInfo *t, short orientation)
{
Object *ob = CTX_data_active_object(C);
Object *obedit = CTX_data_active_object(C);
- switch (t->orientation.user) {
+ switch (orientation) {
case V3D_ORIENT_GLOBAL:
unit_m3(t->spacemtx);
BLI_strncpy(t->spacename, TIP_("global"), sizeof(t->spacename));
@@ -470,32 +476,33 @@ void initTransformOrientation(bContext *C, TransInfo *t)
break;
- case V3D_ORIENT_VIEW:
- if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
- RegionView3D *rv3d = t->ar->regiondata;
- float mat[3][3];
-
+ case V3D_ORIENT_VIEW: {
+ float mat[3][3];
+ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
BLI_strncpy(t->spacename, TIP_("view"), sizeof(t->spacename));
- copy_m3_m4(mat, rv3d->viewinv);
+ copy_m3_m4(mat, t->viewinv);
normalize_m3(mat);
- copy_m3_m3(t->spacemtx, mat);
}
else {
- unit_m3(t->spacemtx);
+ unit_m3(mat);
}
+ negate_v3(mat[2]);
+ copy_m3_m3(t->spacemtx, mat);
break;
+ }
case V3D_ORIENT_CURSOR: {
BLI_strncpy(t->spacename, TIP_("cursor"), sizeof(t->spacename));
BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, t->spacemtx);
break;
}
case V3D_ORIENT_CUSTOM_MATRIX:
- /* Already set. */
BLI_strncpy(t->spacename, TIP_("custom"), sizeof(t->spacename));
+ copy_m3_m3(t->spacemtx, t->orientation.custom_matrix);
break;
case V3D_ORIENT_CUSTOM:
+ default:
+ BLI_assert(orientation >= V3D_ORIENT_CUSTOM);
BLI_strncpy(t->spacename, t->orientation.custom->name, sizeof(t->spacename));
-
if (applyTransformOrientation(t->orientation.custom, t->spacemtx, t->spacename)) {
/* pass */
}
@@ -504,31 +511,17 @@ void initTransformOrientation(bContext *C, TransInfo *t)
}
break;
}
-
- if (t->orient_matrix_is_set == false) {
- t->orient_matrix_is_set = true;
- if (t->flag & T_MODAL) {
- /* Rotate for example defaults to operating on the view plane. */
- t->orientation.unset = V3D_ORIENT_VIEW;
- copy_m3_m4(t->orient_matrix, t->viewinv);
- normalize_m3(t->orient_matrix);
- }
- else {
- copy_m3_m3(t->orient_matrix, t->spacemtx);
- }
- negate_m3(t->orient_matrix);
- }
}
/**
* utility function - get first n, selected vert/edge/faces
*/
-static unsigned int bm_mesh_elems_select_get_n__internal(
- BMesh *bm, BMElem **elems, const unsigned int n, const BMIterType itype, const char htype)
+static uint bm_mesh_elems_select_get_n__internal(
+ BMesh *bm, BMElem **elems, const uint n, const BMIterType itype, const char htype)
{
BMIter iter;
BMElem *ele;
- unsigned int i;
+ uint i;
BLI_assert(ELEM(htype, BM_VERT, BM_EDGE, BM_FACE));
BLI_assert(ELEM(itype, BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH));
@@ -579,18 +572,18 @@ static unsigned int bm_mesh_elems_select_get_n__internal(
return i;
}
-static unsigned int bm_mesh_verts_select_get_n(BMesh *bm, BMVert **elems, const unsigned int n)
+static uint bm_mesh_verts_select_get_n(BMesh *bm, BMVert **elems, const uint n)
{
return bm_mesh_elems_select_get_n__internal(
bm, (BMElem **)elems, min_ii(n, bm->totvertsel), BM_VERTS_OF_MESH, BM_VERT);
}
-static unsigned int bm_mesh_edges_select_get_n(BMesh *bm, BMEdge **elems, const unsigned int n)
+static uint bm_mesh_edges_select_get_n(BMesh *bm, BMEdge **elems, const uint n)
{
return bm_mesh_elems_select_get_n__internal(
bm, (BMElem **)elems, min_ii(n, bm->totedgesel), BM_EDGES_OF_MESH, BM_EDGE);
}
#if 0
-static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const unsigned int n)
+static uint bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const uint n)
{
return bm_mesh_elems_select_get_n__internal(
bm, (BMElem **)elems, min_ii(n, bm->totfacesel), BM_FACES_OF_MESH, BM_FACE);
@@ -1071,10 +1064,9 @@ int getTransformOrientation_ex(const bContext *C,
ok = true;
}
else {
- int totsel;
-
- totsel = count_bone_select(arm, &arm->bonebase, true);
- if (totsel) {
+ int transformed_len;
+ transformed_len = armature_bone_transflags_update_recursive(arm, &arm->bonebase, true);
+ if (transformed_len) {
/* use channels to get stats */
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 4b6ab2045c0..cb4446deb99 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -21,36 +21,36 @@
* \ingroup edtransform
*/
-#include <stdlib.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
#include <stdio.h>
+#include <stdlib.h>
#include "PIL_time.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_meshdata_types.h" /* Temporary, for snapping to other unselected meshes */
#include "DNA_node_types.h"
-#include "DNA_space_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "DNA_windowmanager_types.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "GPU_immediate.h"
#include "GPU_state.h"
-#include "BKE_layer.h"
-#include "BKE_object.h"
-#include "BKE_anim.h" /* for duplis */
#include "BKE_context.h"
+#include "BKE_duplilist.h"
#include "BKE_editmesh.h"
-#include "BKE_sequencer.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_sequencer.h"
#include "RNA_access.h"
@@ -59,9 +59,9 @@
#include "ED_image.h"
#include "ED_markers.h"
#include "ED_node.h"
+#include "ED_transform_snap_object_context.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
-#include "ED_transform_snap_object_context.h"
#include "DEG_depsgraph.h"
@@ -158,7 +158,7 @@ static bool doForceIncrementSnap(const TransInfo *t)
void drawSnapping(const struct bContext *C, TransInfo *t)
{
- unsigned char col[4], selectedCol[4], activeCol[4];
+ uchar col[4], selectedCol[4], activeCol[4];
if (!activeSnap(t)) {
return;
@@ -283,7 +283,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_NODE) {
if (validSnap(t)) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
TransSnapPoint *p;
float size;
@@ -304,13 +304,13 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
immUniformColor4ubv(col);
}
- ED_node_draw_snap(&ar->v2d, p->co, size, 0, pos);
+ ED_node_draw_snap(&region->v2d, p->co, size, 0, pos);
}
if (t->tsnap.status & POINT_INIT) {
immUniformColor4ubv(activeCol);
- ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos);
+ ED_node_draw_snap(&region->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos);
}
immUnbindProgram();
@@ -373,10 +373,11 @@ void applyProject(TransInfo *t)
copy_v3_v3(iloc, td->ob->obmat[3]);
}
- if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) ==
+ if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) ==
V3D_PROJ_RET_OK) {
if (ED_transform_snap_object_project_view3d(
t->tsnap.object_context,
+ t->depsgraph,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = t->tsnap.modeSelect,
@@ -686,7 +687,7 @@ static void initSnappingMode(TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
if (t->tsnap.object_context == NULL) {
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
- bmain, t->scene, t->depsgraph, 0, t->ar, t->view);
+ bmain, t->scene, 0, t->region, t->view);
ED_transform_snap_object_context_set_editmesh_callbacks(
t->tsnap.object_context,
@@ -847,7 +848,7 @@ eRedrawFlag updateSelectedSnapPoint(TransInfo *t)
for (p = t->tsnap.points.first; p; p = p->next) {
float dist_sq;
- if (ED_view3d_project_float_global(t->ar, p->co, screen_loc, V3D_PROJ_TEST_NOP) !=
+ if (ED_view3d_project_float_global(t->region, p->co, screen_loc, V3D_PROJ_TEST_NOP) !=
V3D_PROJ_RET_OK) {
continue;
}
@@ -936,7 +937,7 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3])
else {
if (t->spacetype == SPACE_VIEW3D) {
if (t->options & CTX_PAINT_CURVE) {
- if (ED_view3d_project_float_global(t->ar, point, point, V3D_PROJ_TEST_NOP) !=
+ if (ED_view3d_project_float_global(t->region, point, point, V3D_PROJ_TEST_NOP) !=
V3D_PROJ_RET_OK) {
zero_v3(point); /* no good answer here... */
}
@@ -1105,10 +1106,10 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
}
else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
- Image *ima = ED_space_image(t->sa->spacedata.first);
+ Image *ima = ED_space_image(t->area->spacedata.first);
float co[2];
- UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
+ UI_view2d_region_to_view(&t->region->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
@@ -1365,6 +1366,7 @@ short snapObjectsTransform(
float *target = (t->tsnap.status & TARGET_INIT) ? t->tsnap.snapTarget : t->center_global;
return ED_transform_snap_object_project_view3d_ex(
t->tsnap.object_context,
+ t->depsgraph,
t->scene->toolsettings->snap_mode,
&(const struct SnapObjectParams){
.snap_select = t->tsnap.modeSelect,
@@ -1389,17 +1391,26 @@ short snapObjectsTransform(
/** \name Peeling
* \{ */
-bool peelObjectsSnapContext(SnapObjectContext *sctx,
- const float mval[2],
- const struct SnapObjectParams *params,
- const bool use_peel_object,
- /* return args */
- float r_loc[3],
- float r_no[3],
- float *r_thickness)
+bool peelObjectsTransform(TransInfo *t,
+ const float mval[2],
+ const bool use_peel_object,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ float *r_thickness)
{
ListBase depths_peel = {0};
- ED_transform_snap_object_project_all_view3d_ex(sctx, params, mval, -1.0f, false, &depths_peel);
+ ED_transform_snap_object_project_all_view3d_ex(
+ t->tsnap.object_context,
+ t->depsgraph,
+ &(const struct SnapObjectParams){
+ .snap_select = t->tsnap.modeSelect,
+ .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ },
+ mval,
+ -1.0f,
+ false,
+ &depths_peel);
if (!BLI_listbase_is_empty(&depths_peel)) {
/* At the moment we only use the hits of the first object */
@@ -1455,26 +1466,6 @@ bool peelObjectsSnapContext(SnapObjectContext *sctx,
return false;
}
-bool peelObjectsTransform(TransInfo *t,
- const float mval[2],
- const bool use_peel_object,
- /* return args */
- float r_loc[3],
- float r_no[3],
- float *r_thickness)
-{
- return peelObjectsSnapContext(t->tsnap.object_context,
- mval,
- &(const struct SnapObjectParams){
- .snap_select = t->tsnap.modeSelect,
- .use_object_edit_cage = (t->flag & T_EDIT) != 0,
- },
- use_peel_object,
- r_loc,
- r_no,
- r_thickness);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -1504,14 +1495,14 @@ static NodeBorder snapNodeBorder(int snap_node_mode)
static bool snapNode(ToolSettings *ts,
SpaceNode *UNUSED(snode),
- ARegion *ar,
+ ARegion *region,
bNode *node,
const int mval[2],
float r_loc[2],
float *r_dist_px,
char *r_node_border)
{
- View2D *v2d = &ar->v2d;
+ View2D *v2d = &region->v2d;
NodeBorder border = snapNodeBorder(ts->snap_node_mode);
bool retval = false;
rcti totr;
@@ -1564,7 +1555,7 @@ static bool snapNode(ToolSettings *ts,
static bool snapNodes(ToolSettings *ts,
SpaceNode *snode,
- ARegion *ar,
+ ARegion *region,
const int mval[2],
eSnapSelect snap_select,
float r_loc[2],
@@ -1578,8 +1569,8 @@ static bool snapNodes(ToolSettings *ts,
*r_node_border = 0;
for (node = ntree->nodes.first; node; node = node->next) {
- if (snapNodeTest(&ar->v2d, node, snap_select)) {
- retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist_px, r_node_border);
+ if (snapNodeTest(&region->v2d, node, snap_select)) {
+ retval |= snapNode(ts, snode, region, node, mval, r_loc, r_dist_px, r_node_border);
}
}
@@ -1590,8 +1581,8 @@ bool snapNodesTransform(
TransInfo *t, const int mval[2], float r_loc[2], float *r_dist_px, char *r_node_border)
{
return snapNodes(t->settings,
- t->sa->spacedata.first,
- t->ar,
+ t->area->spacedata.first,
+ t->region,
mval,
t->tsnap.modeSelect,
r_loc,
@@ -1691,7 +1682,7 @@ void snapSequenceBounds(TransInfo *t, const int mval[2])
}
/* convert to frame range */
- UI_view2d_region_to_view(&t->ar->v2d, mval[0], mval[1], &xmouse, &ymouse);
+ UI_view2d_region_to_view(&t->region->v2d, mval[0], mval[1], &xmouse, &ymouse);
mframe = round_fl_to_int(xmouse);
/* now find the closest sequence */
frame = BKE_sequencer_find_next_prev_edit(t->scene, mframe, SEQ_SIDE_BOTH, true, false, true);
@@ -1723,9 +1714,9 @@ static void applyGridIncrement(
if (use_aspect) {
/* custom aspect for fcurve */
if (t->spacetype == SPACE_GRAPH) {
- View2D *v2d = &t->ar->v2d;
+ View2D *v2d = &t->region->v2d;
Scene *scene = t->scene;
- SpaceGraph *sipo = t->sa->spacedata.first;
+ SpaceGraph *sipo = t->area->spacedata.first;
asp_local[0] = UI_view2d_grid_resolution_x__frames_or_seconds(
v2d, scene, sipo->flag & SIPO_DRAWTIME);
asp_local[1] = UI_view2d_grid_resolution_y__values(v2d);
diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h
index a188e2eb829..c088cf80f0d 100644
--- a/source/blender/editors/transform/transform_snap.h
+++ b/source/blender/editors/transform/transform_snap.h
@@ -35,14 +35,6 @@ bool peelObjectsTransform(struct TransInfo *t,
float r_loc[3],
float r_no[3],
float *r_thickness);
-bool peelObjectsSnapContext(struct SnapObjectContext *sctx,
- const float mval[2],
- const struct SnapObjectParams *params,
- const bool use_peel_object,
- /* return args */
- float r_loc[3],
- float r_no[3],
- float *r_thickness);
short snapObjectsTransform(struct TransInfo *t,
const float mval[2],
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 63b9eb3937a..2cfeedbb346 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -19,50 +19,44 @@
*/
#include <stdlib.h>
-#include <math.h>
-#include <float.h>
-#include <stdio.h>
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
-#include "BLI_kdopbvh.h"
-#include "BLI_memarena.h"
#include "BLI_ghash.h"
+#include "BLI_kdopbvh.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
#include "BLI_utildefines.h"
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
-#include "BKE_bvhutils.h"
#include "BKE_armature.h"
+#include "BKE_bvhutils.h"
#include "BKE_curve.h"
-#include "BKE_object.h"
-#include "BKE_anim.h" /* for duplis */
+#include "BKE_duplilist.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
#include "BKE_main.h"
-#include "BKE_tracking.h"
-#include "BKE_context.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
+#include "BKE_object.h"
+#include "BKE_tracking.h"
-#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "ED_transform.h"
+#include "ED_armature.h"
#include "ED_transform_snap_object_context.h"
#include "ED_view3d.h"
-#include "ED_armature.h"
-#include "transform.h"
+#include "ED_transform.h"
/* -------------------------------------------------------------------- */
/** \name Internal Data Types
@@ -92,30 +86,32 @@ typedef struct SnapObjectData {
SNAP_MESH = 1,
SNAP_EDIT_MESH,
} type;
-} SnapObjectData;
-
-typedef struct SnapObjectData_Mesh {
- SnapObjectData sd;
- BVHTreeFromMesh treedata;
- const struct MPoly *poly;
- BVHTree *bvhtree[2]; /* from loose verts and from loose edges */
- uint has_looptris : 1;
- uint has_loose_edge : 1;
- uint has_loose_vert : 1;
-} SnapObjectData_Mesh;
+ BVHTree *bvhtree[2]; /* MESH: loose edges, loose verts
+ * EDIT_MESH: verts, edges. */
+ bool cached[2];
-typedef struct SnapObjectData_EditMesh {
- SnapObjectData sd;
- BVHTreeFromEditMesh *bvh_trees[3];
- float min[3], max[3];
-
-} SnapObjectData_EditMesh;
+ union {
+ struct {
+ /* SNAP_MESH */
+ BVHTreeFromMesh treedata_mesh;
+ const struct MPoly *poly;
+ uint has_looptris : 1;
+ uint has_loose_edge : 1;
+ uint has_loose_vert : 1;
+ };
+ struct {
+ /* SNAP_EDIT_MESH */
+ BVHTreeFromEditMesh treedata_editmesh;
+ float min[3], max[3];
+ struct LinkNode **bvh_cache_p;
+ };
+ };
+} SnapObjectData;
struct SnapObjectContext {
Main *bmain;
Scene *scene;
- Depsgraph *depsgraph;
int flag;
@@ -124,7 +120,7 @@ struct SnapObjectContext {
bool use_v3d;
struct {
const struct View3D *v3d;
- const struct ARegion *ar;
+ const struct ARegion *region;
} v3d_data;
/* Object -> SnapObjectData map */
@@ -149,7 +145,7 @@ struct SnapObjectContext {
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Common Utilities
+/** \name Snap Object Data
* \{ */
/**
@@ -166,6 +162,45 @@ static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3])
}
}
+static void snap_object_data_mesh_clear(SnapObjectData *sod)
+{
+ BLI_assert(sod->type == SNAP_MESH);
+ for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
+ if (!sod->cached[i]) {
+ BLI_bvhtree_free(sod->bvhtree[i]);
+ }
+ sod->bvhtree[i] = NULL;
+ }
+ free_bvhtree_from_mesh(&sod->treedata_mesh);
+}
+
+static void snap_object_data_editmesh_clear(SnapObjectData *sod)
+{
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+ for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
+ if (!sod->cached[i]) {
+ BLI_bvhtree_free(sod->bvhtree[i]);
+ }
+ sod->bvhtree[i] = NULL;
+ }
+ free_bvhtree_from_editmesh(&sod->treedata_editmesh);
+}
+
+static void snap_object_data_clear(SnapObjectData *sod)
+{
+ switch (sod->type) {
+ case SNAP_MESH: {
+ snap_object_data_mesh_clear(sod);
+ break;
+ }
+ case SNAP_EDIT_MESH: {
+ snap_object_data_editmesh_clear(sod);
+ break;
+ }
+ }
+ memset(&sod->type, 0x0, sizeof(*sod) - offsetof(SnapObjectData, type));
+}
+
static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob)
{
SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
@@ -181,29 +216,55 @@ static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *
return sod;
}
-static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
+static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
{
+ SnapObjectData *sod;
void **sod_p;
+ bool init = false;
+
if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH);
+ sod = *sod_p;
+ if (sod->type != SNAP_MESH) {
+ snap_object_data_clear(sod);
+ init = true;
+ }
}
else {
- SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_MESH;
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ init = true;
+ }
+
+ if (init) {
+ sod->type = SNAP_MESH;
/* start assuming that it has each of these element types */
sod->has_looptris = true;
sod->has_loose_edge = true;
sod->has_loose_vert = true;
}
- return *sod_p;
+ return sod;
}
-static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
- Object *ob,
- BMEditMesh *em)
+static struct LinkNode **snap_object_data_editmesh_bvh_cache_get(Object *ob)
{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ if (em->mesh_eval_final) {
+ return &em->mesh_eval_final->runtime.bvh_cache;
+ }
+ if (em->mesh_eval_cage) {
+ return &em->mesh_eval_cage->runtime.bvh_cache;
+ }
+
+ return &((Mesh *)ob->data)->runtime.bvh_cache;
+}
+
+static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
+ Object *ob,
+ BMEditMesh *em)
+{
+ SnapObjectData *sod;
void **sod_p;
+ bool init = false, init_min_max = true, clear_cache = false;
{
/* Use object-data as the key in ghash since the editmesh
@@ -221,18 +282,83 @@ static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext
}
if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH);
+ sod = *sod_p;
+ bool clear = false;
+ /* Check if the geometry has changed. */
+ if (sod->type != SNAP_EDIT_MESH) {
+ clear = true;
+ }
+ else if (sod->treedata_editmesh.em != em) {
+ clear_cache = true;
+ init = true;
+ }
+ else if (sod->bvh_cache_p) {
+ if (sod->bvh_cache_p != snap_object_data_editmesh_bvh_cache_get(ob)) {
+ clear_cache = true;
+ init = true;
+ }
+ else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached &&
+ !bvhcache_has_tree(*sod->bvh_cache_p, sod->treedata_editmesh.tree)) {
+ /* The tree is owned by the EditMesh and may have been freed since we last used! */
+ clear = true;
+ }
+ else if (sod->bvhtree[0] && sod->cached[0] &&
+ !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[0])) {
+ /* The tree is owned by the EditMesh and may have been freed since we last used! */
+ clear = true;
+ }
+ else if (sod->bvhtree[1] && sod->cached[1] &&
+ !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[1])) {
+ /* The tree is owned by the EditMesh and may have been freed since we last used! */
+ clear = true;
+ }
+ }
+
+ if (clear) {
+ snap_object_data_clear(sod);
+ init = true;
+ }
}
else {
- SnapObjectData_EditMesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena,
- sizeof(*sod));
- sod->sd.type = SNAP_EDIT_MESH;
- bm_mesh_minmax(em->bm, sod->min, sod->max);
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ init = true;
+ }
+
+ if (init) {
+ sod->type = SNAP_EDIT_MESH;
+ sod->treedata_editmesh.em = em;
+
+ if (clear_cache) {
+ /* Only init min and max when you have a non-custom bvhtree pending. */
+ init_min_max = false;
+ if (sod->treedata_editmesh.cached) {
+ sod->treedata_editmesh.tree = NULL;
+ init_min_max = true;
+ }
+ for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
+ if (sod->cached[i]) {
+ sod->bvhtree[i] = NULL;
+ init_min_max = true;
+ }
+ }
+ }
+
+ if (init_min_max) {
+ bm_mesh_minmax(em->bm, sod->min, sod->max);
+ }
+
+ sod->bvh_cache_p = snap_object_data_editmesh_bvh_cache_get(ob);
}
- return *sod_p;
+ return sod;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Iterator
+ * \{ */
+
typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
bool is_obedit,
bool use_backface_culling,
@@ -247,11 +373,12 @@ typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
* \param snap_select: from enum #eSnapSelect.
*/
static void iter_snap_objects(SnapObjectContext *sctx,
+ Depsgraph *depsgraph,
const struct SnapObjectParams *params,
IterSnapObjsCallback sob_callback,
void *data)
{
- ViewLayer *view_layer = DEG_get_input_view_layer(sctx->depsgraph);
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
const View3D *v3d = sctx->v3d_data.v3d;
const eSnapSelect snap_select = params->snap_select;
const bool use_object_edit_cage = params->use_object_edit_cage;
@@ -282,10 +409,10 @@ static void iter_snap_objects(SnapObjectContext *sctx,
}
}
- Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object);
+ Object *obj_eval = DEG_get_evaluated_object(depsgraph, base->object);
if (obj_eval->transflag & OB_DUPLI) {
DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
+ ListBase *lb = object_duplilist(depsgraph, sctx->scene, obj_eval);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
sob_callback(
sctx, use_object_edit_cage, use_backface_culling, dupli_ob->ob, dupli_ob->mat, data);
@@ -320,7 +447,7 @@ struct RayCastAll_Data {
float local_scale;
Object *ob;
- unsigned int ob_uuid;
+ uint ob_uuid;
/* output data */
ListBase *hit_list;
@@ -333,7 +460,7 @@ static struct SnapObjectHitDepth *hit_depth_create(const float depth,
int index,
Object *ob,
const float obmat[4][4],
- unsigned int ob_uuid)
+ uint ob_uuid)
{
struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
@@ -459,7 +586,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
Object *ob,
Mesh *me,
const float obmat[4][4],
- const unsigned int ob_index,
+ const uint ob_index,
bool use_hide,
bool use_backface_culling,
/* read/write args */
@@ -516,9 +643,9 @@ static bool raycastMesh(SnapObjectContext *sctx,
len_diff = 0.0f;
}
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+ SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob);
- BVHTreeFromMesh *treedata = &sod->treedata;
+ BVHTreeFromMesh *treedata = &sod->treedata_mesh;
/* The tree is owned by the Mesh and may have been freed since we last used. */
if (treedata->tree) {
@@ -634,7 +761,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
Object *ob,
BMEditMesh *em,
const float obmat[4][4],
- const unsigned int ob_index,
+ const uint ob_index,
bool use_backface_culling,
/* read/write args */
float *ray_depth,
@@ -668,7 +795,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
local_depth *= local_scale;
}
- SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em);
+ SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em);
/* Test BoundBox */
@@ -690,30 +817,18 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
len_diff = 0.0f;
}
- if (sod->bvh_trees[2] == NULL) {
- sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(BVHTreeFromEditMesh));
- }
-
- BVHTreeFromEditMesh *treedata = sod->bvh_trees[2];
-
- BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache;
-
- if (sctx->callbacks.edit_mesh.test_face_fn == NULL) {
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (treedata->tree && !bvhcache_has_tree(*em_bvh_cache, treedata->tree)) {
- free_bvhtree_from_editmesh(treedata);
- }
- }
+ BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh;
if (treedata->tree == NULL) {
- /* Get original version of the edit_mesh. */
- BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+ /* Operators only update the editmesh looptris of the original mesh. */
+ BLI_assert(sod->treedata_editmesh.em == BKE_editmesh_from_object(DEG_get_original_object(ob)));
+ em = sod->treedata_editmesh.em;
if (sctx->callbacks.edit_mesh.test_face_fn) {
- BMesh *bm = em_orig->bm;
- BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em_orig->tottri);
+ BMesh *bm = em->bm;
+ BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em->tottri);
- BLI_bitmap *elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__);
+ BLI_bitmap *elem_mask = BLI_BITMAP_NEW(em->tottri, __func__);
int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
bm,
elem_mask,
@@ -721,14 +836,14 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_looptri_ex(
- treedata, em_orig, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL);
+ treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL);
MEM_freeN(elem_mask);
}
else {
/* Only cache if bvhtree is created without a mask.
* This helps keep a standardized bvhtree in cache. */
- BKE_bvhtree_from_editmesh_get(treedata, em_orig, 4, BVHTREE_FROM_EM_LOOPTRI, em_bvh_cache);
+ BKE_bvhtree_from_editmesh_get(treedata, em, 4, BVHTREE_FROM_EM_LOOPTRI, sod->bvh_cache_p);
}
if (treedata->tree == NULL) {
@@ -795,10 +910,9 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
retval = true;
if (r_index) {
- /* Get original version of the edit_mesh. */
- BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+ em = sod->treedata_editmesh.em;
- *r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f);
+ *r_index = BM_elem_index_get(em->looptris[hit.index][0]->f);
}
}
}
@@ -817,7 +931,7 @@ static bool raycastObj(SnapObjectContext *sctx,
const float ray_dir[3],
Object *ob,
const float obmat[4][4],
- const unsigned int ob_index,
+ const uint ob_index,
bool use_obedit,
bool use_occlusion_test,
bool use_backface_culling,
@@ -850,13 +964,14 @@ static bool raycastObj(SnapObjectContext *sctx,
Mesh *me = ob->data;
bool use_hide = false;
if (BKE_object_is_in_editmode(ob)) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
if (use_obedit) {
+ /* Operators only update the editmesh looptris of the original mesh. */
+ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
retval = raycastEditMesh(sctx,
ray_start,
ray_dir,
ob,
- em,
+ em_orig,
obmat,
ob_index,
use_backface_culling,
@@ -867,9 +982,12 @@ static bool raycastObj(SnapObjectContext *sctx,
r_hit_list);
break;
}
- else if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
- use_hide = true;
+ else {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ if (em->mesh_eval_final) {
+ me = em->mesh_eval_final;
+ use_hide = true;
+ }
}
}
retval = raycastMesh(sctx,
@@ -891,12 +1009,13 @@ static bool raycastObj(SnapObjectContext *sctx,
case OB_CURVE:
case OB_SURF:
case OB_FONT: {
- if (ob->runtime.mesh_eval) {
+ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ if (mesh_eval) {
retval = raycastMesh(sctx,
ray_start,
ray_dir,
ob,
- ob->runtime.mesh_eval,
+ mesh_eval,
obmat,
ob_index,
false,
@@ -927,7 +1046,7 @@ static bool raycastObj(SnapObjectContext *sctx,
struct RaycastObjUserData {
const float *ray_start;
const float *ray_dir;
- unsigned int ob_index;
+ uint ob_index;
/* read/write args */
float *ray_depth;
/* return args */
@@ -997,6 +1116,7 @@ static void raycast_obj_cb(SnapObjectContext *sctx,
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
static bool raycastObjects(SnapObjectContext *sctx,
+ Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float ray_start[3],
const float ray_dir[3],
@@ -1025,7 +1145,7 @@ static bool raycastObjects(SnapObjectContext *sctx,
.ret = false,
};
- iter_snap_objects(sctx, params, raycast_obj_cb, &data);
+ iter_snap_objects(sctx, depsgraph, params, raycast_obj_cb, &data);
return data.ret;
}
@@ -1037,7 +1157,7 @@ static bool raycastObjects(SnapObjectContext *sctx,
* \{ */
/* Test BoundBox */
-static bool snap_bound_box_check_dist(float min[3],
+static bool snap_bound_box_check_dist(const float min[3],
const float max[3],
const float lpmat[4][4],
const float win_size[2],
@@ -1107,7 +1227,7 @@ static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTree
const MLoopTri *lt = &data->looptri[index];
for (int j = 2, j_next = 0; j_next < 3; j = j_next++) {
const MEdge *ed = &medge[mloop[lt->tri[j]].e];
- unsigned int tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
+ uint tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) && ELEM(ed->v2, tri_edge[0], tri_edge[1])) {
// printf("real edge found\n");
v_index[j] = mloop[lt->tri[j]].e;
@@ -1392,7 +1512,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
BVHTreeNearest nearest = {
.index = -1,
- .dist_sq = SQUARE(*dist_px),
+ .dist_sq = square_f(*dist_px),
};
SnapObjectData *sod = snap_object_data_lookup(sctx, ob);
@@ -1400,14 +1520,14 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
BLI_assert(sod != NULL);
if (sod->type == SNAP_MESH) {
- BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata;
+ BVHTreeFromMesh *treedata = &sod->treedata_mesh;
nearest2d.userdata = treedata;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
- const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index];
+ const MPoly *mp = &sod->poly[*r_index];
const MLoop *ml = &treedata->loop[mp->loopstart];
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
elem = SCE_SNAP_MODE_EDGE;
@@ -1435,7 +1555,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
}
else {
BLI_assert(sod->type == SNAP_EDIT_MESH);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMEditMesh *em = sod->treedata_editmesh.em;
nearest2d.userdata = em;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
@@ -1525,14 +1645,14 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
nearest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
nearest2d.use_backface_culling = use_backface_culling;
if (sod->type == SNAP_MESH) {
- nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata;
+ nearest2d.userdata = &sod->treedata_mesh;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
}
else {
BLI_assert(sod->type == SNAP_EDIT_MESH);
- nearest2d.userdata = BKE_editmesh_from_object(ob);
+ nearest2d.userdata = sod->treedata_editmesh.em;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
@@ -1557,7 +1677,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
BVHTreeNearest nearest = {
.index = -1,
- .dist_sq = SQUARE(original_dist_px),
+ .dist_sq = square_f(original_dist_px),
};
float lambda;
@@ -1690,7 +1810,7 @@ static short snapArmature(SnapData *snapdata,
return retval;
}
- float lpmat[4][4], dist_px_sq = SQUARE(*dist_px);
+ float lpmat[4][4], dist_px_sq = square_f(*dist_px);
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
struct DistProjectedAABBPrecalc neasrest_precalc;
@@ -1718,7 +1838,7 @@ static short snapArmature(SnapData *snapdata,
bArmature *arm = ob->data;
if (arm->edbo) {
- for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
if (eBone->layer & arm->layer) {
/* skip hidden or moving (selected) bones */
if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
@@ -1761,7 +1881,7 @@ static short snapArmature(SnapData *snapdata,
}
}
else if (ob->pose && ob->pose->chanbase.first) {
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
Bone *bone = pchan->bone;
/* skip hidden bones */
if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
@@ -1837,7 +1957,7 @@ static short snapCurve(SnapData *snapdata,
}
Curve *cu = ob->data;
- float dist_px_sq = SQUARE(*dist_px);
+ float dist_px_sq = square_f(*dist_px);
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
@@ -1998,7 +2118,7 @@ static short snapEmpty(SnapData *snapdata,
}
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- float dist_px_sq = SQUARE(*dist_px);
+ float dist_px_sq = square_f(*dist_px);
float co[3];
copy_v3_v3(co, obmat[3]);
if (test_projected_vert_dist(&neasrest_precalc,
@@ -2040,7 +2160,7 @@ static short snapCamera(const SnapObjectContext *sctx,
Scene *scene = sctx->scene;
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- float dist_px_sq = SQUARE(*dist_px);
+ float dist_px_sq = square_f(*dist_px);
float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
@@ -2055,7 +2175,7 @@ static short snapCamera(const SnapObjectContext *sctx,
tracking = &clip->tracking;
- BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
+ BKE_tracking_get_camera_object_matrix(object, orig_camera_mat);
invert_m4_m4(orig_camera_imat, orig_camera_mat);
invert_m4_m4(imat, obmat);
@@ -2151,7 +2271,7 @@ static short snapMesh(SnapObjectContext *sctx,
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- float dist_px_sq = SQUARE(*dist_px);
+ float dist_px_sq = square_f(*dist_px);
/* Test BoundBox */
BoundBox *bb = BKE_mesh_boundbox_get(ob);
@@ -2160,27 +2280,23 @@ static short snapMesh(SnapObjectContext *sctx,
return 0;
}
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+ SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob);
BVHTreeFromMesh *treedata, dummy_treedata;
- BVHTree **bvhtree;
- treedata = &sod->treedata;
- bvhtree = sod->bvhtree;
+ treedata = &sod->treedata_mesh;
/* The tree is owned by the Mesh and may have been freed since we last used! */
- if ((sod->has_looptris && treedata->tree &&
- !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) ||
- (sod->has_loose_edge && bvhtree[0] &&
- !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) ||
- (sod->has_loose_vert && bvhtree[1] &&
- !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]))) {
- BLI_assert(!treedata->tree || !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree));
- BLI_assert(!bvhtree[0] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0]));
- BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]));
-
+ if (treedata->cached && treedata->tree &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
free_bvhtree_from_mesh(treedata);
- bvhtree[0] = NULL;
- bvhtree[1] = NULL;
+ }
+ if (sod->cached[0] && sod->bvhtree[0] &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[0])) {
+ sod->bvhtree[0] = NULL;
+ }
+ if (sod->cached[1] && sod->bvhtree[1] &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[1])) {
+ sod->bvhtree[1] = NULL;
}
if (sod->has_looptris && treedata->tree == NULL) {
@@ -2191,9 +2307,10 @@ static short snapMesh(SnapObjectContext *sctx,
treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
}
}
- if (sod->has_loose_edge && bvhtree[0] == NULL) {
- bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
- sod->has_loose_edge = bvhtree[0] != NULL;
+ if (sod->has_loose_edge && sod->bvhtree[0] == NULL) {
+ sod->bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
+ sod->has_loose_edge = sod->bvhtree[0] != NULL;
+ sod->cached[0] = dummy_treedata.cached;
if (sod->has_loose_edge) {
BLI_assert(treedata->vert_allocated == false);
@@ -2206,9 +2323,10 @@ static short snapMesh(SnapObjectContext *sctx,
}
}
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (sod->has_loose_vert && bvhtree[1] == NULL) {
- bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
- sod->has_loose_vert = bvhtree[1] != NULL;
+ if (sod->has_loose_vert && sod->bvhtree[1] == NULL) {
+ sod->bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
+ sod->has_loose_vert = sod->bvhtree[1] != NULL;
+ sod->cached[1] = dummy_treedata.cached;
if (sod->has_loose_vert) {
BLI_assert(treedata->vert_allocated == false);
@@ -2226,7 +2344,7 @@ static short snapMesh(SnapObjectContext *sctx,
if (treedata->vert_allocated == false) {
treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
}
- if (treedata->tree || bvhtree[0]) {
+ if (treedata->tree || sod->bvhtree[0]) {
if (treedata->edge_allocated == false) {
/* If raycast has been executed before, `treedata->edge` can be NULL. */
treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
@@ -2263,9 +2381,9 @@ static short snapMesh(SnapObjectContext *sctx,
mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
}
- if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
/* snap to loose verts */
- BLI_bvhtree_find_nearest_projected(bvhtree[1],
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[1],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2279,9 +2397,9 @@ static short snapMesh(SnapObjectContext *sctx,
}
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (bvhtree[0]) {
+ if (sod->bvhtree[0]) {
/* snap to loose edges */
- BLI_bvhtree_find_nearest_projected(bvhtree[0],
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2311,9 +2429,9 @@ static short snapMesh(SnapObjectContext *sctx,
}
else {
BLI_assert(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX);
- if (bvhtree[0]) {
- /* snap to loose edges */
- BLI_bvhtree_find_nearest_projected(bvhtree[0],
+ if (sod->bvhtree[0]) {
+ /* snap to loose edge verts */
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2325,7 +2443,7 @@ static short snapMesh(SnapObjectContext *sctx,
}
if (treedata->tree) {
- /* snap to looptris */
+ /* snap to looptri verts */
BLI_bvhtree_find_nearest_projected(treedata->tree,
lpmat,
snapdata->win_size,
@@ -2388,17 +2506,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
}
}
- BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL;
-
- BLI_assert(BKE_object_get_pre_modified_mesh(ob) == BKE_object_get_pre_modified_mesh(ob));
- UNUSED_VARS_NDEBUG(ob);
-
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- float dist_px_sq = SQUARE(*dist_px);
+ float dist_px_sq = square_f(*dist_px);
- SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em);
+ SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em);
/* Test BoundBox */
@@ -2408,22 +2521,10 @@ static short snapEditMesh(SnapObjectContext *sctx,
return 0;
}
- BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache;
-
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (sod->bvh_trees[0] == NULL) {
- sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
- }
- treedata_vert = sod->bvh_trees[0];
-
- if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) {
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (treedata_vert->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_vert->tree)) {
- free_bvhtree_from_editmesh(treedata_vert);
- }
- }
+ BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]};
- if (treedata_vert->tree == NULL) {
+ if (treedata.tree == NULL) {
BLI_bitmap *verts_mask = NULL;
int verts_num_active = -1;
if (sctx->callbacks.edit_mesh.test_vert_fn) {
@@ -2436,29 +2537,21 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_verts_ex(
- treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL);
+ &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL);
MEM_freeN(verts_mask);
}
else {
- BKE_bvhtree_from_editmesh_get(treedata_vert, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache);
+ BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, sod->bvh_cache_p);
}
+ sod->bvhtree[0] = treedata.tree;
+ sod->cached[0] = treedata.cached;
}
}
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (sod->bvh_trees[1] == NULL) {
- sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
- }
- treedata_edge = sod->bvh_trees[1];
-
- if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) {
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (treedata_edge->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_edge->tree)) {
- free_bvhtree_from_editmesh(treedata_edge);
- }
- }
+ BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]};
- if (treedata_edge->tree == NULL) {
+ if (treedata.tree == NULL) {
BLI_bitmap *edges_mask = NULL;
int edges_num_active = -1;
if (sctx->callbacks.edit_mesh.test_edge_fn) {
@@ -2471,12 +2564,14 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_edges_ex(
- treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL);
+ &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL);
MEM_freeN(edges_mask);
}
else {
- BKE_bvhtree_from_editmesh_get(treedata_edge, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache);
+ BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, sod->bvh_cache_p);
}
+ sod->bvhtree[1] = treedata.tree;
+ sod->cached[1] = treedata.cached;
}
}
@@ -2502,10 +2597,10 @@ static short snapEditMesh(SnapObjectContext *sctx,
mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
}
- if (treedata_vert && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ if (sod->bvhtree[0] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- BLI_bvhtree_find_nearest_projected(treedata_vert->tree,
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2516,12 +2611,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
&nearest2d);
}
- if (treedata_edge && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) {
+ if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) {
int last_index = nearest.index;
nearest.index = -1;
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
BM_mesh_elem_index_ensure(em->bm, BM_EDGE | BM_VERT);
- BLI_bvhtree_find_nearest_projected(treedata_edge->tree,
+ BLI_bvhtree_find_nearest_projected(sod->bvhtree[1],
lpmat,
snapdata->win_size,
snapdata->mval,
@@ -2588,14 +2683,26 @@ static short snapObject(SnapObjectContext *sctx,
case OB_MESH: {
Mesh *me = ob->data;
if (BKE_object_is_in_editmode(ob)) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
if (use_obedit) {
- retval = snapEditMesh(
- sctx, snapdata, ob, em, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index);
+ /* Operators only update the editmesh looptris of the original mesh. */
+ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+ retval = snapEditMesh(sctx,
+ snapdata,
+ ob,
+ em_orig,
+ obmat,
+ use_backface_culling,
+ dist_px,
+ r_loc,
+ r_no,
+ r_index);
break;
}
- else if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
+ else {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ if (em->mesh_eval_final) {
+ me = em->mesh_eval_final;
+ }
}
}
else if (ob->dt == OB_BOUNDBOX) {
@@ -2615,11 +2722,12 @@ static short snapObject(SnapObjectContext *sctx,
break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */
case OB_SURF:
case OB_FONT: {
- if (ob->runtime.mesh_eval) {
+ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ if (mesh_eval) {
retval |= snapMesh(sctx,
snapdata,
ob,
- ob->runtime.mesh_eval,
+ mesh_eval,
obmat,
use_backface_culling,
dist_px,
@@ -2721,6 +2829,7 @@ static void sanp_obj_cb(SnapObjectContext *sctx,
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
*/
static short snapObjectsRay(SnapObjectContext *sctx,
+ Depsgraph *depsgraph,
SnapData *snapdata,
const struct SnapObjectParams *params,
/* read/write args */
@@ -2743,7 +2852,7 @@ static short snapObjectsRay(SnapObjectContext *sctx,
.ret = 0,
};
- iter_snap_objects(sctx, params, sanp_obj_cb, &data);
+ iter_snap_objects(sctx, depsgraph, params, sanp_obj_cb, &data);
return data.ret;
}
@@ -2754,10 +2863,7 @@ static short snapObjectsRay(SnapObjectContext *sctx,
/** \name Public Object Snapping API
* \{ */
-SnapObjectContext *ED_transform_snap_object_context_create(Main *bmain,
- Scene *scene,
- Depsgraph *depsgraph,
- int flag)
+SnapObjectContext *ED_transform_snap_object_context_create(Main *bmain, Scene *scene, int flag)
{
SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
@@ -2765,7 +2871,6 @@ SnapObjectContext *ED_transform_snap_object_context_create(Main *bmain,
sctx->bmain = bmain;
sctx->scene = scene;
- sctx->depsgraph = depsgraph;
sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
/* Initialize as needed (edit-mode only). */
@@ -2777,16 +2882,15 @@ SnapObjectContext *ED_transform_snap_object_context_create(Main *bmain,
SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain,
Scene *scene,
- Depsgraph *depsgraph,
int flag,
/* extra args for view3d */
- const ARegion *ar,
+ const ARegion *region,
const View3D *v3d)
{
- SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, depsgraph, flag);
+ SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, flag);
sctx->use_v3d = true;
- sctx->v3d_data.ar = ar;
+ sctx->v3d_data.region = region;
sctx->v3d_data.v3d = v3d;
return sctx;
@@ -2794,24 +2898,8 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain,
static void snap_object_data_free(void *sod_v)
{
- switch (((SnapObjectData *)sod_v)->type) {
- case SNAP_MESH: {
- SnapObjectData_Mesh *sod = sod_v;
- if (sod->treedata.tree) {
- free_bvhtree_from_mesh(&sod->treedata);
- }
- break;
- }
- case SNAP_EDIT_MESH: {
- SnapObjectData_EditMesh *sod = sod_v;
- for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
- if (sod->bvh_trees[i]) {
- free_bvhtree_from_editmesh(sod->bvh_trees[i]);
- }
- }
- break;
- }
- }
+ SnapObjectData *sod = sod_v;
+ snap_object_data_clear(sod);
}
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
@@ -2840,6 +2928,7 @@ void ED_transform_snap_object_context_set_editmesh_callbacks(
}
bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx,
+ Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float ray_start[3],
const float ray_normal[3],
@@ -2850,8 +2939,18 @@ bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx,
Object **r_ob,
float r_obmat[4][4])
{
- return raycastObjects(
- sctx, params, ray_start, ray_normal, ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
+ return raycastObjects(sctx,
+ depsgraph,
+ params,
+ ray_start,
+ ray_normal,
+ ray_depth,
+ r_loc,
+ r_no,
+ r_index,
+ r_ob,
+ r_obmat,
+ NULL);
}
/**
@@ -2862,6 +2961,7 @@ bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx,
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
+ Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float ray_start[3],
const float ray_normal[3],
@@ -2877,8 +2977,18 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
float ray_depth_prev = ray_depth;
#endif
- bool retval = raycastObjects(
- sctx, params, ray_start, ray_normal, &ray_depth, NULL, NULL, NULL, NULL, NULL, r_hit_list);
+ bool retval = raycastObjects(sctx,
+ depsgraph,
+ params,
+ ray_start,
+ ray_normal,
+ &ray_depth,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ r_hit_list);
/* meant to be readonly for 'all' hits, ensure it is */
#ifdef DEBUG
@@ -2900,6 +3010,7 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
* \return Snap success
*/
static bool transform_snap_context_project_ray_impl(SnapObjectContext *sctx,
+ Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float ray_start[3],
const float ray_normal[3],
@@ -2911,12 +3022,13 @@ static bool transform_snap_context_project_ray_impl(SnapObjectContext *sctx,
/* try snap edge, then face if it fails */
ret = ED_transform_snap_object_project_ray_ex(
- sctx, params, ray_start, ray_normal, ray_depth, r_co, r_no, NULL, NULL, NULL);
+ sctx, depsgraph, params, ray_start, ray_normal, ray_depth, r_co, r_no, NULL, NULL, NULL);
return ret;
}
bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx,
+ Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float ray_origin[3],
const float ray_direction[3],
@@ -2931,12 +3043,13 @@ bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx,
}
return transform_snap_context_project_ray_impl(
- sctx, params, ray_origin, ray_direction, ray_depth, r_co, r_no);
+ sctx, depsgraph, params, ray_origin, ray_direction, ray_depth, r_co, r_no);
}
static short transform_snap_context_project_view3d_mixed_impl(
SnapObjectContext *sctx,
- const unsigned short snap_to_flag,
+ Depsgraph *depsgraph,
+ const ushort snap_to_flag,
const struct SnapObjectParams *params,
const float mval[2],
const float prev_co[3],
@@ -2958,15 +3071,15 @@ static short transform_snap_context_project_view3d_mixed_impl(
float loc[3], no[3], obmat[4][4];
int index = -1;
- const ARegion *ar = sctx->v3d_data.ar;
- const RegionView3D *rv3d = ar->regiondata;
+ const ARegion *region = sctx->v3d_data.region;
+ const RegionView3D *rv3d = region->regiondata;
bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(sctx->v3d_data.v3d);
if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) {
float ray_start[3], ray_normal[3];
- if (!ED_view3d_win_to_ray_clipped_ex(sctx->depsgraph,
- sctx->v3d_data.ar,
+ if (!ED_view3d_win_to_ray_clipped_ex(depsgraph,
+ sctx->v3d_data.region,
sctx->v3d_data.v3d,
mval,
NULL,
@@ -2978,8 +3091,18 @@ static short transform_snap_context_project_view3d_mixed_impl(
float dummy_ray_depth = BVH_RAYCAST_DIST_MAX;
- has_hit = raycastObjects(
- sctx, params, ray_start, ray_normal, &dummy_ray_depth, loc, no, &index, &ob, obmat, NULL);
+ has_hit = raycastObjects(sctx,
+ depsgraph,
+ params,
+ ray_start,
+ ray_normal,
+ &dummy_ray_depth,
+ loc,
+ no,
+ &index,
+ &ob,
+ obmat,
+ NULL);
if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
retval = SCE_SNAP_MODE_FACE;
@@ -3007,8 +3130,8 @@ static short transform_snap_context_project_view3d_mixed_impl(
SnapData snapdata;
copy_m4_m4(snapdata.pmat, rv3d->persmat);
- snapdata.win_size[0] = ar->winx;
- snapdata.win_size[1] = ar->winy;
+ snapdata.win_size[0] = region->winx;
+ snapdata.win_size[1] = region->winy;
copy_v2_v2(snapdata.mval, mval);
snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
@@ -3053,7 +3176,8 @@ static short transform_snap_context_project_view3d_mixed_impl(
snapdata.has_occlusion_plane = true;
}
- elem_test = snapObjectsRay(sctx, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat);
+ elem_test = snapObjectsRay(
+ sctx, depsgraph, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat);
if (elem_test) {
elem = elem_test;
}
@@ -3100,7 +3224,8 @@ static short transform_snap_context_project_view3d_mixed_impl(
}
short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
- const unsigned short snap_to,
+ Depsgraph *depsgraph,
+ const ushort snap_to,
const struct SnapObjectParams *params,
const float mval[2],
const float prev_co[3],
@@ -3111,8 +3236,18 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
Object **r_ob,
float r_obmat[4][4])
{
- return transform_snap_context_project_view3d_mixed_impl(
- sctx, snap_to, params, mval, prev_co, dist_px, r_loc, r_no, r_index, r_ob, r_obmat);
+ return transform_snap_context_project_view3d_mixed_impl(sctx,
+ depsgraph,
+ snap_to,
+ params,
+ mval,
+ prev_co,
+ dist_px,
+ r_loc,
+ r_no,
+ r_index,
+ r_ob,
+ r_obmat);
}
/**
@@ -3129,7 +3264,8 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
* \return Snap success
*/
bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
- const unsigned short snap_to,
+ Depsgraph *depsgraph,
+ const ushort snap_to,
const struct SnapObjectParams *params,
const float mval[2],
const float prev_co[3],
@@ -3137,14 +3273,25 @@ bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
float r_loc[3],
float r_no[3])
{
- return ED_transform_snap_object_project_view3d_ex(
- sctx, snap_to, params, mval, prev_co, dist_px, r_loc, r_no, NULL, NULL, NULL) != 0;
+ return ED_transform_snap_object_project_view3d_ex(sctx,
+ depsgraph,
+ snap_to,
+ params,
+ mval,
+ prev_co,
+ dist_px,
+ r_loc,
+ r_no,
+ NULL,
+ NULL,
+ NULL) != 0;
}
/**
* see: #ED_transform_snap_object_project_ray_all
*/
bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
+ Depsgraph *depsgraph,
const struct SnapObjectParams *params,
const float mval[2],
float ray_depth,
@@ -3153,8 +3300,8 @@ bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
{
float ray_start[3], ray_normal[3];
- if (!ED_view3d_win_to_ray_clipped_ex(sctx->depsgraph,
- sctx->v3d_data.ar,
+ if (!ED_view3d_win_to_ray_clipped_ex(depsgraph,
+ sctx->v3d_data.region,
sctx->v3d_data.v3d,
mval,
NULL,
@@ -3165,7 +3312,7 @@ bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
}
return ED_transform_snap_object_project_ray_all(
- sctx, params, ray_start, ray_normal, ray_depth, sort, r_hit_list);
+ sctx, depsgraph, params, ray_start, ray_normal, ray_depth, sort, r_hit_list);
}
/** \} */
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 8e190ed9c73..6633e1c427c 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -27,11 +27,11 @@
#include "CLG_log.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -39,27 +39,27 @@
#include "BKE_callbacks.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BKE_layer.h"
#include "BKE_undo_system.h"
#include "BKE_workspace.h"
-#include "BKE_paint.h"
#include "BLO_blend_validate.h"
#include "ED_gpencil.h"
-#include "ED_render.h"
#include "ED_object.h"
#include "ED_outliner.h"
+#include "ED_render.h"
#include "ED_screen.h"
#include "ED_undo.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -79,15 +79,26 @@ static CLG_LogRef LOG = {"ed.undo"};
void ED_undo_push(bContext *C, const char *str)
{
CLOG_INFO(&LOG, 1, "name='%s'", str);
+ WM_file_tag_modified();
- const int steps = U.undosteps;
-
+ wmWindowManager *wm = CTX_wm_manager(C);
+ int steps = U.undosteps;
+
+ /* Ensure steps that have been initialized are always pushed,
+ * even when undo steps are zero.
+ *
+ * Note that some modes (paint, sculpt) initialize an undo step before an action runs,
+ * then accumulate changes there, or restore data from it in the case of 2D painting.
+ *
+ * For this reason we need to handle the undo step even when undo steps is set to zero.
+ */
+ if ((steps <= 0) && wm->undo_stack->step_init != NULL) {
+ steps = 1;
+ }
if (steps <= 0) {
return;
}
- wmWindowManager *wm = CTX_wm_manager(C);
-
/* Only apply limit if this is the last undo step. */
if (wm->undo_stack->step_active && (wm->undo_stack->step_active->next == NULL)) {
BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, steps - 1, 0);
@@ -97,14 +108,12 @@ void ED_undo_push(bContext *C, const char *str)
if (U.undomemory != 0) {
const size_t memory_limit = (size_t)U.undomemory * 1024 * 1024;
- BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, 0, memory_limit);
+ BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, -1, memory_limit);
}
if (CLOG_CHECK(&LOG, 1)) {
BKE_undosys_print(wm->undo_stack);
}
-
- WM_file_tag_modified();
}
/**
@@ -119,7 +128,7 @@ static int ed_undo_step_impl(
CLOG_INFO(&LOG, 1, "name='%s', step=%d", undoname, step);
wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
/* undo during jobs are running can easily lead to freeing data using by jobs,
* or they can just lead to freezing job in some other cases */
@@ -138,7 +147,7 @@ static int ed_undo_step_impl(
if (ED_gpencil_session_active()) {
return ED_undo_gpencil_step(C, step, undoname);
}
- if (sa && (sa->spacetype == SPACE_VIEW3D)) {
+ if (area && (area->spacetype == SPACE_VIEW3D)) {
Object *obact = CTX_data_active_object(C);
if (obact && (obact->type == OB_GPENCIL)) {
ED_gpencil_toggle_brush_cursor(C, false, NULL);
@@ -195,14 +204,15 @@ static int ed_undo_step_impl(
}
/* Set special modes for grease pencil */
- if (sa && (sa->spacetype == SPACE_VIEW3D)) {
+ if (area && (area->spacetype == SPACE_VIEW3D)) {
Object *obact = CTX_data_active_object(C);
if (obact && (obact->type == OB_GPENCIL)) {
/* set cursor */
if (ELEM(obact->mode,
OB_MODE_PAINT_GPENCIL,
OB_MODE_SCULPT_GPENCIL,
- OB_MODE_WEIGHT_GPENCIL)) {
+ OB_MODE_WEIGHT_GPENCIL,
+ OB_MODE_VERTEX_GPENCIL)) {
ED_gpencil_toggle_brush_cursor(C, true, NULL);
}
else {
@@ -389,7 +399,7 @@ static int ed_undo_exec(bContext *C, wmOperator *op)
int ret = ed_undo_step_direction(C, 1, op->reports);
if (ret & OPERATOR_FINISHED) {
/* Keep button under the cursor active. */
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
}
ED_outliner_select_sync_from_all_tag(C);
@@ -418,7 +428,7 @@ static int ed_redo_exec(bContext *C, wmOperator *op)
int ret = ed_undo_step_direction(C, -1, op->reports);
if (ret & OPERATOR_FINISHED) {
/* Keep button under the cursor active. */
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
}
ED_outliner_select_sync_from_all_tag(C);
@@ -432,7 +442,7 @@ static int ed_undo_redo_exec(bContext *C, wmOperator *UNUSED(op))
ret = ret ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
if (ret & OPERATOR_FINISHED) {
/* Keep button under the cursor active. */
- WM_event_add_mousemove(C);
+ WM_event_add_mousemove(CTX_wm_window(C));
}
return ret;
}
@@ -557,11 +567,11 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
struct Scene *scene = CTX_data_scene(C);
/* keep in sync with logic in view3d_panel_operator_redo() */
- ARegion *ar_orig = CTX_wm_region(C);
- ARegion *ar_win = BKE_area_find_region_active_win(CTX_wm_area(C));
+ ARegion *region_orig = CTX_wm_region(C);
+ ARegion *region_win = BKE_area_find_region_active_win(CTX_wm_area(C));
- if (ar_win) {
- CTX_wm_region_set(C, ar_win);
+ if (region_win) {
+ CTX_wm_region_set(C, region_win);
}
if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) &&
@@ -584,9 +594,9 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
if (op->type->check) {
if (op->type->check(C, op)) {
/* check for popup and re-layout buttons */
- ARegion *ar_menu = CTX_wm_menu(C);
- if (ar_menu) {
- ED_region_tag_refresh_ui(ar_menu);
+ ARegion *region_menu = CTX_wm_menu(C);
+ if (region_menu) {
+ ED_region_tag_refresh_ui(region_menu);
}
}
}
@@ -609,7 +619,7 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
}
/* set region back */
- CTX_wm_region_set(C, ar_orig);
+ CTX_wm_region_set(C, region_orig);
}
else {
CLOG_WARN(&LOG, "called with NULL 'op'");
@@ -774,7 +784,7 @@ void ED_undo_object_editmode_restore_helper(struct bContext *C,
uint bases_len = 0;
/* Don't request unique data because we want to de-select objects when exiting edit-mode
* for that to be done on all objects we can't skip ones that share data. */
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, NULL, &bases_len);
+ Base **bases = ED_undo_editmode_bases_from_view_layer(view_layer, &bases_len);
for (uint i = 0; i < bases_len; i++) {
((ID *)bases[i]->object->data)->tag |= LIB_TAG_DOIT;
}
@@ -798,3 +808,104 @@ void ED_undo_object_editmode_restore_helper(struct bContext *C,
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Undo View Layer Helper Functions
+ *
+ * Needed because view layer functions such as
+ * #BKE_view_layer_array_from_objects_in_edit_mode_unique_data also check visibility,
+ * which is not reliable when it comes to object undo operations,
+ * since hidden objects can be operated on in the properties editor,
+ * and local collections may be used.
+ * \{ */
+
+static int undo_editmode_objects_from_view_layer_prepare(ViewLayer *view_layer,
+ Object *obact,
+ int *r_active_index)
+{
+ const short object_type = obact->type;
+
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ Object *ob = base->object;
+ if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
+ ID *id = ob->data;
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+ }
+
+ int len = 0;
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ Object *ob = base->object;
+ if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
+ if (ob == obact) {
+ *r_active_index = len;
+ }
+ ID *id = ob->data;
+ if ((id->tag & LIB_TAG_DOIT) == 0) {
+ len += 1;
+ id->tag |= LIB_TAG_DOIT;
+ }
+ }
+ }
+ return len;
+}
+
+Object **ED_undo_editmode_objects_from_view_layer(ViewLayer *view_layer, uint *r_len)
+{
+ Object *obact = OBACT(view_layer);
+ if ((obact == NULL) || (obact->mode & OB_MODE_EDIT) == 0) {
+ return MEM_mallocN(0, __func__);
+ }
+ int active_index = 0;
+ const int len = undo_editmode_objects_from_view_layer_prepare(view_layer, obact, &active_index);
+ const short object_type = obact->type;
+ int i = 0;
+ Object **objects = MEM_malloc_arrayN(len, sizeof(*objects), __func__);
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ Object *ob = base->object;
+ if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
+ ID *id = ob->data;
+ if (id->tag & LIB_TAG_DOIT) {
+ objects[i++] = ob;
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+ }
+ }
+ BLI_assert(i == len);
+ if (active_index > 0) {
+ SWAP(Object *, objects[0], objects[active_index]);
+ }
+ *r_len = len;
+ return objects;
+}
+
+Base **ED_undo_editmode_bases_from_view_layer(ViewLayer *view_layer, uint *r_len)
+{
+ Object *obact = OBACT(view_layer);
+ if ((obact == NULL) || (obact->mode & OB_MODE_EDIT) == 0) {
+ return MEM_mallocN(0, __func__);
+ }
+ int active_index = 0;
+ const int len = undo_editmode_objects_from_view_layer_prepare(view_layer, obact, &active_index);
+ const short object_type = obact->type;
+ int i = 0;
+ Base **base_array = MEM_malloc_arrayN(len, sizeof(*base_array), __func__);
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ Object *ob = base->object;
+ if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
+ ID *id = ob->data;
+ if (id->tag & LIB_TAG_DOIT) {
+ base_array[i++] = base;
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+ }
+ }
+ BLI_assert(i == len);
+ if (active_index > 0) {
+ SWAP(Base *, base_array[0], base_array[active_index]);
+ }
+ *r_len = len;
+ return base_array;
+}
+
+/** \} */
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index a5f30409aa6..f22e18de7a1 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -20,15 +20,26 @@
* Wrapper between 'ED_undo.h' and 'BKE_undo_system.h' API's.
*/
-#include "BLI_utildefines.h"
#include "BLI_sys_types.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "DNA_node_types.h"
#include "DNA_object_enums.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_blender_undo.h"
#include "BKE_context.h"
-#include "BKE_undo_system.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_scene.h"
+#include "BKE_undo_system.h"
+
+#include "../depsgraph/DEG_depsgraph.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -85,16 +96,98 @@ static bool memfile_undosys_step_encode(struct bContext *UNUSED(C),
us->data = BKE_memfile_undo_encode(bmain, us_prev ? us_prev->data : NULL);
us->step.data_size = us->data->undo_size;
+ /* Store the fact that we should not re-use old data with that undo step, and reset the Main
+ * flag. */
+ us->step.use_old_bmain_data = !bmain->use_memfile_full_barrier;
+ bmain->use_memfile_full_barrier = false;
+
return true;
}
-static void memfile_undosys_step_decode(
- struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final))
+static int memfile_undosys_step_id_reused_cb(LibraryIDLinkCallbackData *cb_data)
+{
+ ID *id_self = cb_data->id_self;
+ ID **id_pointer = cb_data->id_pointer;
+ BLI_assert((id_self->tag & LIB_TAG_UNDO_OLD_ID_REUSED) != 0);
+
+ ID *id = *id_pointer;
+ if (id != NULL && id->lib == NULL && (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) == 0) {
+ bool do_stop_iter = true;
+ if (GS(id_self->name) == ID_OB) {
+ Object *ob_self = (Object *)id_self;
+ if (ob_self->type == OB_ARMATURE) {
+ if (ob_self->data == id) {
+ BLI_assert(GS(id->name) == ID_AR);
+ if (ob_self->pose != NULL) {
+ /* We have a changed/re-read armature used by an unchanged armature object: our beloved
+ * Bone pointers from the object's pose need their usual special treatment. */
+ ob_self->pose->flag |= POSE_RECALC;
+ }
+ }
+ else {
+ /* Cannot stop iteration until we checked ob_self->data pointer... */
+ do_stop_iter = false;
+ }
+ }
+ }
+
+ return do_stop_iter ? IDWALK_RET_STOP_ITER : IDWALK_RET_NOP;
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+static void memfile_undosys_step_decode(struct bContext *C,
+ struct Main *bmain,
+ UndoStep *us_p,
+ int undo_direction,
+ bool UNUSED(is_final))
{
+ BLI_assert(undo_direction != 0);
+
+ bool use_old_bmain_data = true;
+
+ if (USER_EXPERIMENTAL_TEST(&U, use_undo_legacy)) {
+ use_old_bmain_data = false;
+ }
+ else if (undo_direction > 0) {
+ /* Redo case.
+ * The only time we should have to force a complete redo is when current step is tagged as a
+ * redo barrier.
+ * If previous step was not a memfile one should not matter here, current data in old bmain
+ * should still always be valid for unchanged data-blocks. */
+ if (us_p->use_old_bmain_data == false) {
+ use_old_bmain_data = false;
+ }
+ }
+ else {
+ /* Undo case.
+ * Here we do not care whether current step is an undo barrier, since we are coming from
+ * 'the future' we can still re-use old data. However, if *next* undo step
+ * (i.e. the one immediately in the future, the one we are coming from)
+ * is a barrier, then we have to force a complete undo.
+ * Note that non-memfile undo steps **should** not be an issue anymore, since we handle
+ * fine-grained update flags now.
+ */
+ UndoStep *us_next = us_p->next;
+ if (us_next != NULL) {
+ if (us_next->use_old_bmain_data == false) {
+ use_old_bmain_data = false;
+ }
+ }
+ }
+
+ /* Extract depsgraphs from current bmain (which may be freed during undo step reading),
+ * and store them for re-use. */
+ GHash *depsgraphs = NULL;
+ if (use_old_bmain_data) {
+ depsgraphs = BKE_scene_undo_depsgraphs_extract(bmain);
+ }
+
ED_editors_exit(bmain, false);
MemFileUndoStep *us = (MemFileUndoStep *)us_p;
- BKE_memfile_undo_decode(us->data, C);
+ BKE_memfile_undo_decode(us->data, undo_direction, use_old_bmain_data, C);
for (UndoStep *us_iter = us_p->next; us_iter; us_iter = us_iter->next) {
if (BKE_UNDOSYS_TYPE_IS_MEMFILE_SKIP(us_iter->type)) {
@@ -113,6 +206,49 @@ static void memfile_undosys_step_decode(
bmain = CTX_data_main(C);
ED_editors_init_for_undo(bmain);
+ if (use_old_bmain_data) {
+ /* Restore previous depsgraphs into current bmain. */
+ BKE_scene_undo_depsgraphs_restore(bmain, depsgraphs);
+
+ /* We need to inform depsgraph about re-used old IDs that would be using newly read
+ * data-blocks, at least COW evaluated copies need to be updated... */
+ ID *id = NULL;
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ if (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) {
+ BKE_library_foreach_ID_link(
+ bmain, id, memfile_undosys_step_id_reused_cb, bmain, IDWALK_READONLY);
+ }
+
+ /* Tag depsgraph to update data-block for changes that happened between the
+ * current and the target state, see direct_link_id_restore_recalc(). */
+ if (id->recalc) {
+ DEG_id_tag_update_ex(bmain, id, id->recalc);
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ /* Clear temporary tag. */
+ id->tag &= ~LIB_TAG_UNDO_OLD_ID_REUSED;
+
+ /* We only start accumulating from this point, any tags set up to here
+ * are already part of the current undo state. This is done in a second
+ * loop because DEG_id_tag_update may set tags on other datablocks. */
+ id->recalc_after_undo_push = 0;
+ bNodeTree *nodetree = ntreeFromID(id);
+ if (nodetree != NULL) {
+ nodetree->id.recalc_after_undo_push = 0;
+ }
+ if (GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *)id;
+ if (scene->master_collection != NULL) {
+ scene->master_collection->id.recalc_after_undo_push = 0;
+ }
+ }
+ }
+ FOREACH_MAIN_ID_END;
+ }
+
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
}
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index bee3abe1dc5..54e472ef301 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -17,6 +17,7 @@
set(INC
../include
+ ../space_sequencer
../../blenkernel
../../blenlib
../../blentranslation
@@ -39,6 +40,7 @@ set(INC_SYS
set(SRC
ed_transverts.c
ed_util.c
+ ed_util_imbuf.c
gizmo_utils.c
numinput.c
select_utils.c
@@ -92,6 +94,7 @@ set(SRC
../include/ED_undo.h
../include/ED_userpref.h
../include/ED_util.h
+ ../include/ED_util_imbuf.h
../include/ED_uvedit.h
../include/ED_view3d.h
../include/UI_icons.h
diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c
index f054d09094d..1c56ad878e2 100644
--- a/source/blender/editors/util/ed_transverts.c
+++ b/source/blender/editors/util/ed_transverts.c
@@ -27,18 +27,18 @@
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meta_types.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
-#include "BKE_curve.h"
-#include "BKE_lattice.h"
-#include "BKE_editmesh.h"
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_editmesh.h"
+#include "BKE_lattice.h"
#include "BKE_mesh_iterators.h"
#include "DEG_depsgraph.h"
@@ -111,7 +111,7 @@ void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit)
}
BKE_nurb_test_2d(nu);
- BKE_nurb_handles_test(nu, true); /* test for bezier too */
+ BKE_nurb_handles_test(nu, true, false); /* test for bezier too */
nu = nu->next;
}
}
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index b4b89c31414..f8e19b742e4 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -21,23 +21,24 @@
* \ingroup edutil
*/
+#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
+#include "DNA_packedFile_types.h"
+#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_packedFile_types.h"
-#include "BLI_utildefines.h"
-#include "BLI_string.h"
+#include "BLI_listbase.h"
#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -45,6 +46,7 @@
#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_multires.h"
#include "BKE_object.h"
#include "BKE_packedFile.h"
@@ -52,7 +54,6 @@
#include "BKE_screen.h"
#include "BKE_undo_system.h"
#include "BKE_workspace.h"
-#include "BKE_material.h"
#include "DEG_depsgraph.h"
@@ -73,16 +74,16 @@
#include "UI_interface.h"
#include "UI_resources.h"
-#include "WM_types.h"
-#include "WM_api.h"
#include "RNA_access.h"
+#include "WM_api.h"
+#include "WM_types.h"
/* ********* general editor util funcs, not BKE stuff please! ********* */
void ED_editors_init_for_undo(Main *bmain)
{
wmWindowManager *wm = bmain->wm.first;
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
Base *base = BASACT(view_layer);
if (base != NULL) {
@@ -127,7 +128,7 @@ void ED_editors_init(bContext *C)
}
else if (ob->type == OB_GPENCIL) {
/* For multi-edit mode we may already have mode data (grease pencil does not need it).
- * However we may have a non-active object stuck in a greasepencil edit mode. */
+ * However we may have a non-active object stuck in a grease-pencil edit mode. */
if (ob != obact) {
ob->mode = OB_MODE_OBJECT;
DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
@@ -224,8 +225,8 @@ void ED_editors_exit(Main *bmain, bool do_undo_system)
}
/* global in meshtools... */
- ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
- ED_mesh_mirror_topo_table(NULL, NULL, 'e');
+ ED_mesh_mirror_spatial_table_end(NULL);
+ ED_mesh_mirror_topo_table_end(NULL);
}
bool ED_editors_flush_edits_for_object_ex(Main *bmain,
@@ -238,15 +239,12 @@ bool ED_editors_flush_edits_for_object_ex(Main *bmain,
/* Don't allow flushing while in the middle of a stroke (frees data in use).
* Auto-save prevents this from happening but scripts
* may cause a flush on saving: T53986. */
- if ((ob->sculpt && ob->sculpt->cache) == 0) {
-
- {
- char *needs_flush_ptr = &ob->sculpt->needs_flush_to_id;
- if (check_needs_flush && (*needs_flush_ptr == 0)) {
- return false;
- }
- *needs_flush_ptr = 0;
+ if (ob->sculpt != NULL && ob->sculpt->cache == NULL) {
+ char *needs_flush_ptr = &ob->sculpt->needs_flush_to_id;
+ if (check_needs_flush && (*needs_flush_ptr == 0)) {
+ return false;
}
+ *needs_flush_ptr = 0;
/* flush multires changes (for sculpt) */
multires_flush_sculpt_updates(ob);
@@ -437,13 +435,13 @@ void unpack_menu(bContext *C,
/**
* Callback that draws a line between the mouse and a position given as the initial argument.
*/
-void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info)
+void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_info)
{
wmWindow *win = CTX_wm_window(C);
const float *mval_src = (float *)arg_info;
const float mval_dst[2] = {
- win->eventstate->x - ar->winrct.xmin,
- win->eventstate->y - ar->winrct.ymin,
+ win->eventstate->x - region->winrct.xmin,
+ win->eventstate->y - region->winrct.ymin,
};
const uint shdr_pos = GPU_vertformat_attr_add(
@@ -458,7 +456,7 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor3(TH_VIEW_OVERLAY);
immUniform1f("dash_width", 6.0f);
immUniform1f("dash_factor", 0.5f);
@@ -475,12 +473,12 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
*
* \param new_id: may be NULL to unlink \a old_id.
*/
-void ED_spacedata_id_remap(struct ScrArea *sa, struct SpaceLink *sl, ID *old_id, ID *new_id)
+void ED_spacedata_id_remap(struct ScrArea *area, struct SpaceLink *sl, ID *old_id, ID *new_id)
{
SpaceType *st = BKE_spacetype_from_id(sl->spacetype);
if (st && st->id_remap) {
- st->id_remap(sa, sl, old_id, new_id);
+ st->id_remap(area, sl, old_id, new_id);
}
}
diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c
new file mode 100644
index 00000000000..132a63a8249
--- /dev/null
+++ b/source/blender/editors/util/ed_util_imbuf.c
@@ -0,0 +1,571 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edutil
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_rect.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+#include "BKE_sequencer.h"
+
+#include "ED_image.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "GPU_immediate.h"
+#include "GPU_state.h"
+
+#include "IMB_colormanagement.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "UI_view2d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "sequencer_intern.h"
+
+/* Own define. */
+#include "ED_util_imbuf.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Image Pixel Sample Struct (Operator Custom Data)
+ * \{ */
+
+typedef struct ImageSampleInfo {
+ ARegionType *art;
+ void *draw_handle;
+ int x, y;
+ int channels;
+
+ int width, height;
+ int sample_size;
+
+ unsigned char col[4];
+ float colf[4];
+ float linearcol[4];
+ int z;
+ float zf;
+
+ unsigned char *colp;
+ const float *colfp;
+ int *zp;
+ float *zfp;
+
+ bool draw;
+ bool color_manage;
+ int use_default_view;
+} ImageSampleInfo;
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Image Pixel Sample
+ * \{ */
+
+static void image_sample_pixel_color_ubyte(const ImBuf *ibuf,
+ const int coord[2],
+ uchar r_col[4],
+ float r_col_linear[4])
+{
+ const uchar *cp = (unsigned char *)(ibuf->rect + coord[1] * ibuf->x + coord[0]);
+ copy_v4_v4_uchar(r_col, cp);
+ rgba_uchar_to_float(r_col_linear, r_col);
+ IMB_colormanagement_colorspace_to_scene_linear_v4(r_col_linear, false, ibuf->rect_colorspace);
+}
+
+static void image_sample_pixel_color_float(ImBuf *ibuf, const int coord[2], float r_col[4])
+{
+ const float *cp = ibuf->rect_float + (ibuf->channels) * (coord[1] * ibuf->x + coord[0]);
+ copy_v4_v4(r_col, cp);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Image Pixel Region Sample
+ * \{ */
+
+static void image_sample_rect_color_ubyte(const ImBuf *ibuf,
+ const rcti *rect,
+ uchar r_col[4],
+ float r_col_linear[4])
+{
+ uint col_accum_ub[4] = {0, 0, 0, 0};
+ zero_v4(r_col_linear);
+ int col_tot = 0;
+ int coord[2];
+ for (coord[0] = rect->xmin; coord[0] <= rect->xmax; coord[0]++) {
+ for (coord[1] = rect->ymin; coord[1] <= rect->ymax; coord[1]++) {
+ float col_temp_fl[4];
+ uchar col_temp_ub[4];
+ image_sample_pixel_color_ubyte(ibuf, coord, col_temp_ub, col_temp_fl);
+ add_v4_v4(r_col_linear, col_temp_fl);
+ col_accum_ub[0] += (uint)col_temp_ub[0];
+ col_accum_ub[1] += (uint)col_temp_ub[1];
+ col_accum_ub[2] += (uint)col_temp_ub[2];
+ col_accum_ub[3] += (uint)col_temp_ub[3];
+ col_tot += 1;
+ }
+ }
+ mul_v4_fl(r_col_linear, 1.0 / (float)col_tot);
+
+ r_col[0] = MIN2(col_accum_ub[0] / col_tot, 255);
+ r_col[1] = MIN2(col_accum_ub[1] / col_tot, 255);
+ r_col[2] = MIN2(col_accum_ub[2] / col_tot, 255);
+ r_col[3] = MIN2(col_accum_ub[3] / col_tot, 255);
+}
+
+static void image_sample_rect_color_float(ImBuf *ibuf, const rcti *rect, float r_col[4])
+{
+ zero_v4(r_col);
+ int col_tot = 0;
+ int coord[2];
+ for (coord[0] = rect->xmin; coord[0] <= rect->xmax; coord[0]++) {
+ for (coord[1] = rect->ymin; coord[1] <= rect->ymax; coord[1]++) {
+ float col_temp_fl[4];
+ image_sample_pixel_color_float(ibuf, coord, col_temp_fl);
+ add_v4_v4(r_col, col_temp_fl);
+ col_tot += 1;
+ }
+ }
+ mul_v4_fl(r_col, 1.0 / (float)col_tot);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Image Pixel Sample (Internal Utilities)
+ * \{ */
+
+static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *region = CTX_wm_region(C);
+ Image *image = ED_space_image(sima);
+
+ float uv[2];
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &uv[0], &uv[1]);
+ int tile = BKE_image_get_tile_from_pos(sima->image, uv, uv, NULL);
+
+ void *lock;
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile);
+ ImageSampleInfo *info = op->customdata;
+ Scene *scene = CTX_data_scene(C);
+ CurveMapping *curve_mapping = scene->view_settings.curve_mapping;
+
+ if (ibuf == NULL) {
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ info->draw = false;
+ return;
+ }
+
+ if (uv[0] >= 0.0f && uv[1] >= 0.0f && uv[0] < 1.0f && uv[1] < 1.0f) {
+ int x = (int)(uv[0] * ibuf->x), y = (int)(uv[1] * ibuf->y);
+
+ CLAMP(x, 0, ibuf->x - 1);
+ CLAMP(y, 0, ibuf->y - 1);
+
+ info->width = ibuf->x;
+ info->height = ibuf->y;
+ info->x = x;
+ info->y = y;
+
+ info->draw = true;
+ info->channels = ibuf->channels;
+
+ info->colp = NULL;
+ info->colfp = NULL;
+ info->zp = NULL;
+ info->zfp = NULL;
+
+ info->use_default_view = (image->flag & IMA_VIEW_AS_RENDER) ? false : true;
+
+ rcti sample_rect;
+ sample_rect.xmin = max_ii(0, x - info->sample_size / 2);
+ sample_rect.ymin = max_ii(0, y - info->sample_size / 2);
+ sample_rect.xmax = min_ii(ibuf->x, sample_rect.xmin + info->sample_size) - 1;
+ sample_rect.ymax = min_ii(ibuf->y, sample_rect.ymin + info->sample_size) - 1;
+
+ if (ibuf->rect) {
+ image_sample_rect_color_ubyte(ibuf, &sample_rect, info->col, info->linearcol);
+ rgba_uchar_to_float(info->colf, info->col);
+
+ info->colp = info->col;
+ info->colfp = info->colf;
+ info->color_manage = true;
+ }
+ if (ibuf->rect_float) {
+ image_sample_rect_color_float(ibuf, &sample_rect, info->colf);
+
+ if (ibuf->channels == 4) {
+ /* pass */
+ }
+ else if (ibuf->channels == 3) {
+ info->colf[3] = 1.0f;
+ }
+ else {
+ info->colf[1] = info->colf[0];
+ info->colf[2] = info->colf[0];
+ info->colf[3] = 1.0f;
+ }
+ info->colfp = info->colf;
+
+ copy_v4_v4(info->linearcol, info->colf);
+
+ info->color_manage = true;
+ }
+
+ if (ibuf->zbuf) {
+ /* TODO, blend depth (not urgent). */
+ info->z = ibuf->zbuf[y * ibuf->x + x];
+ info->zp = &info->z;
+ if (ibuf->zbuf == (int *)ibuf->rect) {
+ info->colp = NULL;
+ }
+ }
+ if (ibuf->zbuf_float) {
+ /* TODO, blend depth (not urgent). */
+ info->zf = ibuf->zbuf_float[y * ibuf->x + x];
+ info->zfp = &info->zf;
+ if (ibuf->zbuf_float == ibuf->rect_float) {
+ info->colfp = NULL;
+ }
+ }
+
+ if (curve_mapping && ibuf->channels == 4) {
+ /* we reuse this callback for set curves point operators */
+ if (RNA_struct_find_property(op->ptr, "point")) {
+ int point = RNA_enum_get(op->ptr, "point");
+
+ if (point == 1) {
+ BKE_curvemapping_set_black_white(curve_mapping, NULL, info->linearcol);
+ }
+ else if (point == 0) {
+ BKE_curvemapping_set_black_white(curve_mapping, info->linearcol, NULL);
+ }
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
+ }
+
+ // XXX node curve integration ..
+#if 0
+ {
+ ScrArea *sa, *cur = curarea;
+
+ node_curvemap_sample(fp); /* sends global to node editor */
+ for (sa = G.curscreen->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_NODE) {
+ areawinset(sa->win);
+ scrarea_do_windraw(sa);
+ }
+ }
+ node_curvemap_sample(NULL); /* clears global in node editor */
+ curarea = cur;
+ }
+#endif
+ }
+ else {
+ info->draw = 0;
+ }
+
+ ED_space_image_release_buffer(sima, ibuf, lock);
+ ED_area_tag_redraw(CTX_wm_area(C));
+}
+
+static void sequencer_sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
+ ARegion *region = CTX_wm_region(C);
+ ImBuf *ibuf = sequencer_ibuf_get(bmain, depsgraph, scene, sseq, CFRA, 0, NULL);
+ ImageSampleInfo *info = op->customdata;
+ float fx, fy;
+
+ if (ibuf == NULL) {
+ IMB_freeImBuf(ibuf);
+ info->draw = 0;
+ return;
+ }
+
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fx, &fy);
+
+ fx /= scene->r.xasp / scene->r.yasp;
+
+ fx += (float)scene->r.xsch / 2.0f;
+ fy += (float)scene->r.ysch / 2.0f;
+ fx *= (float)ibuf->x / (float)scene->r.xsch;
+ fy *= (float)ibuf->y / (float)scene->r.ysch;
+
+ if (fx >= 0.0f && fy >= 0.0f && fx < ibuf->x && fy < ibuf->y) {
+ const float *fp;
+ unsigned char *cp;
+ int x = (int)fx, y = (int)fy;
+
+ info->x = x;
+ info->y = y;
+ info->draw = 1;
+ info->channels = ibuf->channels;
+
+ info->colp = NULL;
+ info->colfp = NULL;
+
+ if (ibuf->rect) {
+ cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
+
+ info->col[0] = cp[0];
+ info->col[1] = cp[1];
+ info->col[2] = cp[2];
+ info->col[3] = cp[3];
+ info->colp = info->col;
+
+ info->colf[0] = (float)cp[0] / 255.0f;
+ info->colf[1] = (float)cp[1] / 255.0f;
+ info->colf[2] = (float)cp[2] / 255.0f;
+ info->colf[3] = (float)cp[3] / 255.0f;
+ info->colfp = info->colf;
+
+ copy_v4_v4(info->linearcol, info->colf);
+ IMB_colormanagement_colorspace_to_scene_linear_v4(
+ info->linearcol, false, ibuf->rect_colorspace);
+
+ info->color_manage = true;
+ }
+ if (ibuf->rect_float) {
+ fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
+
+ info->colf[0] = fp[0];
+ info->colf[1] = fp[1];
+ info->colf[2] = fp[2];
+ info->colf[3] = fp[3];
+ info->colfp = info->colf;
+
+ /* sequencer's image buffers are in non-linear space, need to make them linear */
+ copy_v4_v4(info->linearcol, info->colf);
+ BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->linearcol);
+
+ info->color_manage = true;
+ }
+ }
+ else {
+ info->draw = 0;
+ }
+
+ IMB_freeImBuf(ibuf);
+ ED_area_tag_redraw(CTX_wm_area(C));
+}
+
+static void ed_imbuf_sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (sa && sa->spacetype == SPACE_IMAGE) {
+ image_sample_apply(C, op, event);
+ }
+
+ if (sa && sa->spacetype == SPACE_SEQ) {
+ sequencer_sample_apply(C, op, event);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Image Pixel Sample (Public Operator Callback)
+ *
+ * Callbacks for the sample operator, used by sequencer and image spaces.
+ * \{ */
+
+void ED_imbuf_sample_draw(const bContext *C, ARegion *region, void *arg_info)
+{
+ ImageSampleInfo *info = arg_info;
+ if (!info->draw) {
+ return;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+ ED_image_draw_info(scene,
+ region,
+ info->color_manage,
+ info->use_default_view,
+ info->channels,
+ info->x,
+ info->y,
+ info->colp,
+ info->colfp,
+ info->linearcol,
+ info->zp,
+ info->zfp);
+
+ if (info->sample_size > 1) {
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (sa && sa->spacetype == SPACE_IMAGE) {
+
+ const wmWindow *win = CTX_wm_window(C);
+ const wmEvent *event = win->eventstate;
+
+ SpaceImage *sima = CTX_wm_space_image(C);
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ const float color[3] = {1, 1, 1};
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ /* TODO(campbell): lock to pixels. */
+ rctf sample_rect_fl;
+ BLI_rctf_init_pt_radius(
+ &sample_rect_fl,
+ (float[2]){event->x - region->winrct.xmin, event->y - region->winrct.ymin},
+ (float)(info->sample_size / 2.0f) * sima->zoom);
+
+ glEnable(GL_COLOR_LOGIC_OP);
+ glLogicOp(GL_XOR);
+ GPU_line_width(1.0f);
+ imm_draw_box_wire_2d(pos,
+ (float)sample_rect_fl.xmin,
+ (float)sample_rect_fl.ymin,
+ (float)sample_rect_fl.xmax,
+ (float)sample_rect_fl.ymax);
+ glDisable(GL_COLOR_LOGIC_OP);
+
+ immUnbindProgram();
+ }
+ }
+}
+
+void ED_imbuf_sample_exit(bContext *C, wmOperator *op)
+{
+ ImageSampleInfo *info = op->customdata;
+
+ ED_region_draw_cb_exit(info->art, info->draw_handle);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ MEM_freeN(info);
+}
+
+int ED_imbuf_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *region = CTX_wm_region(C);
+ ImageSampleInfo *info;
+
+ info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
+
+ info->art = region->type;
+ info->draw_handle = ED_region_draw_cb_activate(
+ region->type, ED_imbuf_sample_draw, info, REGION_DRAW_POST_PIXEL);
+ info->sample_size = RNA_int_get(op->ptr, "size");
+ op->customdata = info;
+
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (sa && sa->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ if (event->mval[1] <= 16 && ED_space_image_show_cache(sima)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ if (!ED_space_image_has_buffer(sima)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ ed_imbuf_sample_apply(C, op, event);
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+int ED_imbuf_sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ switch (event->type) {
+ case LEFTMOUSE:
+ case RIGHTMOUSE: // XXX hardcoded
+ if (event->val == KM_RELEASE) {
+ ED_imbuf_sample_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ break;
+ case MOUSEMOVE:
+ ed_imbuf_sample_apply(C, op, event);
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void ED_imbuf_sample_cancel(bContext *C, wmOperator *op)
+{
+ ED_imbuf_sample_exit(C, op);
+}
+
+bool ED_imbuf_sample_poll(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (sa && sa->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ if (sima == NULL) {
+ return false;
+ }
+
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit) {
+ /* Disable when UV editing so it doesn't swallow all click events
+ * (use for setting cursor). */
+ if (ED_space_image_show_uvedit(sima, obedit)) {
+ return false;
+ }
+ }
+ else if (sima->mode != SI_MODE_VIEW) {
+ return false;
+ }
+
+ return true;
+ }
+
+ if (sa && sa->spacetype == SPACE_SEQ) {
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+
+ if (sseq->mainb != SEQ_DRAW_IMG_IMBUF) {
+ return false;
+ }
+
+ return sseq && BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL;
+ }
+
+ return false;
+}
+
+/** \} */
diff --git a/source/blender/editors/util/gizmo_utils.c b/source/blender/editors/util/gizmo_utils.c
index b856c831424..08e7b3a9a0a 100644
--- a/source/blender/editors/util/gizmo_utils.c
+++ b/source/blender/editors/util/gizmo_utils.c
@@ -28,9 +28,9 @@
#include "DNA_workspace_types.h"
-#include "WM_types.h"
#include "WM_api.h"
#include "WM_toolsystem.h"
+#include "WM_types.h"
#include "ED_gizmo_utils.h"
@@ -59,9 +59,9 @@ bool ED_gizmo_poll_or_unlink_delayed_from_tool_ex(const bContext *C,
{
bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
if ((tref_rt == NULL) || !STREQ(gzgt_idname, tref_rt->gizmo_group)) {
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params);
- WM_gizmo_group_unlink_delayed_ptr_from_space(gzgt, gzmap_type, sa);
+ WM_gizmo_group_unlink_delayed_ptr_from_space(gzgt, gzmap_type, area);
if (gzgt->users == 0) {
WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
}
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index ead841642d7..be1319c37dd 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -20,11 +20,11 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_string.h"
-#include "BLI_string_utf8.h"
#include "BLI_string_cursor_utf8.h"
+#include "BLI_string_utf8.h"
+#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_scene.h"
@@ -340,6 +340,21 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
}
}
+#ifdef USE_FAKE_EDIT
+ /* XXX Hack around keyboards without direct access to '=' nor '*'... */
+ if (ELEM(event->ascii, '=', '*')) {
+ if (!(n->flag & NUM_EDIT_FULL)) {
+ n->flag |= NUM_EDIT_FULL;
+ n->val_flag[idx] |= NUM_EDITED;
+ return true;
+ }
+ else if (event->ctrl) {
+ n->flag &= ~NUM_EDIT_FULL;
+ return true;
+ }
+ }
+#endif
+
switch (event->type) {
case EVT_MODAL_MAP:
if (ELEM(event->val, NUM_MODAL_INCREMENT_UP, NUM_MODAL_INCREMENT_DOWN)) {
@@ -354,7 +369,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
ascii[0] = event->ascii;
}
break;
- case BACKSPACEKEY:
+ case EVT_BACKSPACEKEY:
/* Part specific to backspace... */
if (!(n->val_flag[idx] & NUM_EDITED)) {
copy_v3_v3(n->val, n->val_org);
@@ -381,7 +396,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
* only difference is remove char(s) before/after the cursor. */
dir = STRCUR_DIR_PREV;
ATTR_FALLTHROUGH;
- case DELKEY:
+ case EVT_DELKEY:
if ((n->val_flag[idx] & NUM_EDITED) && n->str[0]) {
int t_cur = cur = n->str_cur;
if (event->ctrl) {
@@ -405,10 +420,10 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
return false;
}
break;
- case LEFTARROWKEY:
+ case EVT_LEFTARROWKEY:
dir = STRCUR_DIR_PREV;
ATTR_FALLTHROUGH;
- case RIGHTARROWKEY:
+ case EVT_RIGHTARROWKEY:
cur = n->str_cur;
if (event->ctrl) {
mode = STRCUR_JUMP_DELIM;
@@ -419,19 +434,19 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
return true;
}
return false;
- case HOMEKEY:
+ case EVT_HOMEKEY:
if (n->str[0]) {
n->str_cur = 0;
return true;
}
return false;
- case ENDKEY:
+ case EVT_ENDKEY:
if (n->str[0]) {
n->str_cur = strlen(n->str);
return true;
}
return false;
- case TABKEY:
+ case EVT_TABKEY:
#ifdef USE_FAKE_EDIT
n->val_flag[idx] &= ~(NUM_NEGATE | NUM_INVERSE);
#endif
@@ -446,8 +461,8 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
n->str_cur = 0;
}
return true;
- case PADPERIOD:
- case PERIODKEY:
+ case EVT_PADPERIOD:
+ case EVT_PERIODKEY:
/* Force numdot, some OSs/countries generate a comma char in this case,
* sic... (T37992) */
ascii[0] = '.';
@@ -473,29 +488,29 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
#endif
#ifdef USE_FAKE_EDIT
- case PADMINUS:
- case MINUSKEY:
+ case EVT_PADMINUS:
+ case EVT_MINUSKEY:
if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) {
n->val_flag[idx] ^= NUM_NEGATE;
updated = true;
}
break;
- case PADSLASHKEY:
- case SLASHKEY:
+ case EVT_PADSLASHKEY:
+ case EVT_SLASHKEY:
if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) {
n->val_flag[idx] ^= NUM_INVERSE;
updated = true;
}
break;
#endif
- case CKEY:
+ case EVT_CKEY:
if (event->ctrl) {
/* Copy current str to the copypaste buffer. */
WM_clipboard_text_set(n->str, 0);
updated = true;
}
break;
- case VKEY:
+ case EVT_VKEY:
if (event->ctrl) {
/* extract the first line from the clipboard */
int pbuf_len;
@@ -523,21 +538,6 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
ascii[0] = event->ascii;
}
-#ifdef USE_FAKE_EDIT
- /* XXX Hack around keyboards without direct access to '=' nor '*'... */
- if (ELEM(ascii[0], '=', '*')) {
- if (!(n->flag & NUM_EDIT_FULL)) {
- n->flag |= NUM_EDIT_FULL;
- n->val_flag[idx] |= NUM_EDITED;
- return true;
- }
- else if (event->ctrl) {
- n->flag &= ~NUM_EDIT_FULL;
- return true;
- }
- }
-#endif
-
/* Up to this point, if we have a ctrl modifier, skip.
* This allows to still access most of modals' shortcuts even in numinput mode.
*/
diff --git a/source/blender/editors/util/select_utils.c b/source/blender/editors/util/select_utils.c
index a26579b0d84..85f48e6d397 100644
--- a/source/blender/editors/util/select_utils.c
+++ b/source/blender/editors/util/select_utils.c
@@ -18,9 +18,9 @@
* \ingroup edutil
*/
-#include "BLI_utildefines.h"
#include "BLI_kdtree.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "ED_select_utils.h"
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index d2ba9ab9591..b40b82c50fb 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -40,6 +40,7 @@ set(SRC
uvedit_draw.c
uvedit_ops.c
uvedit_parametrizer.c
+ uvedit_select.c
uvedit_smart_stitch.c
uvedit_unwrap_ops.c
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index 44bffc76859..c072220842e 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -21,8 +21,8 @@
* \ingroup eduv
*/
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -259,11 +259,11 @@ static bool image_panel_uv_poll(const bContext *C, PanelType *UNUSED(pt))
return ED_uvedit_test(obedit);
}
-static void image_panel_uv(const bContext *C, Panel *pa)
+static void image_panel_uv(const bContext *C, Panel *panel)
{
uiBlock *block;
- block = uiLayoutAbsoluteBlock(pa->layout);
+ block = uiLayoutAbsoluteBlock(panel->layout);
UI_block_func_handle_set(block, do_uvedit_vertex, NULL);
uvedit_vertex_buttons(C, block);
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 528fca85fa7..959ca1eeef1 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -43,8 +43,8 @@
#include "BKE_deform.h"
#include "BKE_editmesh.h"
-#include "BKE_material.h"
#include "BKE_layer.h"
+#include "BKE_material.h"
#include "BKE_scene.h"
@@ -61,8 +61,8 @@
#include "ED_mesh.h"
#include "ED_uvedit.h"
-#include "UI_resources.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "UI_view2d.h"
#include "uvedit_intern.h"
@@ -99,11 +99,11 @@ static int draw_uvs_face_check(const ToolSettings *ts)
/* ------------------------- */
-void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
+void ED_image_draw_cursor(ARegion *region, const float cursor[2])
{
float zoom[2], x_fac, y_fac;
- UI_view2d_scale_get_inverse(&ar->v2d, &zoom[0], &zoom[1]);
+ UI_view2d_scale_get_inverse(&region->v2d, &zoom[0], &zoom[1]);
mul_v2_fl(zoom, 256.0f * UI_DPI_FAC);
x_fac = zoom[0];
@@ -265,6 +265,7 @@ static void draw_uvs_texpaint(const Scene *scene, Object *ob, Depsgraph *depsgra
bool prev_ma_match = (mpoly->mat_nr == (ob_eval->actcol - 1));
GPU_matrix_bind(geom->interface);
+ GPU_shader_set_srgb_uniform(geom->interface);
GPU_batch_bind(geom);
/* TODO(fclem): If drawcall count becomes a problem in the future
@@ -305,6 +306,7 @@ static void draw_uvs(SpaceImage *sima,
Object *ob_eval = batch->ob_eval;
const ToolSettings *ts = scene->toolsettings;
float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float overlay_alpha = sima->uv_opacity;
if (sima->flag & SI_DRAWSHADOW) {
bool is_cage_like_final_meshes = false;
@@ -345,7 +347,11 @@ static void draw_uvs(SpaceImage *sima,
UI_GetThemeColor4fv(TH_FACE, col1);
UI_GetThemeColor4fv(TH_FACE_SELECT, col2);
UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, col3);
- col3[3] *= 0.2; /* Simulate dithering */
+
+ col1[3] *= overlay_alpha;
+ col2[3] *= overlay_alpha;
+ col3[3] *= overlay_alpha;
+
GPU_batch_uniform_4fv(batch->faces, "faceColor", col1);
GPU_batch_uniform_4fv(batch->faces, "selectColor", col2);
GPU_batch_uniform_4fv(batch->faces, "activeColor", col3);
@@ -371,9 +377,16 @@ static void draw_uvs(SpaceImage *sima,
GPU_line_smooth(true);
GPU_blend(true);
}
+ else if (overlay_alpha < 1.0f) {
+ GPU_blend(true);
+ }
+
switch (sima->dt_uv) {
case SI_UVDT_DASH: {
- float dash_colors[2][4] = {{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}};
+ float dash_colors[2][4] = {
+ {0.56f, 0.56f, 0.56f, overlay_alpha},
+ {0.07f, 0.07f, 0.07f, overlay_alpha},
+ };
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
@@ -397,7 +410,8 @@ static void draw_uvs(SpaceImage *sima,
* instead of modifying the provoking vert. */
glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
- UI_GetThemeColor4fv(TH_EDGE_SELECT, col2);
+ UI_GetThemeColor3fv(TH_EDGE_SELECT, col2);
+ col2[3] = overlay_alpha;
GPU_batch_program_set_builtin(
batch->edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES);
@@ -405,18 +419,19 @@ static void draw_uvs(SpaceImage *sima,
if (sima->dt_uv == SI_UVDT_OUTLINE) {
/* Black Outline. */
GPU_line_width(3.0f);
- GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f);
- GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f);
+ GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, overlay_alpha);
+ GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, overlay_alpha);
GPU_batch_draw(batch->edges);
- UI_GetThemeColor4fv(TH_WIRE_EDIT, col1);
+ UI_GetThemeColor3fv(TH_WIRE_EDIT, col1);
}
else if (sima->dt_uv == SI_UVDT_WHITE) {
- copy_v4_fl4(col1, 1.0f, 1.0f, 1.0f, 1.0f);
+ copy_v3_fl3(col1, 1.0f, 1.0f, 1.0f);
}
else {
- copy_v4_fl4(col1, 0.0f, 0.0f, 0.0f, 1.0f);
+ copy_v3_fl3(col1, 0.0f, 0.0f, 0.0f);
}
+ col1[3] = overlay_alpha;
/* Inner Line. Use depth test to insure selection is drawn on top. */
GPU_depth_test(true);
@@ -434,6 +449,9 @@ static void draw_uvs(SpaceImage *sima,
GPU_line_smooth(false);
GPU_blend(false);
}
+ else if (overlay_alpha < 1.0f) {
+ GPU_blend(false);
+ }
}
if (batch->verts || batch->facedots) {
UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2);
@@ -478,9 +496,9 @@ static void draw_uvs(SpaceImage *sima,
}
static void draw_uv_shadows_get(
- SpaceImage *sima, Object *ob, Object *obedit, bool *show_shadow, bool *show_texpaint)
+ SpaceImage *sima, Object *ob, Object *obedit, bool *r_show_shadow, bool *r_show_texpaint)
{
- *show_shadow = *show_texpaint = false;
+ *r_show_shadow = *r_show_texpaint = false;
if (ED_space_image_show_render(sima) || (sima->flag & SI_NO_DRAW_TEXPAINT)) {
return;
@@ -489,10 +507,10 @@ static void draw_uv_shadows_get(
if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) {
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
- *show_shadow = EDBM_uv_check(em);
+ *r_show_shadow = EDBM_uv_check(em);
}
- *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
+ *r_show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
}
void ED_uvedit_draw_main(SpaceImage *sima,
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 7bc6b048585..ffab5bd094f 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -99,6 +99,7 @@ bool uv_find_nearest_face_multi(struct Scene *scene,
void uvedit_live_unwrap_update(struct SpaceImage *sima,
struct Scene *scene,
struct Object *obedit);
+void uvedit_pixel_to_float(struct SpaceImage *sima, float pixeldist, float r_dist[2]);
/* operators */
@@ -113,4 +114,31 @@ void UV_OT_sphere_project(struct wmOperatorType *ot);
void UV_OT_unwrap(struct wmOperatorType *ot);
void UV_OT_stitch(struct wmOperatorType *ot);
+/* uvedit_select.c */
+
+bool uvedit_select_is_any_selected(struct Scene *scene, struct Image *ima, struct Object *obedit);
+bool uvedit_select_is_any_selected_multi(struct Scene *scene,
+ struct Image *ima,
+ struct Object **objects,
+ const uint objects_len);
+const float *uvedit_first_selected_uv_from_vertex(struct Scene *scene,
+ struct Object *obedit,
+ struct Image *ima,
+ struct BMVert *eve,
+ const int cd_loop_uv_offset);
+
+void UV_OT_select_all(struct wmOperatorType *ot);
+void UV_OT_select(struct wmOperatorType *ot);
+void UV_OT_select_loop(struct wmOperatorType *ot);
+void UV_OT_select_linked(struct wmOperatorType *ot);
+void UV_OT_select_linked_pick(struct wmOperatorType *ot);
+void UV_OT_select_split(struct wmOperatorType *ot);
+void UV_OT_select_pinned(struct wmOperatorType *ot);
+void UV_OT_select_box(struct wmOperatorType *ot);
+void UV_OT_select_lasso(struct wmOperatorType *ot);
+void UV_OT_select_circle(struct wmOperatorType *ot);
+void UV_OT_select_more(struct wmOperatorType *ot);
+void UV_OT_select_less(struct wmOperatorType *ot);
+void UV_OT_select_overlap(struct wmOperatorType *ot);
+
#endif /* __UVEDIT_INTERN_H__ */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 5be3f676658..a99e05cb52b 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -21,67 +21,51 @@
* \ingroup eduv
*/
-#include <stdlib.h>
-#include <string.h>
#include <math.h>
+#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
-#include "DNA_object_types.h"
+#include "DNA_image_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
-#include "DNA_image_types.h"
-#include "DNA_space_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
-#include "BLI_utildefines.h"
-#include "BLI_alloca.h"
-#include "BLI_math.h"
-#include "BLI_lasso_2d.h"
-#include "BLI_blenlib.h"
#include "BLI_array.h"
-#include "BLI_hash.h"
#include "BLI_kdtree.h"
-#include "BLI_kdopbvh.h"
-#include "BLI_polyfill_2d.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
-#include "BKE_image.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
-#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_node.h"
-#include "BKE_report.h"
-#include "BKE_scene.h"
#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
#include "ED_image.h"
#include "ED_mesh.h"
#include "ED_node.h"
-#include "ED_uvedit.h"
-#include "ED_object.h"
#include "ED_screen.h"
-#include "ED_select_utils.h"
-#include "ED_transform.h"
+#include "ED_uvedit.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "RNA_enum_types.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "WM_message.h"
+#include "WM_types.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -89,26 +73,6 @@
#include "uvedit_intern.h"
-static bool uv_select_is_any_selected(Scene *scene, Image *ima, Object *obedit);
-static bool uv_select_is_any_selected_multi(Scene *scene,
- Image *ima,
- Object **objects,
- const uint objects_len);
-static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action);
-static void uv_select_all_perform_multi(
- Scene *scene, Image *ima, Object **objects, const uint objects_len, int action);
-static void uv_select_flush_from_tag_face(SpaceImage *sima,
- Scene *scene,
- Object *obedit,
- const bool select);
-static void uv_select_flush_from_tag_loop(SpaceImage *sima,
- Scene *scene,
- Object *obedit,
- const bool select);
-static void uv_select_tag_update_for_object(Depsgraph *depsgraph,
- const ToolSettings *ts,
- Object *obedit);
-
/* -------------------------------------------------------------------- */
/** \name State Testing
* \{ */
@@ -165,7 +129,7 @@ bool ED_object_get_active_image(Object *ob,
bNode **r_node,
bNodeTree **r_ntree)
{
- Material *ma = give_current_material(ob, mat_nr);
+ Material *ma = BKE_object_material_get(ob, mat_nr);
bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL;
bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL;
@@ -211,7 +175,7 @@ bool ED_object_get_active_image(Object *ob,
void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *ima)
{
- Material *ma = give_current_material(ob, mat_nr);
+ Material *ma = BKE_object_material_get(ob, mat_nr);
bNode *node = (ma && ma->use_nodes) ? nodeGetActiveTexture(ma->nodetree) : NULL;
if (node && is_image_texture_node(node)) {
@@ -226,7 +190,7 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
/** \name Space Conversion
* \{ */
-static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist)
+void uvedit_pixel_to_float(SpaceImage *sima, float pixeldist, float r_dist[2])
{
int width, height;
@@ -238,351 +202,8 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
height = IMG_SIZE_FALLBACK;
}
- dist[0] = pixeldist / width;
- dist[1] = pixeldist / height;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Visibility and Selection Utilities
- * \{ */
-
-static void uvedit_vertex_select_tagged(BMEditMesh *em,
- Scene *scene,
- bool select,
- int cd_loop_uv_offset)
-{
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- }
- }
- }
-}
-
-bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa)
-{
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0);
- }
- else {
- return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT));
- }
-}
-bool uvedit_face_visible_nolocal(const Scene *scene, BMFace *efa)
-{
- return uvedit_face_visible_nolocal_ex(scene->toolsettings, efa);
-}
-
-bool uvedit_face_visible_test_ex(const ToolSettings *ts, Object *obedit, Image *ima, BMFace *efa)
-{
- if (ts->uv_flag & UV_SHOW_SAME_IMAGE) {
- Image *face_image;
- ED_object_get_active_image(obedit, efa->mat_nr + 1, &face_image, NULL, NULL, NULL);
- return (face_image == ima) ? uvedit_face_visible_nolocal_ex(ts, efa) : false;
- }
- else {
- return uvedit_face_visible_nolocal_ex(ts, efa);
- }
-}
-bool uvedit_face_visible_test(const Scene *scene, Object *obedit, Image *ima, BMFace *efa)
-{
- return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa);
-}
-
-bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const int cd_loop_uv_offset)
-{
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- return (BM_elem_flag_test(efa, BM_ELEM_SELECT));
- }
- else {
- BMLoop *l;
- MLoopUV *luv;
- BMIter liter;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (!(luv->flag & MLOOPUV_VERTSEL)) {
- return false;
- }
- }
-
- return true;
- }
-}
-bool uvedit_face_select_test(const Scene *scene, BMFace *efa, const int cd_loop_uv_offset)
-{
- return uvedit_face_select_test_ex(scene->toolsettings, efa, cd_loop_uv_offset);
-}
-
-bool uvedit_face_select_set(const struct Scene *scene,
- struct BMEditMesh *em,
- struct BMFace *efa,
- const bool select,
- const bool do_history,
- const int cd_loop_uv_offset)
-{
- if (select) {
- return uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset);
- }
- else {
- return uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset);
- }
-}
-
-bool uvedit_face_select_enable(const Scene *scene,
- BMEditMesh *em,
- BMFace *efa,
- const bool do_history,
- const int cd_loop_uv_offset)
-{
- const ToolSettings *ts = scene->toolsettings;
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- BM_face_select_set(em->bm, efa, true);
- if (do_history) {
- BM_select_history_store(em->bm, (BMElem *)efa);
- }
- }
- else {
- BMLoop *l;
- MLoopUV *luv;
- BMIter liter;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag |= MLOOPUV_VERTSEL;
- }
-
- return true;
- }
-
- return false;
-}
-
-bool uvedit_face_select_disable(const Scene *scene,
- BMEditMesh *em,
- BMFace *efa,
- const int cd_loop_uv_offset)
-{
- const ToolSettings *ts = scene->toolsettings;
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- BM_face_select_set(em->bm, efa, false);
- }
- else {
- BMLoop *l;
- MLoopUV *luv;
- BMIter liter;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag &= ~MLOOPUV_VERTSEL;
- }
-
- return true;
- }
-
- return false;
-}
-
-bool uvedit_edge_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset)
-{
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode & SCE_SELECT_FACE) {
- return BM_elem_flag_test(l->f, BM_ELEM_SELECT);
- }
- else if (ts->selectmode == SCE_SELECT_EDGE) {
- return BM_elem_flag_test(l->e, BM_ELEM_SELECT);
- }
- else {
- return BM_elem_flag_test(l->v, BM_ELEM_SELECT) &&
- BM_elem_flag_test(l->next->v, BM_ELEM_SELECT);
- }
- }
- else {
- MLoopUV *luv1, *luv2;
-
- luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
-
- return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL);
- }
-}
-bool uvedit_edge_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset)
-{
- return uvedit_edge_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
-}
-
-void uvedit_edge_select_set(BMEditMesh *em,
- const Scene *scene,
- BMLoop *l,
- const bool select,
- const bool do_history,
- const int cd_loop_uv_offset)
-
-{
- if (select) {
- uvedit_edge_select_enable(em, scene, l, do_history, cd_loop_uv_offset);
- }
- else {
- uvedit_edge_select_disable(em, scene, l, cd_loop_uv_offset);
- }
-}
-
-void uvedit_edge_select_enable(BMEditMesh *em,
- const Scene *scene,
- BMLoop *l,
- const bool do_history,
- const int cd_loop_uv_offset)
-
-{
- const ToolSettings *ts = scene->toolsettings;
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode & SCE_SELECT_FACE) {
- BM_face_select_set(em->bm, l->f, true);
- }
- else if (ts->selectmode & SCE_SELECT_EDGE) {
- BM_edge_select_set(em->bm, l->e, true);
- }
- else {
- BM_vert_select_set(em->bm, l->e->v1, true);
- BM_vert_select_set(em->bm, l->e->v2, true);
- }
-
- if (do_history) {
- BM_select_history_store(em->bm, (BMElem *)l->e);
- }
- }
- else {
- MLoopUV *luv1, *luv2;
-
- luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
-
- luv1->flag |= MLOOPUV_VERTSEL;
- luv2->flag |= MLOOPUV_VERTSEL;
- }
-}
-
-void uvedit_edge_select_disable(BMEditMesh *em,
- const Scene *scene,
- BMLoop *l,
- const int cd_loop_uv_offset)
-
-{
- const ToolSettings *ts = scene->toolsettings;
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode & SCE_SELECT_FACE) {
- BM_face_select_set(em->bm, l->f, false);
- }
- else if (ts->selectmode & SCE_SELECT_EDGE) {
- BM_edge_select_set(em->bm, l->e, false);
- }
- else {
- BM_vert_select_set(em->bm, l->e->v1, false);
- BM_vert_select_set(em->bm, l->e->v2, false);
- }
- }
- else {
- MLoopUV *luv1, *luv2;
-
- luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
-
- luv1->flag &= ~MLOOPUV_VERTSEL;
- luv2->flag &= ~MLOOPUV_VERTSEL;
- }
-}
-
-bool uvedit_uv_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset)
-{
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode & SCE_SELECT_FACE) {
- return BM_elem_flag_test_bool(l->f, BM_ELEM_SELECT);
- }
- else {
- return BM_elem_flag_test_bool(l->v, BM_ELEM_SELECT);
- }
- }
- else {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- return (luv->flag & MLOOPUV_VERTSEL) != 0;
- }
-}
-bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset)
-{
- return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
-}
-
-void uvedit_uv_select_set(BMEditMesh *em,
- const Scene *scene,
- BMLoop *l,
- const bool select,
- const bool do_history,
- const int cd_loop_uv_offset)
-{
- if (select) {
- uvedit_uv_select_enable(em, scene, l, do_history, cd_loop_uv_offset);
- }
- else {
- uvedit_uv_select_disable(em, scene, l, cd_loop_uv_offset);
- }
-}
-
-void uvedit_uv_select_enable(BMEditMesh *em,
- const Scene *scene,
- BMLoop *l,
- const bool do_history,
- const int cd_loop_uv_offset)
-{
- const ToolSettings *ts = scene->toolsettings;
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode & SCE_SELECT_FACE) {
- BM_face_select_set(em->bm, l->f, true);
- }
- else {
- BM_vert_select_set(em->bm, l->v, true);
- }
-
- if (do_history) {
- BM_select_history_remove(em->bm, (BMElem *)l->v);
- }
- }
- else {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag |= MLOOPUV_VERTSEL;
- }
-}
-
-void uvedit_uv_select_disable(BMEditMesh *em,
- const Scene *scene,
- BMLoop *l,
- const int cd_loop_uv_offset)
-{
- const ToolSettings *ts = scene->toolsettings;
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode & SCE_SELECT_FACE) {
- BM_face_select_set(em->bm, l->f, false);
- }
- else {
- BM_vert_select_set(em->bm, l->v, false);
- }
- }
- else {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag &= ~MLOOPUV_VERTSEL;
- }
+ r_dist[0] = pixeldist / width;
+ r_dist[1] = pixeldist / height;
}
/** \} */
@@ -696,7 +317,7 @@ void ED_uvedit_select_all(BMesh *bm)
static bool ED_uvedit_median_multi(
const Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float co[2])
{
- unsigned int sel = 0;
+ uint sel = 0;
zero_v2(co);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
@@ -771,7 +392,8 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima,
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
view_layer, ((View3D *)NULL), &objects_len);
- *r_has_select = uv_select_is_any_selected_multi(scene, sima->image, objects, objects_len);
+ *r_has_select = uvedit_select_is_any_selected_multi(
+ scene, sima->image, objects, objects_len);
MEM_freeN(objects);
}
break;
@@ -800,877 +422,6 @@ bool ED_uvedit_center_from_pivot(
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Find Nearest Elements
- * \{ */
-
-bool uv_find_nearest_edge(
- Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit)
-{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv, *luv_next;
- int i;
- bool found = false;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
-
- const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
-
- if (dist_test_sq < hit->dist_sq) {
- hit->efa = efa;
-
- hit->l = l;
- hit->luv = luv;
- hit->luv_next = luv_next;
- hit->lindex = i;
-
- hit->dist_sq = dist_test_sq;
- found = true;
- }
- }
- }
- return found;
-}
-
-bool uv_find_nearest_edge_multi(Scene *scene,
- Image *ima,
- Object **objects,
- const uint objects_len,
- const float co[2],
- UvNearestHit *hit_final)
-{
- bool found = false;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) {
- hit_final->ob = obedit;
- found = true;
- }
- }
- return found;
-}
-
-bool uv_find_nearest_face(
- Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final)
-{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- bool found = false;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- /* this will fill in hit.vert1 and hit.vert2 */
- float dist_sq_init = hit_final->dist_sq;
- UvNearestHit hit = *hit_final;
- if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
- hit.dist_sq = dist_sq_init;
- hit.l = NULL;
- hit.luv = hit.luv_next = NULL;
-
- BMIter iter;
- BMFace *efa;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
-
- float cent[2];
- uv_poly_center(efa, cent, cd_loop_uv_offset);
-
- const float dist_test_sq = len_squared_v2v2(co, cent);
-
- if (dist_test_sq < hit.dist_sq) {
- hit.efa = efa;
- hit.dist_sq = dist_test_sq;
- found = true;
- }
- }
- }
- if (found) {
- *hit_final = hit;
- }
- return found;
-}
-
-bool uv_find_nearest_face_multi(Scene *scene,
- Image *ima,
- Object **objects,
- const uint objects_len,
- const float co[2],
- UvNearestHit *hit_final)
-{
- bool found = false;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) {
- hit_final->ob = obedit;
- found = true;
- }
- }
- return found;
-}
-
-static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_loop_uv_offset)
-{
- const float *uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset))->uv;
- const float *uv_curr = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
- const float *uv_next = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset))->uv;
-
- return ((line_point_side_v2(uv_prev, uv_curr, co) > 0.0f) &&
- (line_point_side_v2(uv_next, uv_curr, co) <= 0.0f));
-}
-
-bool uv_find_nearest_vert(Scene *scene,
- Image *ima,
- Object *obedit,
- float const co[2],
- const float penalty_dist,
- UvNearestHit *hit_final)
-{
- bool found = false;
-
- /* this will fill in hit.vert1 and hit.vert2 */
- float dist_sq_init = hit_final->dist_sq;
- UvNearestHit hit = *hit_final;
- if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
- hit.dist_sq = dist_sq_init;
-
- hit.l = NULL;
- hit.luv = hit.luv_next = NULL;
-
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMIter iter;
-
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
-
- BMIter liter;
- BMLoop *l;
- int i;
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- float dist_test_sq;
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist;
- dist_test_sq = SQUARE(dist_test_sq);
- }
- else {
- dist_test_sq = len_squared_v2v2(co, luv->uv);
- }
-
- if (dist_test_sq <= hit.dist_sq) {
- if (dist_test_sq == hit.dist_sq) {
- if (!uv_nearest_between(l, co, cd_loop_uv_offset)) {
- continue;
- }
- }
-
- hit.dist_sq = dist_test_sq;
-
- hit.l = l;
- hit.luv = luv;
- hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
- hit.efa = efa;
- hit.lindex = i;
- found = true;
- }
- }
- }
- }
-
- if (found) {
- *hit_final = hit;
- }
-
- return found;
-}
-
-bool uv_find_nearest_vert_multi(Scene *scene,
- Image *ima,
- Object **objects,
- const uint objects_len,
- float const co[2],
- const float penalty_dist,
- UvNearestHit *hit_final)
-{
- bool found = false;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) {
- hit_final->ob = obedit;
- found = true;
- }
- }
- return found;
-}
-
-bool ED_uvedit_nearest_uv(const Scene *scene,
- Object *obedit,
- Image *ima,
- const float co[2],
- float *dist_sq,
- float r_uv[2])
-{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMIter iter;
- BMFace *efa;
- const float *uv_best = NULL;
- float dist_best = *dist_sq;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
- const float dist_test = len_squared_v2v2(co, uv);
- if (dist_best > dist_test) {
- dist_best = dist_test;
- uv_best = uv;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- if (uv_best != NULL) {
- copy_v2_v2(r_uv, uv_best);
- *dist_sq = dist_best;
- return true;
- }
- else {
- return false;
- }
-}
-
-bool ED_uvedit_nearest_uv_multi(const Scene *scene,
- Image *ima,
- Object **objects,
- const uint objects_len,
- const float co[2],
- float *dist_sq,
- float r_uv[2])
-{
- bool found = false;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- if (ED_uvedit_nearest_uv(scene, obedit, ima, co, dist_sq, r_uv)) {
- found = true;
- }
- }
- return found;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Loop Select
- * \{ */
-
-static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first)
-{
- UvMapVert *iterv;
- int count = 0;
-
- for (iterv = first; iterv; iterv = iterv->next) {
- if (iterv->separate && iterv != first) {
- break;
- }
-
- count++;
- }
-
- if (count < 5) {
- first->flag = 1;
- }
-}
-
-static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa, BMLoop *l)
-{
- UvMapVert *iterv, *first;
- first = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
-
- for (iterv = first; iterv; iterv = iterv->next) {
- if (iterv->separate) {
- first = iterv;
- }
- if (iterv->poly_index == BM_elem_index_get(efa)) {
- return first;
- }
- }
-
- return NULL;
-}
-
-static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em,
- UvMapVert *first1,
- UvMapVert *first2,
- int *totface)
-{
- UvMapVert *iterv1, *iterv2;
- BMFace *efa;
- int tot = 0;
-
- /* count number of faces this edge has */
- for (iterv1 = first1; iterv1; iterv1 = iterv1->next) {
- if (iterv1->separate && iterv1 != first1) {
- break;
- }
-
- for (iterv2 = first2; iterv2; iterv2 = iterv2->next) {
- if (iterv2->separate && iterv2 != first2) {
- break;
- }
-
- if (iterv1->poly_index == iterv2->poly_index) {
- /* if face already tagged, don't do this edge */
- efa = BM_face_at_index(em->bm, iterv1->poly_index);
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- return false;
- }
-
- tot++;
- break;
- }
- }
- }
-
- if (*totface == 0) { /* start edge */
- *totface = tot;
- }
- else if (tot != *totface) { /* check for same number of faces as start edge */
- return false;
- }
-
- /* tag the faces */
- for (iterv1 = first1; iterv1; iterv1 = iterv1->next) {
- if (iterv1->separate && iterv1 != first1) {
- break;
- }
-
- for (iterv2 = first2; iterv2; iterv2 = iterv2->next) {
- if (iterv2->separate && iterv2 != first2) {
- break;
- }
-
- if (iterv1->poly_index == iterv2->poly_index) {
- efa = BM_face_at_index(em->bm, iterv1->poly_index);
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- break;
- }
- }
- }
-
- return true;
-}
-
-static int uv_select_edgeloop(Scene *scene,
- Image *ima,
- Object *obedit,
- UvNearestHit *hit,
- const float limit[2],
- const bool extend)
-{
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMIter iter, liter;
- BMLoop *l;
- UvVertMap *vmap;
- UvMapVert *iterv_curr;
- UvMapVert *iterv_next;
- int starttotf;
- bool looking, select;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- /* setup */
- BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- vmap = BM_uv_vert_map_create(em->bm, limit, false, false);
-
- BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
-
- if (!extend) {
- uv_select_all_perform(scene, ima, obedit, SEL_DESELECT);
- }
-
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
-
- /* set flags for first face and verts */
- iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l);
- iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next);
- uv_select_edgeloop_vertex_loop_flag(iterv_curr);
- uv_select_edgeloop_vertex_loop_flag(iterv_next);
-
- starttotf = 0;
- uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf);
-
- /* sorry, first edge isn't even ok */
- looking = !(iterv_curr->flag == 0 && iterv_next->flag == 0);
-
- /* iterate */
- while (looking) {
- looking = false;
-
- /* find correct valence edges which are not tagged yet, but connect to tagged one */
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG) &&
- uvedit_face_visible_test(scene, obedit, ima, efa)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- /* check face not hidden and not tagged */
- if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) {
- continue;
- }
- if (!(iterv_next = uv_select_edgeloop_vertex_map_get(vmap, efa, l->next))) {
- continue;
- }
-
- /* check if vertex is tagged and has right valence */
- if (iterv_curr->flag || iterv_next->flag) {
- if (uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf)) {
- looking = true;
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
-
- uv_select_edgeloop_vertex_loop_flag(iterv_curr);
- uv_select_edgeloop_vertex_loop_flag(iterv_next);
- break;
- }
- }
- }
- }
- }
- }
-
- /* do the actual select/deselect */
- iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l);
- iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next);
- iterv_curr->flag = 1;
- iterv_next->flag = 1;
-
- if (extend) {
- select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset));
- }
- else {
- select = true;
- }
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l);
-
- if (iterv_curr->flag) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- }
- }
- }
-
- /* cleanup */
- BM_uv_vert_map_free(vmap);
-
- return (select) ? 1 : -1;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Select Linked
- * \{ */
-
-static void uv_select_linked_multi(Scene *scene,
- Image *ima,
- Object **objects,
- const uint objects_len,
- const float limit[2],
- UvNearestHit *hit_final,
- bool extend,
- bool deselect,
- bool toggle,
- bool select_faces)
-{
- /* loop over objects, or just use hit_final->ob */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- if (hit_final && ob_index != 0) {
- break;
- }
- Object *obedit = hit_final ? hit_final->ob : objects[ob_index];
-
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- UvVertMap *vmap;
- UvMapVert *vlist, *iterv, *startv;
- int i, stacksize = 0, *stack;
- unsigned int a;
- char *flag;
-
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
-
- /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320
- * this made *every* projection split the island into front/back islands.
- * Keep 'use_winding' to false, see: T50970.
- *
- * Better solve this by having a delimit option for select-linked operator,
- * keeping island-select working as is. */
- vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false);
-
- if (vmap == NULL) {
- continue;
- }
-
- stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack");
- flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag");
-
- if (hit_final == NULL) {
- /* Use existing selection */
- BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
- if (select_faces) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- stack[stacksize] = a;
- stacksize++;
- flag[a] = 1;
- }
- }
- else {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (luv->flag & MLOOPUV_VERTSEL) {
- stack[stacksize] = a;
- stacksize++;
- flag[a] = 1;
-
- break;
- }
- }
- }
- }
- }
- }
- else {
- BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- if (efa == hit_final->efa) {
- stack[stacksize] = a;
- stacksize++;
- flag[a] = 1;
- break;
- }
- }
- }
-
- while (stacksize > 0) {
-
- stacksize--;
- a = stack[stacksize];
-
- efa = BM_face_at_index(em->bm, a);
-
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
-
- /* make_uv_vert_map_EM sets verts tmp.l to the indices */
- vlist = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
-
- startv = vlist;
-
- for (iterv = vlist; iterv; iterv = iterv->next) {
- if (iterv->separate) {
- startv = iterv;
- }
- if (iterv->poly_index == a) {
- break;
- }
- }
-
- for (iterv = startv; iterv; iterv = iterv->next) {
- if ((startv != iterv) && (iterv->separate)) {
- break;
- }
- else if (!flag[iterv->poly_index]) {
- flag[iterv->poly_index] = 1;
- stack[stacksize] = iterv->poly_index;
- stacksize++;
- }
- }
- }
- }
-
- /* Toggling - if any of the linked vertices is selected (and visible), we deselect. */
- if ((toggle == true) && (extend == false) && (deselect == false)) {
- BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- bool found_selected = false;
- if (!flag[a]) {
- continue;
- }
-
- if (select_faces) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- found_selected = true;
- }
- }
- else {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (luv->flag & MLOOPUV_VERTSEL) {
- found_selected = true;
- }
- }
-
- if (found_selected) {
- deselect = true;
- break;
- }
- }
- }
- }
-
-#define SET_SELECTION(value) \
- if (select_faces) { \
- BM_face_select_set(em->bm, efa, value); \
- } \
- else { \
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { \
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); \
- luv->flag = (value) ? (luv->flag | MLOOPUV_VERTSEL) : (luv->flag & ~MLOOPUV_VERTSEL); \
- } \
- } \
- (void)0
-
- BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- if (!flag[a]) {
- if (!extend && !deselect && !toggle) {
- SET_SELECTION(false);
- }
- continue;
- }
-
- if (!deselect) {
- SET_SELECTION(true);
- }
- else {
- SET_SELECTION(false);
- }
- }
-
-#undef SET_SELECTION
-
- MEM_freeN(stack);
- MEM_freeN(flag);
- BM_uv_vert_map_free(vmap);
- }
-}
-
-/* WATCH IT: this returns first selected UV,
- * not ideal in many cases since there could be multiple */
-static float *uv_sel_co_from_eve(
- Scene *scene, Object *obedit, Image *ima, BMEditMesh *em, BMVert *eve)
-{
- BMIter liter;
- BMLoop *l;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) {
- continue;
- }
-
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- return luv->uv;
- }
- }
-
- return NULL;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Select More/Less Operator
- * \{ */
-
-static int uv_select_more_less(bContext *C, const bool select)
-{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
- SpaceImage *sima = CTX_wm_space_image(C);
-
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- const ToolSettings *ts = scene->toolsettings;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
-
- const bool is_uv_face_selectmode = (ts->uv_selectmode == UV_SELECT_FACE);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- bool changed = false;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (select) {
- EDBM_select_more(em, true);
- }
- else {
- EDBM_select_less(em, true);
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- continue;
- }
-
- if (is_uv_face_selectmode) {
-
- /* clear tags */
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
-
- /* mark loops to be selected */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
-
-#define IS_SEL 1
-#define IS_UNSEL 2
-
- int sel_state = 0;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (luv->flag & MLOOPUV_VERTSEL) {
- sel_state |= IS_SEL;
- }
- else {
- sel_state |= IS_UNSEL;
- }
-
- /* if we have a mixed selection, tag to grow it */
- if (sel_state == (IS_SEL | IS_UNSEL)) {
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- changed = true;
- break;
- }
- }
-
-#undef IS_SEL
-#undef IS_UNSEL
- }
- }
- }
- else {
-
- /* clear tags */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- BM_elem_flag_disable(l, BM_ELEM_TAG);
- }
- }
-
- /* mark loops to be selected */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
-
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (((luv->flag & MLOOPUV_VERTSEL) != 0) == select) {
- BM_elem_flag_enable(l->next, BM_ELEM_TAG);
- BM_elem_flag_enable(l->prev, BM_ELEM_TAG);
- changed = true;
- }
- }
- }
- }
- }
-
- if (changed) {
- if (is_uv_face_selectmode) {
- /* Select tagged faces. */
- uv_select_flush_from_tag_face(sima, scene, obedit, select);
- }
- else {
- /* Select tagged loops. */
- uv_select_flush_from_tag_loop(sima, scene, obedit, select);
- }
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
-}
-
-static int uv_select_more_exec(bContext *C, wmOperator *UNUSED(op))
-{
- return uv_select_more_less(C, true);
-}
-
-static void UV_OT_select_more(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select More";
- ot->description = "Select more UV vertices connected to initial selection";
- ot->idname = "UV_OT_select_more";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_select_more_exec;
- ot->poll = ED_operator_uvedit_space_image;
-}
-
-static int uv_select_less_exec(bContext *C, wmOperator *UNUSED(op))
-{
- return uv_select_more_less(C, false);
-}
-
-static void UV_OT_select_less(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Less";
- ot->description = "Deselect UV vertices at the boundary of each selection region";
- ot->idname = "UV_OT_select_less";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_select_less_exec;
- ot->poll = ED_operator_uvedit_space_image;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Weld Align Operator
* \{ */
@@ -1867,9 +618,10 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
if (BLI_array_len(eve_line) > 2) {
/* we know the returns from these must be valid */
- const float *uv_start = uv_sel_co_from_eve(scene, obedit, ima, em, eve_line[0]);
- const float *uv_end = uv_sel_co_from_eve(
- scene, obedit, ima, em, eve_line[BLI_array_len(eve_line) - 1]);
+ const float *uv_start = uvedit_first_selected_uv_from_vertex(
+ scene, obedit, ima, eve_line[0], cd_loop_uv_offset);
+ const float *uv_end = uvedit_first_selected_uv_from_vertex(
+ scene, obedit, ima, eve_line[BLI_array_len(eve_line) - 1], cd_loop_uv_offset);
/* For UV_STRAIGHTEN_X & UV_STRAIGHTEN_Y modes */
float a = 0.0f;
eUVWeldAlign tool_local = tool;
@@ -2317,1620 +1069,6 @@ static void UV_OT_weld(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name (De)Select All Operator
- * \{ */
-
-static bool uv_select_is_any_selected(Scene *scene, Image *ima, Object *obedit)
-{
- const ToolSettings *ts = scene->toolsettings;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- return (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel);
- }
- else {
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (luv->flag & MLOOPUV_VERTSEL) {
- return true;
- }
- }
- }
- }
- return false;
-}
-
-static bool uv_select_is_any_selected_multi(Scene *scene,
- Image *ima,
- Object **objects,
- const uint objects_len)
-{
- bool found = false;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- if (uv_select_is_any_selected(scene, ima, obedit)) {
- found = true;
- break;
- }
- }
- return found;
-}
-
-static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action)
-{
- const ToolSettings *ts = scene->toolsettings;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if (action == SEL_TOGGLE) {
- action = uv_select_is_any_selected(scene, ima, obedit) ? SEL_DESELECT : SEL_SELECT;
- }
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- switch (action) {
- case SEL_TOGGLE:
- EDBM_select_toggle_all(em);
- break;
- case SEL_SELECT:
- EDBM_flag_enable_all(em, BM_ELEM_SELECT);
- break;
- case SEL_DESELECT:
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- break;
- case SEL_INVERT:
- EDBM_select_swap(em);
- EDBM_selectmode_flush(em);
- break;
- }
- }
- else {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- switch (action) {
- case SEL_SELECT:
- luv->flag |= MLOOPUV_VERTSEL;
- break;
- case SEL_DESELECT:
- luv->flag &= ~MLOOPUV_VERTSEL;
- break;
- case SEL_INVERT:
- luv->flag ^= MLOOPUV_VERTSEL;
- break;
- }
- }
- }
- }
-}
-
-static void uv_select_all_perform_multi(
- Scene *scene, Image *ima, Object **objects, const uint objects_len, int action)
-{
- if (action == SEL_TOGGLE) {
- action = uv_select_is_any_selected_multi(scene, ima, objects, objects_len) ? SEL_DESELECT :
- SEL_SELECT;
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- uv_select_all_perform(scene, ima, obedit, action);
- }
-}
-
-static int uv_select_all_exec(bContext *C, wmOperator *op)
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- const ToolSettings *ts = scene->toolsettings;
- Image *ima = CTX_data_edit_image(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- int action = RNA_enum_get(op->ptr, "action");
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
-
- uv_select_all_perform_multi(scene, ima, objects, objects_len, action);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- uv_select_tag_update_for_object(depsgraph, ts, obedit);
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
-}
-
-static void UV_OT_select_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select All";
- ot->description = "Change selection of all UV vertices";
- ot->idname = "UV_OT_select_all";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_select_all_exec;
- ot->poll = ED_operator_uvedit;
-
- WM_operator_properties_select_all(ot);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Mouse Select Operator
- * \{ */
-
-static bool uv_sticky_select(
- float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen)
-{
- int i;
-
- /* this function test if some vertex needs to selected
- * in addition to the existing ones due to sticky select */
- if (sticky == SI_STICKY_DISABLE) {
- return false;
- }
-
- for (i = 0; i < hitlen; i++) {
- if (hitv[i] == v) {
- if (sticky == SI_STICKY_LOC) {
- if (fabsf(hituv[i][0] - uv[0]) < limit[0] && fabsf(hituv[i][1] - uv[1]) < limit[1]) {
- return true;
- }
- }
- else if (sticky == SI_STICKY_VERTEX) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-static int uv_mouse_select_multi(bContext *C,
- Object **objects,
- uint objects_len,
- const float co[2],
- const bool extend,
- const bool deselect_all,
- const bool loop)
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- const ToolSettings *ts = scene->toolsettings;
- Image *ima = CTX_data_edit_image(C);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- UvNearestHit hit = UV_NEAREST_HIT_INIT;
- int i, selectmode, sticky, sync, *hitv = NULL;
- bool select = true;
- bool found_item = false;
- /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
- int flush = 0;
- int hitlen = 0;
- float limit[2], **hituv = NULL;
-
- /* notice 'limit' is the same no matter the zoom level, since this is like
- * remove doubles and could annoying if it joined points when zoomed out.
- * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and
- * shift-selecting can consider an adjacent point close enough to add to
- * the selection rather than de-selecting the closest. */
-
- float penalty_dist;
- {
- float penalty[2];
- uvedit_pixel_to_float(sima, limit, 0.05f);
- uvedit_pixel_to_float(sima, penalty, 5.0f / (sima ? sima->zoom : 1.0f));
- penalty_dist = len_v2(penalty);
- }
-
- /* retrieve operation mode */
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- sync = 1;
-
- if (ts->selectmode & SCE_SELECT_FACE) {
- selectmode = UV_SELECT_FACE;
- }
- else if (ts->selectmode & SCE_SELECT_EDGE) {
- selectmode = UV_SELECT_EDGE;
- }
- else {
- selectmode = UV_SELECT_VERTEX;
- }
-
- sticky = SI_STICKY_DISABLE;
- }
- else {
- sync = 0;
- selectmode = ts->uv_selectmode;
- sticky = (sima) ? sima->sticky : 1;
- }
-
- /* find nearest element */
- if (loop) {
- /* find edge */
- found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
- }
- else if (selectmode == UV_SELECT_VERTEX) {
- /* find vertex */
- found_item = uv_find_nearest_vert_multi(
- scene, ima, objects, objects_len, co, penalty_dist, &hit);
- found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
-
- if (found_item) {
- /* mark 1 vertex as being hit */
- hitv = BLI_array_alloca(hitv, hit.efa->len);
- hituv = BLI_array_alloca(hituv, hit.efa->len);
- copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
-
- hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
- hituv[hit.lindex] = hit.luv->uv;
-
- hitlen = hit.efa->len;
- }
- }
- else if (selectmode == UV_SELECT_EDGE) {
- /* find edge */
- found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
- found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
-
- if (found_item) {
- /* mark 2 edge vertices as being hit */
- hitv = BLI_array_alloca(hitv, hit.efa->len);
- hituv = BLI_array_alloca(hituv, hit.efa->len);
- copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
-
- hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
- hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v);
- hituv[hit.lindex] = hit.luv->uv;
- hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv;
-
- hitlen = hit.efa->len;
- }
- }
- else if (selectmode == UV_SELECT_FACE) {
- /* find face */
- found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit);
- found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
-
- if (found_item) {
- BMEditMesh *em = BKE_editmesh_from_object(hit.ob);
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- /* make active */
- BM_mesh_active_face_set(em->bm, hit.efa);
-
- /* mark all face vertices as being hit */
-
- hitv = BLI_array_alloca(hitv, hit.efa->len);
- hituv = BLI_array_alloca(hituv, hit.efa->len);
- BM_ITER_ELEM_INDEX (l, &liter, hit.efa, BM_LOOPS_OF_FACE, i) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- hituv[i] = luv->uv;
- hitv[i] = BM_elem_index_get(l->v);
- }
-
- hitlen = hit.efa->len;
- }
- }
- else if (selectmode == UV_SELECT_ISLAND) {
- found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
- found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
- }
-
- if (!found_item) {
- if (deselect_all) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- uv_select_tag_update_for_object(depsgraph, ts, obedit);
- }
-
- return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
- }
-
- Object *obedit = hit.ob;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- /* do selection */
- if (loop) {
- if (!extend) {
- /* TODO(MULTI_EDIT): We only need to de-select non-active */
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
- }
- flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend);
- }
- else if (selectmode == UV_SELECT_ISLAND) {
- if (!extend) {
- /* TODO(MULTI_EDIT): We only need to de-select non-active */
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
- }
- /* Current behavior of 'extend'
- * is actually toggling, so pass extend flag as 'toggle' here */
- uv_select_linked_multi(
- scene, ima, objects, objects_len, limit, &hit, false, false, extend, false);
- }
- else if (extend) {
- if (selectmode == UV_SELECT_VERTEX) {
- /* (de)select uv vertex */
- select = !uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset);
- uvedit_uv_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset);
- flush = 1;
- }
- else if (selectmode == UV_SELECT_EDGE) {
- /* (de)select edge */
- select = !(uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset));
- uvedit_edge_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset);
- flush = 1;
- }
- else if (selectmode == UV_SELECT_FACE) {
- /* (de)select face */
- select = !(uvedit_face_select_test(scene, hit.efa, cd_loop_uv_offset));
- uvedit_face_select_set(scene, em, hit.efa, select, true, cd_loop_uv_offset);
- flush = -1;
- }
-
- /* de-selecting an edge may deselect a face too - validate */
- if (sync) {
- if (select == false) {
- BM_select_history_validate(em->bm);
- }
- }
-
- /* (de)select sticky uv nodes */
- if (sticky != SI_STICKY_DISABLE) {
-
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (uv_sticky_select(
- limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- }
- }
- }
-
- flush = select ? 1 : -1;
- }
- }
- else {
- /* deselect all */
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
-
- if (selectmode == UV_SELECT_VERTEX) {
- /* select vertex */
- uvedit_uv_select_enable(em, scene, hit.l, true, cd_loop_uv_offset);
- flush = 1;
- }
- else if (selectmode == UV_SELECT_EDGE) {
- /* select edge */
- uvedit_edge_select_enable(em, scene, hit.l, true, cd_loop_uv_offset);
- flush = 1;
- }
- else if (selectmode == UV_SELECT_FACE) {
- /* select face */
- uvedit_face_select_enable(scene, em, hit.efa, true, cd_loop_uv_offset);
- }
-
- /* select sticky uvs */
- if (sticky != SI_STICKY_DISABLE) {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (sticky == SI_STICKY_DISABLE) {
- continue;
- }
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (uv_sticky_select(
- limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) {
- uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset);
- }
-
- flush = 1;
- }
- }
- }
- }
-
- if (sync) {
- /* flush for mesh selection */
-
- /* before bmesh */
-#if 0
- if (ts->selectmode != SCE_SELECT_FACE) {
- if (flush == 1) {
- EDBM_select_flush(em);
- }
- else if (flush == -1) {
- EDBM_deselect_flush(em);
- }
- }
-#else
- if (flush != 0) {
- if (loop) {
- /* push vertex -> edge selection */
- if (select) {
- EDBM_select_flush(em);
- }
- else {
- EDBM_deselect_flush(em);
- }
- }
- else {
- EDBM_selectmode_flush(em);
- }
- }
-#endif
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obiter = objects[ob_index];
- uv_select_tag_update_for_object(depsgraph, ts, obiter);
- }
-
- return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
-}
-static int uv_mouse_select(
- bContext *C, const float co[2], const bool extend, const bool deselect_all, const bool loop)
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
- int ret = uv_mouse_select_multi(C, objects, objects_len, co, extend, deselect_all, loop);
- MEM_freeN(objects);
- return ret;
-}
-
-static int uv_select_exec(bContext *C, wmOperator *op)
-{
- float co[2];
-
- RNA_float_get_array(op->ptr, "location", co);
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
- const bool loop = false;
-
- return uv_mouse_select(C, co, extend, deselect_all, loop);
-}
-
-static int uv_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- float co[2];
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
- RNA_float_set_array(op->ptr, "location", co);
-
- return uv_select_exec(C, op);
-}
-
-static void UV_OT_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select";
- ot->description = "Select UV vertices";
- ot->idname = "UV_OT_select";
- ot->flag = OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_select_exec;
- ot->invoke = uv_select_invoke;
- ot->poll = ED_operator_uvedit; /* requires space image */
-
- /* properties */
- PropertyRNA *prop;
- RNA_def_boolean(ot->srna,
- "extend",
- 0,
- "Extend",
- "Extend selection rather than clearing the existing selection");
- prop = RNA_def_boolean(ot->srna,
- "deselect_all",
- false,
- "Deselect On Nothing",
- "Deselect all when nothing under the cursor");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- RNA_def_float_vector(
- ot->srna,
- "location",
- 2,
- NULL,
- -FLT_MAX,
- FLT_MAX,
- "Location",
- "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds",
- -100.0f,
- 100.0f);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Loop Select Operator
- * \{ */
-
-static int uv_select_loop_exec(bContext *C, wmOperator *op)
-{
- float co[2];
-
- RNA_float_get_array(op->ptr, "location", co);
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- const bool deselect_all = false;
- const bool loop = true;
-
- return uv_mouse_select(C, co, extend, deselect_all, loop);
-}
-
-static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- float co[2];
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
- RNA_float_set_array(op->ptr, "location", co);
-
- return uv_select_loop_exec(C, op);
-}
-
-static void UV_OT_select_loop(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Loop Select";
- ot->description = "Select a loop of connected UV vertices";
- ot->idname = "UV_OT_select_loop";
- ot->flag = OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_select_loop_exec;
- ot->invoke = uv_select_loop_invoke;
- ot->poll = ED_operator_uvedit; /* requires space image */
-
- /* properties */
- RNA_def_boolean(ot->srna,
- "extend",
- 0,
- "Extend",
- "Extend selection rather than clearing the existing selection");
- RNA_def_float_vector(
- ot->srna,
- "location",
- 2,
- NULL,
- -FLT_MAX,
- FLT_MAX,
- "Location",
- "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds",
- -100.0f,
- 100.0f);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Select Linked Operator
- * \{ */
-
-static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, bool pick)
-{
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- const ToolSettings *ts = scene->toolsettings;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
- float limit[2];
- bool extend = true;
- bool deselect = false;
- bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
-
- UvNearestHit hit = UV_NEAREST_HIT_INIT;
-
- if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) {
- BKE_report(op->reports,
- RPT_ERROR,
- "Select linked only works in face select mode when sync selection is enabled");
- return OPERATOR_CANCELLED;
- }
-
- if (pick) {
- extend = RNA_boolean_get(op->ptr, "extend");
- deselect = RNA_boolean_get(op->ptr, "deselect");
- }
- uvedit_pixel_to_float(sima, limit, 0.05f);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
-
- if (pick) {
- float co[2];
-
- if (event) {
- /* invoke */
- ARegion *ar = CTX_wm_region(C);
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
- RNA_float_set_array(op->ptr, "location", co);
- }
- else {
- /* exec */
- RNA_float_get_array(op->ptr, "location", co);
- }
-
- if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
- }
-
- if (!extend) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
- }
-
- uv_select_linked_multi(scene,
- ima,
- objects,
- objects_len,
- limit,
- pick ? &hit : NULL,
- extend,
- deselect,
- false,
- select_faces);
-
- /* weak!, but works */
- Object **objects_free = objects;
- if (pick) {
- objects = &hit.ob;
- objects_len = 1;
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
-
- MEM_SAFE_FREE(objects_free);
-
- return OPERATOR_FINISHED;
-}
-
-static int uv_select_linked_exec(bContext *C, wmOperator *op)
-{
- return uv_select_linked_internal(C, op, NULL, false);
-}
-
-static void UV_OT_select_linked(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Linked";
- ot->description = "Select all UV vertices linked to the active UV map";
- ot->idname = "UV_OT_select_linked";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_select_linked_exec;
- ot->poll = ED_operator_uvedit; /* requires space image */
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Select Linked (Cursor Pick) Operator
- * \{ */
-
-static int uv_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- return uv_select_linked_internal(C, op, event, true);
-}
-
-static int uv_select_linked_pick_exec(bContext *C, wmOperator *op)
-{
- return uv_select_linked_internal(C, op, NULL, true);
-}
-
-static void UV_OT_select_linked_pick(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Linked Pick";
- ot->description = "Select all UV vertices linked under the mouse";
- ot->idname = "UV_OT_select_linked_pick";
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->invoke = uv_select_linked_pick_invoke;
- ot->exec = uv_select_linked_pick_exec;
- ot->poll = ED_operator_uvedit; /* requires space image */
-
- /* properties */
- RNA_def_boolean(ot->srna,
- "extend",
- 0,
- "Extend",
- "Extend selection rather than clearing the existing selection");
- RNA_def_boolean(ot->srna,
- "deselect",
- 0,
- "Deselect",
- "Deselect linked UV vertices rather than selecting them");
- RNA_def_float_vector(
- ot->srna,
- "location",
- 2,
- NULL,
- -FLT_MAX,
- FLT_MAX,
- "Location",
- "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds",
- -100.0f,
- 100.0f);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Select Split Operator
- * \{ */
-
-/**
- * \note This is based on similar use case to #MESH_OT_split(), which has a similar effect
- * but in this case they are not joined to begin with (only having the behavior of being joined)
- * so its best to call this #uv_select_split() instead of just split(), but assigned to the same
- * key as #MESH_OT_split - Campbell.
- */
-static int uv_select_split_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const ToolSettings *ts = scene->toolsettings;
- Image *ima = CTX_data_edit_image(C);
-
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
-
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled");
- return OPERATOR_CANCELLED;
- }
-
- bool changed_multi = false;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMesh *bm = BKE_editmesh_from_object(obedit)->bm;
-
- bool changed = false;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- bool is_sel = false;
- bool is_unsel = false;
-
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
-
- /* are we all selected? */
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (luv->flag & MLOOPUV_VERTSEL) {
- is_sel = true;
- }
- else {
- is_unsel = true;
- }
-
- /* we have mixed selection, bail out */
- if (is_sel && is_unsel) {
- break;
- }
- }
-
- if (is_sel && is_unsel) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag &= ~MLOOPUV_VERTSEL;
- }
-
- changed = true;
- }
- }
-
- if (changed) {
- changed_multi = true;
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
- }
- }
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
-}
-
-static void UV_OT_select_split(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Split";
- ot->description = "Select only entirely selected faces";
- ot->idname = "UV_OT_select_split";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_select_split_exec;
- ot->poll = ED_operator_uvedit; /* requires space image */
-}
-
-static void uv_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const short select)
-{
- /* bmesh API handles flushing but not on de-select */
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (ts->selectmode != SCE_SELECT_FACE) {
- if (select == false) {
- EDBM_deselect_flush(em);
- }
- else {
- EDBM_select_flush(em);
- }
- }
-
- if (select == false) {
- BM_select_history_validate(em->bm);
- }
- }
-}
-
-static void uv_select_tag_update_for_object(Depsgraph *depsgraph,
- const ToolSettings *ts,
- Object *obedit)
-{
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data);
- }
- else {
- Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
- BKE_mesh_batch_cache_dirty_tag(obedit_eval->data, BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT);
- /* Only for region redraw. */
- WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data);
- }
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Select/Tag Flushing Utils
- *
- * Utility functions to flush the uv-selection from tags.
- * \{ */
-
-/**
- * helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face
- */
-static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene,
- BMEditMesh *em,
- UvVertMap *vmap,
- const unsigned int efa_index,
- BMLoop *l,
- const bool select,
- const int cd_loop_uv_offset)
-{
- UvMapVert *start_vlist = NULL, *vlist_iter;
- BMFace *efa_vlist;
-
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
-
- vlist_iter = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
-
- while (vlist_iter) {
- if (vlist_iter->separate) {
- start_vlist = vlist_iter;
- }
-
- if (efa_index == vlist_iter->poly_index) {
- break;
- }
-
- vlist_iter = vlist_iter->next;
- }
-
- vlist_iter = start_vlist;
- while (vlist_iter) {
-
- if (vlist_iter != start_vlist && vlist_iter->separate) {
- break;
- }
-
- if (efa_index != vlist_iter->poly_index) {
- BMLoop *l_other;
- efa_vlist = BM_face_at_index(em->bm, vlist_iter->poly_index);
- /* tf_vlist = BM_ELEM_CD_GET_VOID_P(efa_vlist, cd_poly_tex_offset); */ /* UNUSED */
-
- l_other = BM_iter_at_index(
- em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->loop_of_poly_index);
-
- uvedit_uv_select_set(em, scene, l_other, select, false, cd_loop_uv_offset);
- }
- vlist_iter = vlist_iter->next;
- }
-}
-
-/**
- * Flush the selection from face tags based on sticky and selection modes.
- *
- * needed because settings the selection a face is done in a number of places but it also
- * needs to respect the sticky modes for the UV verts, so dealing with the sticky modes
- * is best done in a separate function.
- *
- * \note This function is very similar to #uv_select_flush_from_tag_loop,
- * be sure to update both upon changing.
- */
-static void uv_select_flush_from_tag_face(SpaceImage *sima,
- Scene *scene,
- Object *obedit,
- const bool select)
-{
- /* Selecting UV Faces with some modes requires us to change
- * the selection in other faces (depending on the sticky mode).
- *
- * This only needs to be done when the Mesh is not used for
- * selection (so for sticky modes, vertex or location based). */
-
- const ToolSettings *ts = scene->toolsettings;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) {
- /* Tag all verts as untouched, then touch the ones that have a face center
- * in the loop and select all MLoopUV's that use a touched vert. */
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
- }
- }
- }
-
- /* now select tagged verts */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- }
- }
- }
- }
- else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) {
- struct UvVertMap *vmap;
- float limit[2];
- unsigned int efa_index;
-
- uvedit_pixel_to_float(sima, limit, 0.05);
-
- BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- vmap = BM_uv_vert_map_create(em->bm, limit, false, false);
- if (vmap == NULL) {
- return;
- }
-
- BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- uv_select_flush_from_tag_sticky_loc_internal(
- scene, em, vmap, efa_index, l, select, cd_loop_uv_offset);
- }
- }
- }
- BM_uv_vert_map_free(vmap);
- }
- else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- uvedit_face_select_set(scene, em, efa, select, false, cd_loop_uv_offset);
- }
- }
- }
-}
-
-/**
- * Flush the selection from loop tags based on sticky and selection modes.
- *
- * needed because settings the selection a face is done in a number of places but it also needs
- * to respect the sticky modes for the UV verts, so dealing with the sticky modes is best done
- * in a separate function.
- *
- * \note This function is very similar to #uv_select_flush_from_tag_loop,
- * be sure to update both upon changing.
- */
-static void uv_select_flush_from_tag_loop(SpaceImage *sima,
- Scene *scene,
- Object *obedit,
- const bool select)
-{
- /* Selecting UV Loops with some modes requires us to change
- * the selection in other faces (depending on the sticky mode).
- *
- * This only needs to be done when the Mesh is not used for
- * selection (so for sticky modes, vertex or location based). */
-
- const ToolSettings *ts = scene->toolsettings;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) {
- /* Tag all verts as untouched, then touch the ones that have a face center
- * in the loop and select all MLoopUV's that use a touched vert. */
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
- }
- }
- }
-
- /* now select tagged verts */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- }
- }
- }
- }
- else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) {
- struct UvVertMap *vmap;
- float limit[2];
- unsigned int efa_index;
-
- uvedit_pixel_to_float(sima, limit, 0.05);
-
- BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- vmap = BM_uv_vert_map_create(em->bm, limit, false, false);
- if (vmap == NULL) {
- return;
- }
-
- BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) {
- /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
- uv_select_flush_from_tag_sticky_loc_internal(
- scene, em, vmap, efa_index, l, select, cd_loop_uv_offset);
- }
- }
- }
- BM_uv_vert_map_free(vmap);
- }
- else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- }
- }
- }
- }
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Box Select Operator
- * \{ */
-
-static int uv_box_select_exec(bContext *C, wmOperator *op)
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- const ToolSettings *ts = scene->toolsettings;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
- ARegion *ar = CTX_wm_region(C);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- rctf rectf;
- bool pinned;
- const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ?
- (ts->selectmode == SCE_SELECT_FACE) :
- (ts->uv_selectmode == UV_SELECT_FACE));
-
- /* get rectangle from operator */
- WM_operator_properties_border_to_rctf(op, &rectf);
- UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf);
-
- const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- const bool select = (sel_op != SEL_OP_SUB);
- const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op);
-
- pinned = RNA_boolean_get(op->ptr, "pinned");
-
- bool changed_multi = false;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
-
- if (use_pre_deselect) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
- }
-
- /* don't indent to avoid diff noise! */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- bool changed = false;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- /* do actual selection */
- if (use_face_center && !pinned) {
- /* handle face selection mode */
- float cent[2];
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- /* assume not touched */
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
-
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
- uv_poly_center(efa, cent, cd_loop_uv_offset);
- if (BLI_rctf_isect_pt_v(&rectf, cent)) {
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- changed = true;
- }
- }
- }
-
- /* (de)selects all tagged faces and deals with sticky modes */
- if (changed) {
- uv_select_flush_from_tag_face(sima, scene, obedit, select);
- }
- }
- else {
- /* other selection modes */
- changed = true;
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) {
-
- /* UV_SYNC_SELECTION - can't do pinned selection */
- if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
- }
- }
- else if (pinned) {
- if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
- }
- }
- }
- }
-
- if (sima->sticky == SI_STICKY_VERTEX) {
- uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
- }
- }
-
- if (changed || use_pre_deselect) {
- changed_multi = true;
-
- uv_select_sync_flush(ts, em, select);
- uv_select_tag_update_for_object(depsgraph, ts, obedit);
- }
- }
-
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
-}
-
-static void UV_OT_select_box(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Box Select";
- ot->description = "Select UV vertices using box selection";
- ot->idname = "UV_OT_select_box";
-
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = uv_box_select_exec;
- ot->modal = WM_gesture_box_modal;
- ot->poll = ED_operator_uvedit_space_image; /* requires space image */
- ot->cancel = WM_gesture_box_cancel;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only");
-
- WM_operator_properties_gesture_box(ot);
- WM_operator_properties_select_operation_simple(ot);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Circle Select Operator
- * \{ */
-
-static int uv_inside_circle(const float uv[2], const float offset[2], const float ellipse[2])
-{
- /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
- float x, y;
- x = (uv[0] - offset[0]) * ellipse[0];
- y = (uv[1] - offset[1]) * ellipse[1];
- return ((x * x + y * y) < 1.0f);
-}
-
-static int uv_circle_select_exec(bContext *C, wmOperator *op)
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const ToolSettings *ts = scene->toolsettings;
- ARegion *ar = CTX_wm_region(C);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
- int x, y, radius, width, height;
- float zoomx, zoomy, offset[2], ellipse[2];
-
- const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ?
- (ts->selectmode == SCE_SELECT_FACE) :
- (ts->uv_selectmode == UV_SELECT_FACE));
-
- /* get operator properties */
- x = RNA_int_get(op->ptr, "x");
- y = RNA_int_get(op->ptr, "y");
- radius = RNA_int_get(op->ptr, "radius");
-
- /* compute ellipse size and location, not a circle since we deal
- * with non square image. ellipse is normalized, r = 1.0. */
- ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
-
- ellipse[0] = width * zoomx / radius;
- ellipse[1] = height * zoomy / radius;
-
- UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
-
- bool changed_multi = false;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
-
- const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
- WM_gesture_is_modal_first(op->customdata));
- const bool select = (sel_op != SEL_OP_SUB);
- const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op);
-
- if (use_pre_deselect) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- bool changed = false;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- /* do selection */
- if (use_face_center) {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- /* assume not touched */
- if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
- float cent[2];
- uv_poly_center(efa, cent, cd_loop_uv_offset);
- if (uv_inside_circle(cent, offset, ellipse)) {
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- changed = true;
- }
- }
- }
-
- /* (de)selects all tagged faces and deals with sticky modes */
- if (changed) {
- uv_select_flush_from_tag_face(sima, scene, obedit, select);
- }
- }
- else {
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (uv_inside_circle(luv->uv, offset, ellipse)) {
- changed = true;
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
- }
- }
- }
-
- if (sima->sticky == SI_STICKY_VERTEX) {
- uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
- }
- }
-
- if (changed || use_pre_deselect) {
- changed_multi = true;
-
- uv_select_sync_flush(ts, em, select);
- uv_select_tag_update_for_object(depsgraph, ts, obedit);
- }
- }
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
-}
-
-static void UV_OT_select_circle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Circle Select";
- ot->description = "Select UV vertices using circle selection";
- ot->idname = "UV_OT_select_circle";
-
- /* api callbacks */
- ot->invoke = WM_gesture_circle_invoke;
- ot->modal = WM_gesture_circle_modal;
- ot->exec = uv_circle_select_exec;
- ot->poll = ED_operator_uvedit_space_image; /* requires space image */
- ot->cancel = WM_gesture_circle_cancel;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_gesture_circle(ot);
- WM_operator_properties_select_operation_simple(ot);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Lasso Select Operator
- * \{ */
-
-static bool do_lasso_select_mesh_uv(bContext *C,
- const int mcords[][2],
- short moves,
- const eSelectOp sel_op)
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- const ToolSettings *ts = scene->toolsettings;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ?
- (ts->selectmode == SCE_SELECT_FACE) :
- (ts->uv_selectmode == UV_SELECT_FACE));
- const bool select = (sel_op != SEL_OP_SUB);
- const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op);
-
- BMIter iter, liter;
-
- BMFace *efa;
- BMLoop *l;
- int screen_uv[2];
- bool changed_multi = false;
- rcti rect;
-
- BLI_lasso_boundbox(&rect, mcords, moves);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
-
- if (use_pre_deselect) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
- }
-
- /* don't indent to avoid diff noise! */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
-
- bool changed = false;
-
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if (use_face_center) { /* Face Center Sel */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- /* assume not touched */
- if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
- float cent[2];
- uv_poly_center(efa, cent, cd_loop_uv_offset);
-
- if (UI_view2d_view_to_region_clip(
- &ar->v2d, cent[0], cent[1], &screen_uv[0], &screen_uv[1]) &&
- BLI_rcti_isect_pt_v(&rect, screen_uv) &&
- BLI_lasso_is_point_inside(
- mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) {
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- changed = true;
- }
- }
- }
-
- /* (de)selects all tagged faces and deals with sticky modes */
- if (changed) {
- uv_select_flush_from_tag_face(sima, scene, obedit, select);
- }
- }
- else { /* Vert Sel */
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (UI_view2d_view_to_region_clip(
- &ar->v2d, luv->uv[0], luv->uv[1], &screen_uv[0], &screen_uv[1]) &&
- BLI_rcti_isect_pt_v(&rect, screen_uv) &&
- BLI_lasso_is_point_inside(
- mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- changed = true;
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
- }
- }
- }
- }
- }
-
- if (sima->sticky == SI_STICKY_VERTEX) {
- uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
- }
- }
-
- if (changed || use_pre_deselect) {
- changed_multi = true;
-
- uv_select_sync_flush(ts, em, select);
- uv_select_tag_update_for_object(depsgraph, ts, obedit);
- }
- }
- MEM_freeN(objects);
-
- return changed_multi;
-}
-
-static int uv_lasso_select_exec(bContext *C, wmOperator *op)
-{
- int mcords_tot;
- const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
-
- if (mcords) {
- const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- bool changed = do_lasso_select_mesh_uv(C, mcords, mcords_tot, sel_op);
- MEM_freeN((void *)mcords);
-
- return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
- }
-
- return OPERATOR_PASS_THROUGH;
-}
-
-static void UV_OT_select_lasso(wmOperatorType *ot)
-{
- ot->name = "Lasso Select UV";
- ot->description = "Select UVs using lasso selection";
- ot->idname = "UV_OT_select_lasso";
-
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = uv_lasso_select_exec;
- ot->poll = ED_operator_uvedit_space_image;
- ot->cancel = WM_gesture_lasso_cancel;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_gesture_lasso(ot);
- WM_operator_properties_select_operation_simple(ot);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Snap Cursor Operator
* \{ */
@@ -4335,314 +1473,6 @@ static void UV_OT_pin(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Select Pinned UV's Operator
- * \{ */
-
-static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- const ToolSettings *ts = scene->toolsettings;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- bool changed = false;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
- }
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- if (luv->flag & MLOOPUV_PINNED) {
- uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset);
- changed = true;
- }
- }
- }
-
- if (changed) {
- uv_select_tag_update_for_object(depsgraph, ts, obedit);
- }
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
-}
-
-static void UV_OT_select_pinned(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Selected Pinned";
- ot->description = "Select all pinned UV vertices";
- ot->idname = "UV_OT_select_pinned";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_select_pinned_exec;
- ot->poll = ED_operator_uvedit;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Select Overlap Operator
- * \{ */
-
-BLI_INLINE uint overlap_hash(const void *overlap_v)
-{
- const BVHTreeOverlap *overlap = overlap_v;
-
- /* Designed to treat (A,B) and (B,A) as the same. */
- int x = overlap->indexA;
- int y = overlap->indexB;
- if (x > y) {
- SWAP(int, x, y);
- }
- return BLI_hash_int_2d(x, y);
-}
-
-BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v)
-{
- const BVHTreeOverlap *a = a_v;
- const BVHTreeOverlap *b = b_v;
- return !((a->indexA == b->indexA && a->indexB == b->indexB) ||
- (a->indexA == b->indexB && a->indexB == b->indexA));
-}
-
-struct UVOverlapData {
- int ob_index;
- int face_index;
- float tri[3][2];
-};
-
-static int uv_select_overlap(bContext *C, const bool extend)
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, ((View3D *)NULL), &objects_len);
-
- /* Calculate maximum number of tree nodes and prepare initial selection. */
- uint uv_tri_len = 0;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
- if (!extend) {
- uv_select_all_perform(scene, ima, obedit, SEL_DESELECT);
- }
-
- BMIter iter;
- BMFace *efa;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) {
- continue;
- }
- uv_tri_len += efa->len - 2;
- }
- }
-
- struct UVOverlapData *overlap_data = MEM_mallocN(sizeof(struct UVOverlapData) * uv_tri_len,
- "UvOverlapData");
- BVHTree *uv_tree = BLI_bvhtree_new(uv_tri_len, 0.0f, 4, 6);
-
- /* Use a global data index when inserting into the BVH. */
- int data_index = 0;
-
- int face_len_alloc = 3;
- float(*uv_verts)[2] = MEM_mallocN(sizeof(*uv_verts) * face_len_alloc, "UvOverlapCoords");
- uint(*indices)[3] = MEM_mallocN(sizeof(*indices) * (face_len_alloc - 2), "UvOverlapTris");
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMIter iter, liter;
- BMFace *efa;
- BMLoop *l;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- /* Triangulate each UV face and store it inside the BVH. */
- int face_index;
- BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, face_index) {
-
- if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) {
- continue;
- }
-
- const uint face_len = efa->len;
- const uint tri_len = face_len - 2;
-
- if (face_len_alloc < face_len) {
- MEM_freeN(uv_verts);
- MEM_freeN(indices);
- uv_verts = MEM_mallocN(sizeof(*uv_verts) * face_len, "UvOverlapCoords");
- indices = MEM_mallocN(sizeof(*indices) * tri_len, "UvOverlapTris");
- face_len_alloc = face_len;
- }
-
- int vert_index;
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, vert_index) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(uv_verts[vert_index], luv->uv);
- }
-
- BLI_polyfill_calc(uv_verts, face_len, 0, indices);
-
- for (int t = 0; t < tri_len; t++) {
- overlap_data[data_index].ob_index = ob_index;
- overlap_data[data_index].face_index = face_index;
-
- /* BVH needs 3D, overlap data uses 2D. */
- const float tri[3][3] = {
- {UNPACK2(uv_verts[indices[t][0]]), 0.0f},
- {UNPACK2(uv_verts[indices[t][1]]), 0.0f},
- {UNPACK2(uv_verts[indices[t][2]]), 0.0f},
- };
-
- copy_v2_v2(overlap_data[data_index].tri[0], tri[0]);
- copy_v2_v2(overlap_data[data_index].tri[1], tri[1]);
- copy_v2_v2(overlap_data[data_index].tri[2], tri[2]);
-
- BLI_bvhtree_insert(uv_tree, data_index, &tri[0][0], 3);
- data_index++;
- }
- }
- }
- BLI_assert(data_index == uv_tri_len);
-
- MEM_freeN(uv_verts);
- MEM_freeN(indices);
-
- BLI_bvhtree_balance(uv_tree);
-
- uint tree_overlap_len;
- BVHTreeOverlap *overlap = BLI_bvhtree_overlap(uv_tree, uv_tree, &tree_overlap_len, NULL, NULL);
-
- if (overlap != NULL) {
- GSet *overlap_set = BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, tree_overlap_len);
-
- for (int i = 0; i < tree_overlap_len; i++) {
- /* Skip overlaps against yourself. */
- if (overlap[i].indexA == overlap[i].indexB) {
- continue;
- }
-
- /* Skip overlaps that have already been tested. */
- if (!BLI_gset_add(overlap_set, &overlap[i])) {
- continue;
- }
-
- const struct UVOverlapData *o_a = &overlap_data[overlap[i].indexA];
- const struct UVOverlapData *o_b = &overlap_data[overlap[i].indexB];
- Object *obedit_a = objects[o_a->ob_index];
- Object *obedit_b = objects[o_b->ob_index];
- BMEditMesh *em_a = BKE_editmesh_from_object(obedit_a);
- BMEditMesh *em_b = BKE_editmesh_from_object(obedit_b);
- BMFace *face_a = em_a->bm->ftable[o_a->face_index];
- BMFace *face_b = em_b->bm->ftable[o_b->face_index];
- const int cd_loop_uv_offset_a = CustomData_get_offset(&em_a->bm->ldata, CD_MLOOPUV);
- const int cd_loop_uv_offset_b = CustomData_get_offset(&em_b->bm->ldata, CD_MLOOPUV);
-
- /* Skip if both faces are already selected. */
- if (uvedit_face_select_test(scene, face_a, cd_loop_uv_offset_a) &&
- uvedit_face_select_test(scene, face_b, cd_loop_uv_offset_b)) {
- continue;
- }
-
- /* Main tri-tri overlap test. */
- const float endpoint_bias = -1e-4f;
- const float(*t1)[2] = o_a->tri;
- const float(*t2)[2] = o_b->tri;
- float vi[2];
- bool result = (
- /* Don't use 'isect_tri_tri_v2' here
- * because it's important to ignore overlap at end-points. */
- isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[0], t2[1], endpoint_bias, vi) == 1 ||
- isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[1], t2[2], endpoint_bias, vi) == 1 ||
- isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[2], t2[0], endpoint_bias, vi) == 1 ||
- isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[0], t2[1], endpoint_bias, vi) == 1 ||
- isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[1], t2[2], endpoint_bias, vi) == 1 ||
- isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[2], t2[0], endpoint_bias, vi) == 1 ||
- isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[0], t2[1], endpoint_bias, vi) == 1 ||
- isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[1], t2[2], endpoint_bias, vi) == 1 ||
- isect_point_tri_v2(t1[0], t2[0], t2[1], t2[2]) != 0 ||
- isect_point_tri_v2(t2[0], t1[0], t1[1], t1[2]) != 0);
-
- if (result) {
- uvedit_face_select_enable(scene, em_a, face_a, false, cd_loop_uv_offset_a);
- uvedit_face_select_enable(scene, em_b, face_b, false, cd_loop_uv_offset_b);
- }
- }
-
- BLI_gset_free(overlap_set, NULL);
- MEM_freeN(overlap);
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- uv_select_tag_update_for_object(depsgraph, scene->toolsettings, objects[ob_index]);
- }
-
- BLI_bvhtree_free(uv_tree);
-
- MEM_freeN(overlap_data);
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
-}
-
-static int uv_select_overlap_exec(bContext *C, wmOperator *op)
-{
- bool extend = RNA_boolean_get(op->ptr, "extend");
- return uv_select_overlap(C, extend);
-}
-
-static void UV_OT_select_overlap(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Overlap";
- ot->description = "Select all UV faces which overlap each other";
- ot->idname = "UV_OT_select_overlap";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = uv_select_overlap_exec;
- ot->poll = ED_operator_uvedit;
-
- /* properties */
- RNA_def_boolean(ot->srna,
- "extend",
- 0,
- "Extend",
- "Extend selection rather than clearing the existing selection");
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Hide Operator
* \{ */
@@ -4670,99 +1500,109 @@ static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test, const int cd_loop
static int uv_hide_exec(bContext *C, wmOperator *op)
{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceImage *sima = CTX_wm_space_image(C);
- Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
const bool swap = RNA_boolean_get(op->ptr, "unselected");
Image *ima = sima ? sima->image : NULL;
const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (EDBM_mesh_hide(em, swap)) {
- EDBM_update_generic(obedit->data, true, false);
- }
- return OPERATOR_FINISHED;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- int hide = 0;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
- continue;
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (EDBM_mesh_hide(em, swap)) {
+ EDBM_update_generic(ob->data, true, false);
+ }
+ return OPERATOR_FINISHED;
}
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ int hide = 0;
- if (UV_SEL_TEST(luv, !swap)) {
- hide = 1;
- break;
+ if (!uvedit_face_visible_test(scene, ob, ima, efa)) {
+ continue;
}
- }
- if (hide) {
- /* note, a special case for edges could be used,
- * for now edges act like verts and get flushed */
- if (use_face_center) {
- if (em->selectmode == SCE_SELECT_FACE) {
- /* check that every UV is selected */
- if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) {
- BM_face_select_set(em->bm, efa, false);
- }
- uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset);
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ if (UV_SEL_TEST(luv, !swap)) {
+ hide = 1;
+ break;
}
- else {
- if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (UV_SEL_TEST(luv, !swap)) {
- BM_vert_select_set(em->bm, l->v, false);
+ }
+
+ if (hide) {
+ /* note, a special case for edges could be used,
+ * for now edges act like verts and get flushed */
+ if (use_face_center) {
+ if (em->selectmode == SCE_SELECT_FACE) {
+ /* check that every UV is selected */
+ if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) {
+ BM_face_select_set(em->bm, efa, false);
+ }
+ uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset);
+ }
+ else {
+ if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (UV_SEL_TEST(luv, !swap)) {
+ BM_vert_select_set(em->bm, l->v, false);
+ }
}
}
+ if (!swap) {
+ uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset);
+ }
}
- if (!swap) {
+ }
+ else if (em->selectmode == SCE_SELECT_FACE) {
+ /* check if a UV is de-selected */
+ if (bm_face_is_all_uv_sel(efa, false, cd_loop_uv_offset) != !swap) {
+ BM_face_select_set(em->bm, efa, false);
uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset);
}
}
- }
- else if (em->selectmode == SCE_SELECT_FACE) {
- /* check if a UV is de-selected */
- if (bm_face_is_all_uv_sel(efa, false, cd_loop_uv_offset) != !swap) {
- BM_face_select_set(em->bm, efa, false);
- uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset);
- }
- }
- else {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (UV_SEL_TEST(luv, !swap)) {
- BM_vert_select_set(em->bm, l->v, false);
- if (!swap) {
- luv->flag &= ~MLOOPUV_VERTSEL;
+ else {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (UV_SEL_TEST(luv, !swap)) {
+ BM_vert_select_set(em->bm, l->v, false);
+ if (!swap) {
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
}
}
}
}
}
- }
- /* flush vertex selection changes */
- if (em->selectmode != SCE_SELECT_FACE) {
- EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX | SCE_SELECT_EDGE);
- }
+ /* flush vertex selection changes */
+ if (em->selectmode != SCE_SELECT_FACE) {
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX | SCE_SELECT_EDGE);
+ }
- BM_select_history_validate(em->bm);
+ BM_select_history_validate(em->bm);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ }
+
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -4793,119 +1633,131 @@ static void UV_OT_hide(wmOperatorType *ot)
static int uv_reveal_exec(bContext *C, wmOperator *op)
{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceImage *sima = CTX_wm_space_image(C);
- Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- MLoopUV *luv;
+
const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1;
+ const bool select = RNA_boolean_get(op->ptr, "select");
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
- const bool select = RNA_boolean_get(op->ptr, "select");
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
- /* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and
- * confuse our checks on selected verts. */
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- /* call the mesh function if we are in mesh sync sel */
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- if (EDBM_mesh_reveal(em, select)) {
- EDBM_update_generic(obedit->data, true, false);
- }
- return OPERATOR_FINISHED;
- }
- if (use_face_center) {
- if (em->selectmode == SCE_SELECT_FACE) {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
- }
- /* BM_face_select_set(em->bm, efa, true); */
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- }
+ /* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and
+ * confuse our checks on selected verts. */
+
+ /* call the mesh function if we are in mesh sync sel */
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (EDBM_mesh_reveal(em, select)) {
+ EDBM_update_generic(ob->data, true, false);
}
+ return OPERATOR_FINISHED;
}
- else {
- /* enable adjacent faces to have disconnected UV selections if sticky is disabled */
- if (!stickymode) {
+ if (use_face_center) {
+ if (em->selectmode == SCE_SELECT_FACE) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- int totsel = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- totsel += BM_elem_flag_test(l->v, BM_ELEM_SELECT);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
}
-
- if (!totsel) {
+ /* BM_face_select_set(em->bm, efa, true); */
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ }
+ }
+ }
+ else {
+ /* enable adjacent faces to have disconnected UV selections if sticky is disabled */
+ if (!stickymode) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) &&
+ !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ int totsel = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
+ totsel += BM_elem_flag_test(l->v, BM_ELEM_SELECT);
+ }
+
+ if (!totsel) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
+ }
+ /* BM_face_select_set(em->bm, efa, true); */
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
- /* BM_face_select_set(em->bm, efa, true); */
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
}
}
- }
- else {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
+ else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) &&
+ !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
+ }
}
+ /* BM_face_select_set(em->bm, efa, true); */
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
- /* BM_face_select_set(em->bm, efa, true); */
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
}
}
}
- }
- else if (em->selectmode == SCE_SELECT_FACE) {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
+ else if (em->selectmode == SCE_SELECT_FACE) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
+ }
+ /* BM_face_select_set(em->bm, efa, true); */
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
- /* BM_face_select_set(em->bm, efa, true); */
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
}
- }
- else {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
+ else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
+ }
}
+ /* BM_face_select_set(em->bm, efa, true); */
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
- /* BM_face_select_set(em->bm, efa, true); */
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
}
- }
- /* re-select tagged faces */
- BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
+ /* re-select tagged faces */
+ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
+
+ DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ }
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -4954,10 +1806,10 @@ static int uv_set_2d_cursor_exec(bContext *C, wmOperator *op)
static int uv_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
float location[2];
- if (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
if (event->mval[1] <= 16) {
SpaceImage *sima = CTX_wm_space_image(C);
if (sima && ED_space_image_show_cache(sima)) {
@@ -4966,7 +1818,8 @@ static int uv_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
}
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
RNA_float_set_array(op->ptr, "location", location);
return uv_set_2d_cursor_exec(C, op);
@@ -5153,6 +2006,8 @@ static void UV_OT_seams_from_islands(wmOperatorType *ot)
static int uv_mark_seam_exec(bContext *C, wmOperator *op)
{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = sima ? sima->image : NULL;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
const ToolSettings *ts = scene->toolsettings;
@@ -5183,10 +2038,12 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
- if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) {
- BM_elem_flag_set(loop->e, BM_ELEM_SEAM, flag_set);
- changed = true;
+ if (uvedit_face_visible_test(scene, ob, ima, efa)) {
+ BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) {
+ BM_elem_flag_set(loop->e, BM_ELEM_SEAM, flag_set);
+ changed = true;
+ }
}
}
}
@@ -5263,6 +2120,7 @@ static void UV_OT_mark_seam(wmOperatorType *ot)
void ED_operatortypes_uvedit(void)
{
+ /* uvedit_select.c */
WM_operatortype_append(UV_OT_select_all);
WM_operatortype_append(UV_OT_select);
WM_operatortype_append(UV_OT_select_loop);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index e4d73c2b229..da8e0efa522 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -20,21 +20,21 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
-#include "BLI_memarena.h"
-#include "BLI_math.h"
-#include "BLI_rand.h"
-#include "BLI_heap.h"
#include "BLI_boxpack_2d.h"
#include "BLI_convexhull_2d.h"
+#include "BLI_heap.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
#include "BLI_polyfill_2d.h"
#include "BLI_polyfill_2d_beautify.h"
+#include "BLI_rand.h"
+#include "BLI_utildefines.h"
#include "uvedit_parametrizer.h"
#include <math.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "BLI_sys_types.h" /* for intptr_t support */
@@ -107,7 +107,7 @@ typedef struct PVert {
struct PEdge *edge;
float co[3];
float uv[2];
- unsigned char flag;
+ uchar flag;
} PVert;
@@ -126,7 +126,7 @@ typedef struct PEdge {
struct PEdge *next;
struct PFace *face;
float *orig_uv, old_uv[2];
- unsigned short flag;
+ ushort flag;
} PEdge;
@@ -141,7 +141,7 @@ typedef struct PFace {
} u;
struct PEdge *edge;
- unsigned char flag;
+ uchar flag;
} PFace;
enum PVertFlag {
@@ -197,7 +197,7 @@ typedef struct PChart {
} pack;
} u;
- unsigned char flag;
+ uchar flag;
struct PHandle *handle;
} PChart;
@@ -245,7 +245,7 @@ static int PHashSizes[] = {
1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459,
};
-#define PHASH_hash(ph, item) (((uintptr_t)(item)) % ((unsigned int)(ph)->cursize))
+#define PHASH_hash(ph, item) (((uintptr_t)(item)) % ((uint)(ph)->cursize))
#define PHASH_edge(v1, v2) (((v1) < (v2)) ? ((v1)*39) ^ ((v2)*31) : ((v1)*31) ^ ((v2)*39))
static PHash *phash_new(PHashLink **list, int sizehint)
@@ -347,7 +347,7 @@ static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link)
/* Geometry */
-static float p_vec_angle_cos(float *v1, float *v2, float *v3)
+static float p_vec_angle_cos(const float v1[3], const float v2[3], const float v3[3])
{
float d1[3], d2[3];
@@ -365,7 +365,7 @@ static float p_vec_angle_cos(float *v1, float *v2, float *v3)
return d1[0] * d2[0] + d1[1] * d2[1] + d1[2] * d2[2];
}
-static float p_vec_angle(float *v1, float *v2, float *v3)
+static float p_vec_angle(const float v1[3], const float v2[3], const float v3[3])
{
float dot = p_vec_angle_cos(v1, v2, v3);
@@ -380,7 +380,7 @@ static float p_vec_angle(float *v1, float *v2, float *v3)
}
}
-static float p_vec2_angle(float *v1, float *v2, float *v3)
+static float p_vec2_angle(const float v1[2], const float v2[2], const float v3[2])
{
float u1[3], u2[3], u3[3];
@@ -397,19 +397,20 @@ static float p_vec2_angle(float *v1, float *v2, float *v3)
return p_vec_angle(u1, u2, u3);
}
-static void p_triangle_angles(float *v1, float *v2, float *v3, float *a1, float *a2, float *a3)
+static void p_triangle_angles(
+ const float v1[3], const float v2[3], const float v3[3], float *r_a1, float *r_a2, float *r_a3)
{
- *a1 = p_vec_angle(v3, v1, v2);
- *a2 = p_vec_angle(v1, v2, v3);
- *a3 = (float)M_PI - *a2 - *a1;
+ *r_a1 = p_vec_angle(v3, v1, v2);
+ *r_a2 = p_vec_angle(v1, v2, v3);
+ *r_a3 = (float)M_PI - *r_a2 - *r_a1;
}
-static void p_face_angles(PFace *f, float *a1, float *a2, float *a3)
+static void p_face_angles(PFace *f, float *r_a1, float *r_a2, float *r_a3)
{
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
- p_triangle_angles(v1->co, v2->co, v3->co, a1, a2, a3);
+ p_triangle_angles(v1->co, v2->co, v3->co, r_a1, r_a2, r_a3);
}
static float p_face_area(PFace *f)
@@ -420,7 +421,7 @@ static float p_face_area(PFace *f)
return area_tri_v3(v1->co, v2->co, v3->co);
}
-static float p_area_signed(float *v1, float *v2, float *v3)
+static float p_area_signed(const float v1[2], const float v2[2], const float v3[2])
{
return 0.5f * (((v2[0] - v1[0]) * (v3[1] - v1[1])) - ((v3[0] - v1[0]) * (v2[1] - v1[1])));
}
@@ -503,14 +504,14 @@ static void p_chart_uv_transform(PChart *chart, float mat[2][2])
PVert *v;
for (v = chart->verts; v; v = v->nextlink) {
- mul_m2v2(mat, v->uv);
+ mul_m2_v2(mat, v->uv);
}
}
static void p_chart_uv_to_array(PChart *chart, float (*points)[2])
{
PVert *v;
- unsigned int i = 0;
+ uint i = 0;
for (v = chart->verts; v; v = v->nextlink) {
copy_v2_v2(points[i++], v->uv);
@@ -520,14 +521,18 @@ static void p_chart_uv_to_array(PChart *chart, float (*points)[2])
static void UNUSED_FUNCTION(p_chart_uv_from_array)(PChart *chart, float (*points)[2])
{
PVert *v;
- unsigned int i = 0;
+ uint i = 0;
for (v = chart->verts; v; v = v->nextlink) {
copy_v2_v2(v->uv, points[i++]);
}
}
-static PBool p_intersect_line_2d_dir(float *v1, float *dir1, float *v2, float *dir2, float *isect)
+static PBool p_intersect_line_2d_dir(const float v1[2],
+ const float dir1[2],
+ const float v2[2],
+ const float dir2[2],
+ float r_isect[2])
{
float lmbda, div;
@@ -538,14 +543,18 @@ static PBool p_intersect_line_2d_dir(float *v1, float *dir1, float *v2, float *d
}
lmbda = ((v1[1] - v2[1]) * dir1[0] - (v1[0] - v2[0]) * dir1[1]) / div;
- isect[0] = v1[0] + lmbda * dir2[0];
- isect[1] = v1[1] + lmbda * dir2[1];
+ r_isect[0] = v1[0] + lmbda * dir2[0];
+ r_isect[1] = v1[1] + lmbda * dir2[1];
return P_TRUE;
}
#if 0
-static PBool p_intersect_line_2d(float *v1, float *v2, float *v3, float *v4, float *isect)
+static PBool p_intersect_line_2d(const float v1[2],
+ const float v2[2],
+ const float v3[2],
+ const float v4[2],
+ const float r_isect[2])
{
float dir1[2], dir2[2];
@@ -892,7 +901,7 @@ static PBool p_edge_implicit_seam(PEdge *e, PEdge *ep)
return P_FALSE;
}
-static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl)
+static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PBool impl, PEdge **r_pair)
{
PHashKey key;
PEdge *pe;
@@ -906,7 +915,7 @@ static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl
key = PHASH_edge(key1, key2);
pe = (PEdge *)phash_lookup(handle->hash_edges, key);
- *pair = NULL;
+ *r_pair = NULL;
while (pe) {
if (pe != e) {
@@ -917,34 +926,34 @@ static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl
((v1->u.key == key2) && (v2->u.key == key1))) {
/* don't connect seams and t-junctions */
- if ((pe->flag & PEDGE_SEAM) || *pair || (impl && p_edge_implicit_seam(e, pe))) {
- *pair = NULL;
+ if ((pe->flag & PEDGE_SEAM) || *r_pair || (impl && p_edge_implicit_seam(e, pe))) {
+ *r_pair = NULL;
return P_FALSE;
}
- *pair = pe;
+ *r_pair = pe;
}
}
pe = (PEdge *)phash_next(handle->hash_edges, key, (PHashLink *)pe);
}
- if (*pair && (e->vert == (*pair)->vert)) {
- if ((*pair)->next->pair || (*pair)->next->next->pair) {
+ if (*r_pair && (e->vert == (*r_pair)->vert)) {
+ if ((*r_pair)->next->pair || (*r_pair)->next->next->pair) {
/* non unfoldable, maybe mobius ring or klein bottle */
- *pair = NULL;
+ *r_pair = NULL;
return P_FALSE;
}
}
- return (*pair != NULL);
+ return (*r_pair != NULL);
}
-static PBool p_edge_connect_pair(PHandle *handle, PEdge *e, PEdge ***stack, PBool impl)
+static PBool p_edge_connect_pair(PHandle *handle, PEdge *e, PBool impl, PEdge ***stack)
{
PEdge *pair = NULL;
- if (!e->pair && p_edge_has_pair(handle, e, &pair, impl)) {
+ if (!e->pair && p_edge_has_pair(handle, e, impl, &pair)) {
if (e->vert == pair->vert) {
p_face_flip(pair->face);
}
@@ -992,13 +1001,13 @@ static int p_connect_pairs(PHandle *handle, PBool impl)
/* assign verts to charts so we can sort them later */
f->u.chart = ncharts;
- if (!p_edge_connect_pair(handle, e, &stack, impl)) {
+ if (!p_edge_connect_pair(handle, e, impl, &stack)) {
e->vert->edge = e;
}
- if (!p_edge_connect_pair(handle, e1, &stack, impl)) {
+ if (!p_edge_connect_pair(handle, e1, impl, &stack)) {
e1->vert->edge = e1;
}
- if (!p_edge_connect_pair(handle, e2, &stack, impl)) {
+ if (!p_edge_connect_pair(handle, e2, impl, &stack)) {
e2->vert->edge = e2;
}
}
@@ -1255,16 +1264,16 @@ static PBool p_quad_split_direction(PHandle *handle, float **co, PHashKey *vkeys
/* Construction: boundary filling */
-static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer)
+static void p_chart_boundaries(PChart *chart, int *r_nboundaries, PEdge **r_outer)
{
PEdge *e, *be;
float len, maxlen = -1.0;
- if (nboundaries) {
- *nboundaries = 0;
+ if (r_nboundaries) {
+ *r_nboundaries = 0;
}
- if (outer) {
- *outer = NULL;
+ if (r_outer) {
+ *r_outer = NULL;
}
for (e = chart->edges; e; e = e->nextlink) {
@@ -1272,8 +1281,8 @@ static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer)
continue;
}
- if (nboundaries) {
- (*nboundaries)++;
+ if (r_nboundaries) {
+ (*r_nboundaries)++;
}
len = 0.0f;
@@ -1285,8 +1294,8 @@ static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer)
be = be->next->vert->edge;
} while (be != e);
- if (outer && (len > maxlen)) {
- *outer = e;
+ if (r_outer && (len > maxlen)) {
+ *r_outer = e;
maxlen = len;
}
}
@@ -1427,7 +1436,7 @@ static void p_chart_fill_boundaries(PChart *chart, PEdge *outer)
#if 0
/* Polygon kernel for inserting uv's non overlapping */
-static int p_polygon_point_in(float *cp1, float *cp2, float *p)
+static int p_polygon_point_in(const float cp1[2], const float cp2[2], const float p[2])
{
if ((cp1[0] == p[0]) && (cp1[1] == p[1])) {
return 2;
@@ -1443,43 +1452,43 @@ static int p_polygon_point_in(float *cp1, float *cp2, float *p)
static void p_polygon_kernel_clip(float (*oldpoints)[2],
int noldpoints,
float (*newpoints)[2],
- int *nnewpoints,
- float *cp1,
- float *cp2)
+ int *r_nnewpoints,
+ const float cp1[2],
+ const float cp2[2])
{
float *p2, *p1, isect[2];
int i, p2in, p1in;
p1 = oldpoints[noldpoints - 1];
p1in = p_polygon_point_in(cp1, cp2, p1);
- *nnewpoints = 0;
+ *r_nnewpoints = 0;
for (i = 0; i < noldpoints; i++) {
p2 = oldpoints[i];
p2in = p_polygon_point_in(cp1, cp2, p2);
if ((p2in >= 2) || (p1in && p2in)) {
- newpoints[*nnewpoints][0] = p2[0];
- newpoints[*nnewpoints][1] = p2[1];
- (*nnewpoints)++;
+ newpoints[*r_nnewpoints][0] = p2[0];
+ newpoints[*r_nnewpoints][1] = p2[1];
+ (*r_nnewpoints)++;
}
else if (p1in && !p2in) {
if (p1in != 3) {
p_intersect_line_2d(p1, p2, cp1, cp2, isect);
- newpoints[*nnewpoints][0] = isect[0];
- newpoints[*nnewpoints][1] = isect[1];
- (*nnewpoints)++;
+ newpoints[*r_nnewpoints][0] = isect[0];
+ newpoints[*r_nnewpoints][1] = isect[1];
+ (*r_nnewpoints)++;
}
}
else if (!p1in && p2in) {
p_intersect_line_2d(p1, p2, cp1, cp2, isect);
- newpoints[*nnewpoints][0] = isect[0];
- newpoints[*nnewpoints][1] = isect[1];
- (*nnewpoints)++;
+ newpoints[*r_nnewpoints][0] = isect[0];
+ newpoints[*r_nnewpoints][1] = isect[1];
+ (*r_nnewpoints)++;
- newpoints[*nnewpoints][0] = p2[0];
- newpoints[*nnewpoints][1] = p2[1];
- (*nnewpoints)++;
+ newpoints[*r_nnewpoints][0] = p2[0];
+ newpoints[*r_nnewpoints][1] = p2[1];
+ (*r_nnewpoints)++;
}
p1in = p2in;
@@ -1556,7 +1565,7 @@ static void p_polygon_kernel_center(float (*points)[2], int npoints, float *cent
int NCOLLAPSE = 1;
int NCOLLAPSEX = 0;
-static float p_vert_cotan(float *v1, float *v2, float *v3)
+static float p_vert_cotan(const float v1[3], const float v2[3], const float v3[3])
{
float a[3], b[3], c[3], clen;
@@ -1733,16 +1742,16 @@ static void p_vert_fix_edge_pointer(PVert *v)
}
}
-static void p_collapsing_verts(PEdge *edge, PEdge *pair, PVert **newv, PVert **keepv)
+static void p_collapsing_verts(PEdge *edge, PEdge *pair, PVert **r_newv, PVert **r_keepv)
{
/* the two vertices that are involved in the collapse */
if (edge) {
- *newv = edge->vert;
- *keepv = edge->next->vert;
+ *r_newv = edge->vert;
+ *r_keepv = edge->next->vert;
}
else {
- *newv = pair->next->vert;
- *keepv = pair->vert;
+ *r_newv = pair->next->vert;
+ *r_keepv = pair->vert;
}
}
@@ -2107,20 +2116,20 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair)
return cost;
}
-static void p_collapse_cost_vertex(PVert *vert, float *mincost, PEdge **mine)
+static void p_collapse_cost_vertex(PVert *vert, float *r_mincost, PEdge **r_mine)
{
PEdge *e, *enext, *pair;
- *mine = NULL;
- *mincost = 0.0f;
+ *r_mine = NULL;
+ *r_mincost = 0.0f;
e = vert->edge;
do {
if (p_collapse_allowed(e, e->pair)) {
float cost = p_collapse_cost(e, e->pair);
- if ((*mine == NULL) || (cost < *mincost)) {
- *mincost = cost;
- *mine = e;
+ if ((*r_mine == NULL) || (cost < *r_mincost)) {
+ *r_mincost = cost;
+ *r_mine = e;
}
}
@@ -2133,9 +2142,9 @@ static void p_collapse_cost_vertex(PVert *vert, float *mincost, PEdge **mine)
if (p_collapse_allowed(NULL, pair)) {
float cost = p_collapse_cost(NULL, pair);
- if ((*mine == NULL) || (cost < *mincost)) {
- *mincost = cost;
- *mine = pair;
+ if ((*r_mine == NULL) || (cost < *r_mincost)) {
+ *r_mincost = cost;
+ *r_mine = pair;
}
}
@@ -3549,7 +3558,7 @@ static int p_compare_geometric_uv(const void *a, const void *b)
}
}
-static PBool p_chart_convex_hull(PChart *chart, PVert ***verts, int *nverts, int *right)
+static PBool p_chart_convex_hull(PChart *chart, PVert ***r_verts, int *r_nverts, int *r_right)
{
/* Graham algorithm, taken from:
* http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/117225 */
@@ -3608,9 +3617,9 @@ static PBool p_chart_convex_hull(PChart *chart, PVert ***verts, int *nverts, int
*p = L[i];
}
- *verts = points;
- *nverts = npoints;
- *right = ulen - 1;
+ *r_verts = points;
+ *r_nverts = npoints;
+ *r_right = ulen - 1;
MEM_freeN(U);
MEM_freeN(L);
@@ -4400,8 +4409,8 @@ static void p_add_ngon(ParamHandle *handle,
PHandle *phandle = (PHandle *)handle;
MemArena *arena = phandle->polyfill_arena;
Heap *heap = phandle->polyfill_heap;
- unsigned int nfilltri = nverts - 2;
- unsigned int(*tris)[3] = BLI_memarena_alloc(arena, sizeof(*tris) * (size_t)nfilltri);
+ uint nfilltri = nverts - 2;
+ uint(*tris)[3] = BLI_memarena_alloc(arena, sizeof(*tris) * (size_t)nfilltri);
float(*projverts)[2] = BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)nverts);
/* Calc normal, flipped: to get a positive 2d cross product. */
@@ -4432,10 +4441,10 @@ static void p_add_ngon(ParamHandle *handle,
/* Add triangles. */
for (int j = 0; j < nfilltri; j++) {
- unsigned int *tri = tris[j];
- unsigned int v0 = tri[0];
- unsigned int v1 = tri[1];
- unsigned int v2 = tri[2];
+ uint *tri = tris[j];
+ uint v0 = tri[0];
+ uint v1 = tri[1];
+ uint v2 = tri[2];
ParamKey tri_vkeys[3] = {vkeys[v0], vkeys[v1], vkeys[v2]};
float *tri_co[3] = {co[v0], co[v1], co[v2]};
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h
index 2b80241e6e3..53188ea42bb 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.h
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.h
@@ -21,12 +21,12 @@
* \ingroup eduv
*/
+#include "BLI_sys_types.h" // for intptr_t support
+
#ifdef __cplusplus
extern "C" {
#endif
-#include "BLI_sys_types.h" // for intptr_t support
-
typedef void ParamHandle; /* handle to a set of charts */
typedef intptr_t ParamKey; /* (hash) key for identifying verts and faces */
typedef enum ParamBool {
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
new file mode 100644
index 00000000000..6e931b56a85
--- /dev/null
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -0,0 +1,3415 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup eduv
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_image_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+
+#include "BLI_alloca.h"
+#include "BLI_blenlib.h"
+#include "BLI_hash.h"
+#include "BLI_kdopbvh.h"
+#include "BLI_lasso_2d.h"
+#include "BLI_math.h"
+#include "BLI_polyfill_2d.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
+#include "BKE_layer.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_report.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "ED_image.h"
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_select_utils.h"
+#include "ED_uvedit.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
+
+#include "uvedit_intern.h"
+
+static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action);
+static void uv_select_all_perform_multi(
+ Scene *scene, Image *ima, Object **objects, const uint objects_len, int action);
+static void uv_select_flush_from_tag_face(SpaceImage *sima,
+ Scene *scene,
+ Object *obedit,
+ const bool select);
+static void uv_select_flush_from_tag_loop(SpaceImage *sima,
+ Scene *scene,
+ Object *obedit,
+ const bool select);
+static void uv_select_tag_update_for_object(Depsgraph *depsgraph,
+ const ToolSettings *ts,
+ Object *obedit);
+
+/* -------------------------------------------------------------------- */
+/** \name Visibility and Selection Utilities
+ * \{ */
+
+static void uv_select_island_limit_default(SpaceImage *sima, float r_limit[2])
+{
+ uvedit_pixel_to_float(sima, 0.05f, r_limit);
+}
+
+static void uvedit_vertex_select_tagged(BMEditMesh *em,
+ Scene *scene,
+ bool select,
+ int cd_loop_uv_offset)
+{
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ }
+ }
+ }
+}
+
+bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa)
+{
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0);
+ }
+ else {
+ return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT));
+ }
+}
+bool uvedit_face_visible_nolocal(const Scene *scene, BMFace *efa)
+{
+ return uvedit_face_visible_nolocal_ex(scene->toolsettings, efa);
+}
+
+bool uvedit_face_visible_test_ex(const ToolSettings *ts, Object *obedit, Image *ima, BMFace *efa)
+{
+ if (ts->uv_flag & UV_SHOW_SAME_IMAGE) {
+ Image *face_image;
+ ED_object_get_active_image(obedit, efa->mat_nr + 1, &face_image, NULL, NULL, NULL);
+ return (face_image == ima) ? uvedit_face_visible_nolocal_ex(ts, efa) : false;
+ }
+ else {
+ return uvedit_face_visible_nolocal_ex(ts, efa);
+ }
+}
+bool uvedit_face_visible_test(const Scene *scene, Object *obedit, Image *ima, BMFace *efa)
+{
+ return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa);
+}
+
+bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const int cd_loop_uv_offset)
+{
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ return (BM_elem_flag_test(efa, BM_ELEM_SELECT));
+ }
+ else {
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (!(luv->flag & MLOOPUV_VERTSEL)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
+bool uvedit_face_select_test(const Scene *scene, BMFace *efa, const int cd_loop_uv_offset)
+{
+ return uvedit_face_select_test_ex(scene->toolsettings, efa, cd_loop_uv_offset);
+}
+
+bool uvedit_face_select_set(const struct Scene *scene,
+ struct BMEditMesh *em,
+ struct BMFace *efa,
+ const bool select,
+ const bool do_history,
+ const int cd_loop_uv_offset)
+{
+ if (select) {
+ return uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset);
+ }
+ else {
+ return uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset);
+ }
+}
+
+bool uvedit_face_select_enable(const Scene *scene,
+ BMEditMesh *em,
+ BMFace *efa,
+ const bool do_history,
+ const int cd_loop_uv_offset)
+{
+ const ToolSettings *ts = scene->toolsettings;
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ BM_face_select_set(em->bm, efa, true);
+ if (do_history) {
+ BM_select_history_store(em->bm, (BMElem *)efa);
+ }
+ }
+ else {
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool uvedit_face_select_disable(const Scene *scene,
+ BMEditMesh *em,
+ BMFace *efa,
+ const int cd_loop_uv_offset)
+{
+ const ToolSettings *ts = scene->toolsettings;
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ BM_face_select_set(em->bm, efa, false);
+ }
+ else {
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool uvedit_edge_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset)
+{
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ return BM_elem_flag_test(l->f, BM_ELEM_SELECT);
+ }
+ else if (ts->selectmode == SCE_SELECT_EDGE) {
+ return BM_elem_flag_test(l->e, BM_ELEM_SELECT);
+ }
+ else {
+ return BM_elem_flag_test(l->v, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(l->next->v, BM_ELEM_SELECT);
+ }
+ }
+ else {
+ MLoopUV *luv1, *luv2;
+
+ luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
+
+ return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL);
+ }
+}
+bool uvedit_edge_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset)
+{
+ return uvedit_edge_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
+}
+
+void uvedit_edge_select_set(BMEditMesh *em,
+ const Scene *scene,
+ BMLoop *l,
+ const bool select,
+ const bool do_history,
+ const int cd_loop_uv_offset)
+
+{
+ if (select) {
+ uvedit_edge_select_enable(em, scene, l, do_history, cd_loop_uv_offset);
+ }
+ else {
+ uvedit_edge_select_disable(em, scene, l, cd_loop_uv_offset);
+ }
+}
+
+void uvedit_edge_select_enable(BMEditMesh *em,
+ const Scene *scene,
+ BMLoop *l,
+ const bool do_history,
+ const int cd_loop_uv_offset)
+
+{
+ const ToolSettings *ts = scene->toolsettings;
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ BM_face_select_set(em->bm, l->f, true);
+ }
+ else if (ts->selectmode & SCE_SELECT_EDGE) {
+ BM_edge_select_set(em->bm, l->e, true);
+ }
+ else {
+ BM_vert_select_set(em->bm, l->e->v1, true);
+ BM_vert_select_set(em->bm, l->e->v2, true);
+ }
+
+ if (do_history) {
+ BM_select_history_store(em->bm, (BMElem *)l->e);
+ }
+ }
+ else {
+ MLoopUV *luv1, *luv2;
+
+ luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
+
+ luv1->flag |= MLOOPUV_VERTSEL;
+ luv2->flag |= MLOOPUV_VERTSEL;
+ }
+}
+
+void uvedit_edge_select_disable(BMEditMesh *em,
+ const Scene *scene,
+ BMLoop *l,
+ const int cd_loop_uv_offset)
+
+{
+ const ToolSettings *ts = scene->toolsettings;
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ BM_face_select_set(em->bm, l->f, false);
+ }
+ else if (ts->selectmode & SCE_SELECT_EDGE) {
+ BM_edge_select_set(em->bm, l->e, false);
+ }
+ else {
+ BM_vert_select_set(em->bm, l->e->v1, false);
+ BM_vert_select_set(em->bm, l->e->v2, false);
+ }
+ }
+ else {
+ MLoopUV *luv1, *luv2;
+
+ luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
+
+ luv1->flag &= ~MLOOPUV_VERTSEL;
+ luv2->flag &= ~MLOOPUV_VERTSEL;
+ }
+}
+
+bool uvedit_uv_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset)
+{
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ return BM_elem_flag_test_bool(l->f, BM_ELEM_SELECT);
+ }
+ else {
+ return BM_elem_flag_test_bool(l->v, BM_ELEM_SELECT);
+ }
+ }
+ else {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ return (luv->flag & MLOOPUV_VERTSEL) != 0;
+ }
+}
+bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset)
+{
+ return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
+}
+
+void uvedit_uv_select_set(BMEditMesh *em,
+ const Scene *scene,
+ BMLoop *l,
+ const bool select,
+ const bool do_history,
+ const int cd_loop_uv_offset)
+{
+ if (select) {
+ uvedit_uv_select_enable(em, scene, l, do_history, cd_loop_uv_offset);
+ }
+ else {
+ uvedit_uv_select_disable(em, scene, l, cd_loop_uv_offset);
+ }
+}
+
+void uvedit_uv_select_enable(BMEditMesh *em,
+ const Scene *scene,
+ BMLoop *l,
+ const bool do_history,
+ const int cd_loop_uv_offset)
+{
+ const ToolSettings *ts = scene->toolsettings;
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ BM_face_select_set(em->bm, l->f, true);
+ }
+ else {
+ BM_vert_select_set(em->bm, l->v, true);
+ }
+
+ if (do_history) {
+ BM_select_history_remove(em->bm, (BMElem *)l->v);
+ }
+ }
+ else {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+}
+
+void uvedit_uv_select_disable(BMEditMesh *em,
+ const Scene *scene,
+ BMLoop *l,
+ const int cd_loop_uv_offset)
+{
+ const ToolSettings *ts = scene->toolsettings;
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ BM_face_select_set(em->bm, l->f, false);
+ }
+ else {
+ BM_vert_select_set(em->bm, l->v, false);
+ }
+ }
+ else {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Find Nearest Elements
+ * \{ */
+
+bool uv_find_nearest_edge(
+ Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv, *luv_next;
+ int i;
+ bool found = false;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
+
+ const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
+
+ if (dist_test_sq < hit->dist_sq) {
+ hit->efa = efa;
+
+ hit->l = l;
+ hit->luv = luv;
+ hit->luv_next = luv_next;
+ hit->lindex = i;
+
+ hit->dist_sq = dist_test_sq;
+ found = true;
+ }
+ }
+ }
+ return found;
+}
+
+bool uv_find_nearest_edge_multi(Scene *scene,
+ Image *ima,
+ Object **objects,
+ const uint objects_len,
+ const float co[2],
+ UvNearestHit *hit_final)
+{
+ bool found = false;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) {
+ hit_final->ob = obedit;
+ found = true;
+ }
+ }
+ return found;
+}
+
+bool uv_find_nearest_face(
+ Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ bool found = false;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* this will fill in hit.vert1 and hit.vert2 */
+ float dist_sq_init = hit_final->dist_sq;
+ UvNearestHit hit = *hit_final;
+ if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
+ hit.dist_sq = dist_sq_init;
+ hit.l = NULL;
+ hit.luv = hit.luv_next = NULL;
+
+ BMIter iter;
+ BMFace *efa;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ float cent[2];
+ uv_poly_center(efa, cent, cd_loop_uv_offset);
+
+ const float dist_test_sq = len_squared_v2v2(co, cent);
+
+ if (dist_test_sq < hit.dist_sq) {
+ hit.efa = efa;
+ hit.dist_sq = dist_test_sq;
+ found = true;
+ }
+ }
+ }
+ if (found) {
+ *hit_final = hit;
+ }
+ return found;
+}
+
+bool uv_find_nearest_face_multi(Scene *scene,
+ Image *ima,
+ Object **objects,
+ const uint objects_len,
+ const float co[2],
+ UvNearestHit *hit_final)
+{
+ bool found = false;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) {
+ hit_final->ob = obedit;
+ found = true;
+ }
+ }
+ return found;
+}
+
+static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_loop_uv_offset)
+{
+ const float *uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset))->uv;
+ const float *uv_curr = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
+ const float *uv_next = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset))->uv;
+
+ return ((line_point_side_v2(uv_prev, uv_curr, co) > 0.0f) &&
+ (line_point_side_v2(uv_next, uv_curr, co) <= 0.0f));
+}
+
+bool uv_find_nearest_vert(Scene *scene,
+ Image *ima,
+ Object *obedit,
+ float const co[2],
+ const float penalty_dist,
+ UvNearestHit *hit_final)
+{
+ bool found = false;
+
+ /* this will fill in hit.vert1 and hit.vert2 */
+ float dist_sq_init = hit_final->dist_sq;
+ UvNearestHit hit = *hit_final;
+ if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
+ hit.dist_sq = dist_sq_init;
+
+ hit.l = NULL;
+ hit.luv = hit.luv_next = NULL;
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMIter iter;
+
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ BMIter liter;
+ BMLoop *l;
+ int i;
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ float dist_test_sq;
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist;
+ dist_test_sq = square_f(dist_test_sq);
+ }
+ else {
+ dist_test_sq = len_squared_v2v2(co, luv->uv);
+ }
+
+ if (dist_test_sq <= hit.dist_sq) {
+ if (dist_test_sq == hit.dist_sq) {
+ if (!uv_nearest_between(l, co, cd_loop_uv_offset)) {
+ continue;
+ }
+ }
+
+ hit.dist_sq = dist_test_sq;
+
+ hit.l = l;
+ hit.luv = luv;
+ hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
+ hit.efa = efa;
+ hit.lindex = i;
+ found = true;
+ }
+ }
+ }
+ }
+
+ if (found) {
+ *hit_final = hit;
+ }
+
+ return found;
+}
+
+bool uv_find_nearest_vert_multi(Scene *scene,
+ Image *ima,
+ Object **objects,
+ const uint objects_len,
+ float const co[2],
+ const float penalty_dist,
+ UvNearestHit *hit_final)
+{
+ bool found = false;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) {
+ hit_final->ob = obedit;
+ found = true;
+ }
+ }
+ return found;
+}
+
+bool ED_uvedit_nearest_uv(const Scene *scene,
+ Object *obedit,
+ Image *ima,
+ const float co[2],
+ float *dist_sq,
+ float r_uv[2])
+{
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMIter iter;
+ BMFace *efa;
+ const float *uv_best = NULL;
+ float dist_best = *dist_sq;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
+ const float dist_test = len_squared_v2v2(co, uv);
+ if (dist_best > dist_test) {
+ dist_best = dist_test;
+ uv_best = uv;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ if (uv_best != NULL) {
+ copy_v2_v2(r_uv, uv_best);
+ *dist_sq = dist_best;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+bool ED_uvedit_nearest_uv_multi(const Scene *scene,
+ Image *ima,
+ Object **objects,
+ const uint objects_len,
+ const float co[2],
+ float *dist_sq,
+ float r_uv[2])
+{
+ bool found = false;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ if (ED_uvedit_nearest_uv(scene, obedit, ima, co, dist_sq, r_uv)) {
+ found = true;
+ }
+ }
+ return found;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Loop Select
+ * \{ */
+
+static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first)
+{
+ UvMapVert *iterv;
+ int count = 0;
+
+ for (iterv = first; iterv; iterv = iterv->next) {
+ if (iterv->separate && iterv != first) {
+ break;
+ }
+
+ count++;
+ }
+
+ if (count < 5) {
+ first->flag = 1;
+ }
+}
+
+static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa, BMLoop *l)
+{
+ UvMapVert *iterv, *first;
+ first = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
+
+ for (iterv = first; iterv; iterv = iterv->next) {
+ if (iterv->separate) {
+ first = iterv;
+ }
+ if (iterv->poly_index == BM_elem_index_get(efa)) {
+ return first;
+ }
+ }
+
+ return NULL;
+}
+
+static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em,
+ UvMapVert *first1,
+ UvMapVert *first2,
+ int *totface)
+{
+ UvMapVert *iterv1, *iterv2;
+ BMFace *efa;
+ int tot = 0;
+
+ /* count number of faces this edge has */
+ for (iterv1 = first1; iterv1; iterv1 = iterv1->next) {
+ if (iterv1->separate && iterv1 != first1) {
+ break;
+ }
+
+ for (iterv2 = first2; iterv2; iterv2 = iterv2->next) {
+ if (iterv2->separate && iterv2 != first2) {
+ break;
+ }
+
+ if (iterv1->poly_index == iterv2->poly_index) {
+ /* if face already tagged, don't do this edge */
+ efa = BM_face_at_index(em->bm, iterv1->poly_index);
+ if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+ return false;
+ }
+
+ tot++;
+ break;
+ }
+ }
+ }
+
+ if (*totface == 0) { /* start edge */
+ *totface = tot;
+ }
+ else if (tot != *totface) { /* check for same number of faces as start edge */
+ return false;
+ }
+
+ /* tag the faces */
+ for (iterv1 = first1; iterv1; iterv1 = iterv1->next) {
+ if (iterv1->separate && iterv1 != first1) {
+ break;
+ }
+
+ for (iterv2 = first2; iterv2; iterv2 = iterv2->next) {
+ if (iterv2->separate && iterv2 != first2) {
+ break;
+ }
+
+ if (iterv1->poly_index == iterv2->poly_index) {
+ efa = BM_face_at_index(em->bm, iterv1->poly_index);
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+static int uv_select_edgeloop(Scene *scene,
+ Image *ima,
+ Object *obedit,
+ UvNearestHit *hit,
+ const float limit[2],
+ const bool extend)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMIter iter, liter;
+ BMLoop *l;
+ UvVertMap *vmap;
+ UvMapVert *iterv_curr;
+ UvMapVert *iterv_next;
+ int starttotf;
+ bool looking, select;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* setup */
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE);
+ vmap = BM_uv_vert_map_create(em->bm, limit, false, false);
+
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
+
+ if (!extend) {
+ uv_select_all_perform(scene, ima, obedit, SEL_DESELECT);
+ }
+
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+
+ /* set flags for first face and verts */
+ iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l);
+ iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next);
+ uv_select_edgeloop_vertex_loop_flag(iterv_curr);
+ uv_select_edgeloop_vertex_loop_flag(iterv_next);
+
+ starttotf = 0;
+ uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf);
+
+ /* sorry, first edge isn't even ok */
+ looking = !(iterv_curr->flag == 0 && iterv_next->flag == 0);
+
+ /* iterate */
+ while (looking) {
+ looking = false;
+
+ /* find correct valence edges which are not tagged yet, but connect to tagged one */
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG) &&
+ uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ /* check face not hidden and not tagged */
+ if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) {
+ continue;
+ }
+ if (!(iterv_next = uv_select_edgeloop_vertex_map_get(vmap, efa, l->next))) {
+ continue;
+ }
+
+ /* check if vertex is tagged and has right valence */
+ if (iterv_curr->flag || iterv_next->flag) {
+ if (uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf)) {
+ looking = true;
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
+
+ uv_select_edgeloop_vertex_loop_flag(iterv_curr);
+ uv_select_edgeloop_vertex_loop_flag(iterv_next);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* do the actual select/deselect */
+ iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l);
+ iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next);
+ iterv_curr->flag = 1;
+ iterv_next->flag = 1;
+
+ if (extend) {
+ select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset));
+ }
+ else {
+ select = true;
+ }
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l);
+
+ if (iterv_curr->flag) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ }
+ }
+ }
+
+ /* cleanup */
+ BM_uv_vert_map_free(vmap);
+
+ return (select) ? 1 : -1;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked
+ * \{ */
+
+static void uv_select_linked_multi(Scene *scene,
+ Image *ima,
+ Object **objects,
+ const uint objects_len,
+ const float limit[2],
+ UvNearestHit *hit_final,
+ bool extend,
+ bool deselect,
+ bool toggle,
+ bool select_faces)
+{
+ /* loop over objects, or just use hit_final->ob */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ if (hit_final && ob_index != 0) {
+ break;
+ }
+ Object *obedit = hit_final ? hit_final->ob : objects[ob_index];
+
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ UvVertMap *vmap;
+ UvMapVert *vlist, *iterv, *startv;
+ int i, stacksize = 0, *stack;
+ uint a;
+ char *flag;
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
+
+ /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320
+ * this made *every* projection split the island into front/back islands.
+ * Keep 'use_winding' to false, see: T50970.
+ *
+ * Better solve this by having a delimit option for select-linked operator,
+ * keeping island-select working as is. */
+ vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false);
+
+ if (vmap == NULL) {
+ continue;
+ }
+
+ stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack");
+ flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag");
+
+ if (hit_final == NULL) {
+ /* Use existing selection */
+ BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (select_faces) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ stack[stacksize] = a;
+ stacksize++;
+ flag[a] = 1;
+ }
+ }
+ else {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ stack[stacksize] = a;
+ stacksize++;
+ flag[a] = 1;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
+ if (efa == hit_final->efa) {
+ stack[stacksize] = a;
+ stacksize++;
+ flag[a] = 1;
+ break;
+ }
+ }
+ }
+
+ while (stacksize > 0) {
+
+ stacksize--;
+ a = stack[stacksize];
+
+ efa = BM_face_at_index(em->bm, a);
+
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+
+ /* make_uv_vert_map_EM sets verts tmp.l to the indices */
+ vlist = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
+
+ startv = vlist;
+
+ for (iterv = vlist; iterv; iterv = iterv->next) {
+ if (iterv->separate) {
+ startv = iterv;
+ }
+ if (iterv->poly_index == a) {
+ break;
+ }
+ }
+
+ for (iterv = startv; iterv; iterv = iterv->next) {
+ if ((startv != iterv) && (iterv->separate)) {
+ break;
+ }
+ else if (!flag[iterv->poly_index]) {
+ flag[iterv->poly_index] = 1;
+ stack[stacksize] = iterv->poly_index;
+ stacksize++;
+ }
+ }
+ }
+ }
+
+ /* Toggling - if any of the linked vertices is selected (and visible), we deselect. */
+ if ((toggle == true) && (extend == false) && (deselect == false)) {
+ BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
+ bool found_selected = false;
+ if (!flag[a]) {
+ continue;
+ }
+
+ if (select_faces) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ found_selected = true;
+ }
+ }
+ else {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ found_selected = true;
+ }
+ }
+
+ if (found_selected) {
+ deselect = true;
+ break;
+ }
+ }
+ }
+ }
+
+#define SET_SELECTION(value) \
+ if (select_faces) { \
+ BM_face_select_set(em->bm, efa, value); \
+ } \
+ else { \
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { \
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); \
+ luv->flag = (value) ? (luv->flag | MLOOPUV_VERTSEL) : (luv->flag & ~MLOOPUV_VERTSEL); \
+ } \
+ } \
+ (void)0
+
+ BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
+ if (!flag[a]) {
+ if (!extend && !deselect && !toggle) {
+ SET_SELECTION(false);
+ }
+ continue;
+ }
+
+ if (!deselect) {
+ SET_SELECTION(true);
+ }
+ else {
+ SET_SELECTION(false);
+ }
+ }
+
+#undef SET_SELECTION
+
+ MEM_freeN(stack);
+ MEM_freeN(flag);
+ BM_uv_vert_map_free(vmap);
+ }
+}
+
+/**
+ * \warning This returns first selected UV,
+ * not ideal in many cases since there could be multiple.
+ */
+const float *uvedit_first_selected_uv_from_vertex(
+ Scene *scene, Object *obedit, Image *ima, BMVert *eve, const int cd_loop_uv_offset)
+{
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) {
+ continue;
+ }
+
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ return luv->uv;
+ }
+ }
+
+ return NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More/Less Operator
+ * \{ */
+
+static int uv_select_more_less(bContext *C, const bool select)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Image *ima = CTX_data_edit_image(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ const ToolSettings *ts = scene->toolsettings;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ const bool is_uv_face_selectmode = (ts->uv_selectmode == UV_SELECT_FACE);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ bool changed = false;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (select) {
+ EDBM_select_more(em, true);
+ }
+ else {
+ EDBM_select_less(em, true);
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ continue;
+ }
+
+ if (is_uv_face_selectmode) {
+
+ /* clear tags */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+
+ /* mark loops to be selected */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
+
+#define IS_SEL 1
+#define IS_UNSEL 2
+
+ int sel_state = 0;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ sel_state |= IS_SEL;
+ }
+ else {
+ sel_state |= IS_UNSEL;
+ }
+
+ /* if we have a mixed selection, tag to grow it */
+ if (sel_state == (IS_SEL | IS_UNSEL)) {
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ changed = true;
+ break;
+ }
+ }
+
+#undef IS_SEL
+#undef IS_UNSEL
+ }
+ }
+ }
+ else {
+
+ /* clear tags */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ BM_elem_flag_disable(l, BM_ELEM_TAG);
+ }
+ }
+
+ /* mark loops to be selected */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ if (((luv->flag & MLOOPUV_VERTSEL) != 0) == select) {
+ BM_elem_flag_enable(l->next, BM_ELEM_TAG);
+ BM_elem_flag_enable(l->prev, BM_ELEM_TAG);
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ if (is_uv_face_selectmode) {
+ /* Select tagged faces. */
+ uv_select_flush_from_tag_face(sima, scene, obedit, select);
+ }
+ else {
+ /* Select tagged loops. */
+ uv_select_flush_from_tag_loop(sima, scene, obedit, select);
+ }
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
+}
+
+static int uv_select_more_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ return uv_select_more_less(C, true);
+}
+
+void UV_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select More";
+ ot->description = "Select more UV vertices connected to initial selection";
+ ot->idname = "UV_OT_select_more";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_select_more_exec;
+ ot->poll = ED_operator_uvedit_space_image;
+}
+
+static int uv_select_less_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ return uv_select_more_less(C, false);
+}
+
+void UV_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->description = "Deselect UV vertices at the boundary of each selection region";
+ ot->idname = "UV_OT_select_less";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_select_less_exec;
+ ot->poll = ED_operator_uvedit_space_image;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name (De)Select All Operator
+ * \{ */
+
+bool uvedit_select_is_any_selected(Scene *scene, Image *ima, Object *obedit)
+{
+ const ToolSettings *ts = scene->toolsettings;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ return (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel);
+ }
+ else {
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool uvedit_select_is_any_selected_multi(Scene *scene,
+ Image *ima,
+ Object **objects,
+ const uint objects_len)
+{
+ bool found = false;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ if (uvedit_select_is_any_selected(scene, ima, obedit)) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+}
+
+static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action)
+{
+ const ToolSettings *ts = scene->toolsettings;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (action == SEL_TOGGLE) {
+ action = uvedit_select_is_any_selected(scene, ima, obedit) ? SEL_DESELECT : SEL_SELECT;
+ }
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ switch (action) {
+ case SEL_TOGGLE:
+ EDBM_select_toggle_all(em);
+ break;
+ case SEL_SELECT:
+ EDBM_flag_enable_all(em, BM_ELEM_SELECT);
+ break;
+ case SEL_DESELECT:
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ break;
+ case SEL_INVERT:
+ EDBM_select_swap(em);
+ EDBM_selectmode_flush(em);
+ break;
+ }
+ }
+ else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ switch (action) {
+ case SEL_SELECT:
+ luv->flag |= MLOOPUV_VERTSEL;
+ break;
+ case SEL_DESELECT:
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ break;
+ case SEL_INVERT:
+ luv->flag ^= MLOOPUV_VERTSEL;
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void uv_select_all_perform_multi(
+ Scene *scene, Image *ima, Object **objects, const uint objects_len, int action)
+{
+ if (action == SEL_TOGGLE) {
+ action = uvedit_select_is_any_selected_multi(scene, ima, objects, objects_len) ? SEL_DESELECT :
+ SEL_SELECT;
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ uv_select_all_perform(scene, ima, obedit, action);
+ }
+}
+
+static int uv_select_all_exec(bContext *C, wmOperator *op)
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ const ToolSettings *ts = scene->toolsettings;
+ Image *ima = CTX_data_edit_image(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ int action = RNA_enum_get(op->ptr, "action");
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, action);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ uv_select_tag_update_for_object(depsgraph, ts, obedit);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_select_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->description = "Change selection of all UV vertices";
+ ot->idname = "UV_OT_select_all";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_select_all_exec;
+ ot->poll = ED_operator_uvedit;
+
+ WM_operator_properties_select_all(ot);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mouse Select Operator
+ * \{ */
+
+static bool uv_sticky_select(
+ float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen)
+{
+ int i;
+
+ /* this function test if some vertex needs to selected
+ * in addition to the existing ones due to sticky select */
+ if (sticky == SI_STICKY_DISABLE) {
+ return false;
+ }
+
+ for (i = 0; i < hitlen; i++) {
+ if (hitv[i] == v) {
+ if (sticky == SI_STICKY_LOC) {
+ if (fabsf(hituv[i][0] - uv[0]) < limit[0] && fabsf(hituv[i][1] - uv[1]) < limit[1]) {
+ return true;
+ }
+ }
+ else if (sticky == SI_STICKY_VERTEX) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int uv_mouse_select_multi(bContext *C,
+ Object **objects,
+ uint objects_len,
+ const float co[2],
+ const bool extend,
+ const bool deselect_all,
+ const bool loop)
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ const ToolSettings *ts = scene->toolsettings;
+ Image *ima = CTX_data_edit_image(C);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ UvNearestHit hit = UV_NEAREST_HIT_INIT;
+ int i, selectmode, sticky, sync, *hitv = NULL;
+ bool select = true;
+ bool found_item = false;
+ /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
+ int flush = 0;
+ int hitlen = 0;
+ float limit[2], **hituv = NULL;
+
+ /* notice 'limit' is the same no matter the zoom level, since this is like
+ * remove doubles and could annoying if it joined points when zoomed out.
+ * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and
+ * shift-selecting can consider an adjacent point close enough to add to
+ * the selection rather than de-selecting the closest. */
+
+ float penalty_dist;
+ {
+ float penalty[2];
+ uvedit_pixel_to_float(sima, 0.05f, limit);
+ uvedit_pixel_to_float(sima, 5.0f / (sima ? sima->zoom : 1.0f), penalty);
+ penalty_dist = len_v2(penalty);
+ }
+
+ /* retrieve operation mode */
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ sync = 1;
+
+ if (ts->selectmode & SCE_SELECT_FACE) {
+ selectmode = UV_SELECT_FACE;
+ }
+ else if (ts->selectmode & SCE_SELECT_EDGE) {
+ selectmode = UV_SELECT_EDGE;
+ }
+ else {
+ selectmode = UV_SELECT_VERTEX;
+ }
+
+ sticky = SI_STICKY_DISABLE;
+ }
+ else {
+ sync = 0;
+ selectmode = ts->uv_selectmode;
+ sticky = (sima) ? sima->sticky : 1;
+ }
+
+ /* find nearest element */
+ if (loop) {
+ /* find edge */
+ found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
+ }
+ else if (selectmode == UV_SELECT_VERTEX) {
+ /* find vertex */
+ found_item = uv_find_nearest_vert_multi(
+ scene, ima, objects, objects_len, co, penalty_dist, &hit);
+ found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
+
+ if (found_item) {
+ /* mark 1 vertex as being hit */
+ hitv = BLI_array_alloca(hitv, hit.efa->len);
+ hituv = BLI_array_alloca(hituv, hit.efa->len);
+ copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
+
+ hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
+ hituv[hit.lindex] = hit.luv->uv;
+
+ hitlen = hit.efa->len;
+ }
+ }
+ else if (selectmode == UV_SELECT_EDGE) {
+ /* find edge */
+ found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
+ found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
+
+ if (found_item) {
+ /* mark 2 edge vertices as being hit */
+ hitv = BLI_array_alloca(hitv, hit.efa->len);
+ hituv = BLI_array_alloca(hituv, hit.efa->len);
+ copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
+
+ hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
+ hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v);
+ hituv[hit.lindex] = hit.luv->uv;
+ hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv;
+
+ hitlen = hit.efa->len;
+ }
+ }
+ else if (selectmode == UV_SELECT_FACE) {
+ /* find face */
+ found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit);
+ found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
+
+ if (found_item) {
+ BMEditMesh *em = BKE_editmesh_from_object(hit.ob);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* make active */
+ BM_mesh_active_face_set(em->bm, hit.efa);
+
+ /* mark all face vertices as being hit */
+
+ hitv = BLI_array_alloca(hitv, hit.efa->len);
+ hituv = BLI_array_alloca(hituv, hit.efa->len);
+ BM_ITER_ELEM_INDEX (l, &liter, hit.efa, BM_LOOPS_OF_FACE, i) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ hituv[i] = luv->uv;
+ hitv[i] = BM_elem_index_get(l->v);
+ }
+
+ hitlen = hit.efa->len;
+ }
+ }
+ else if (selectmode == UV_SELECT_ISLAND) {
+ found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
+ found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
+ }
+
+ if (!found_item) {
+ if (deselect_all) {
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ uv_select_tag_update_for_object(depsgraph, ts, obedit);
+ }
+
+ return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *obedit = hit.ob;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* do selection */
+ if (loop) {
+ if (!extend) {
+ /* TODO(MULTI_EDIT): We only need to de-select non-active */
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ }
+ flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend);
+ }
+ else if (selectmode == UV_SELECT_ISLAND) {
+ if (!extend) {
+ /* TODO(MULTI_EDIT): We only need to de-select non-active */
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ }
+ /* Current behavior of 'extend'
+ * is actually toggling, so pass extend flag as 'toggle' here */
+ uv_select_linked_multi(
+ scene, ima, objects, objects_len, limit, &hit, false, false, extend, false);
+ }
+ else if (extend) {
+ if (selectmode == UV_SELECT_VERTEX) {
+ /* (de)select uv vertex */
+ select = !uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset);
+ uvedit_uv_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset);
+ flush = 1;
+ }
+ else if (selectmode == UV_SELECT_EDGE) {
+ /* (de)select edge */
+ select = !(uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset));
+ uvedit_edge_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset);
+ flush = 1;
+ }
+ else if (selectmode == UV_SELECT_FACE) {
+ /* (de)select face */
+ select = !(uvedit_face_select_test(scene, hit.efa, cd_loop_uv_offset));
+ uvedit_face_select_set(scene, em, hit.efa, select, true, cd_loop_uv_offset);
+ flush = -1;
+ }
+
+ /* de-selecting an edge may deselect a face too - validate */
+ if (sync) {
+ if (select == false) {
+ BM_select_history_validate(em->bm);
+ }
+ }
+
+ /* (de)select sticky uv nodes */
+ if (sticky != SI_STICKY_DISABLE) {
+
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (uv_sticky_select(
+ limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ }
+ }
+ }
+
+ flush = select ? 1 : -1;
+ }
+ }
+ else {
+ /* deselect all */
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+
+ if (selectmode == UV_SELECT_VERTEX) {
+ /* select vertex */
+ uvedit_uv_select_enable(em, scene, hit.l, true, cd_loop_uv_offset);
+ flush = 1;
+ }
+ else if (selectmode == UV_SELECT_EDGE) {
+ /* select edge */
+ uvedit_edge_select_enable(em, scene, hit.l, true, cd_loop_uv_offset);
+ flush = 1;
+ }
+ else if (selectmode == UV_SELECT_FACE) {
+ /* select face */
+ uvedit_face_select_enable(scene, em, hit.efa, true, cd_loop_uv_offset);
+ }
+
+ /* select sticky uvs */
+ if (sticky != SI_STICKY_DISABLE) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (sticky == SI_STICKY_DISABLE) {
+ continue;
+ }
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ if (uv_sticky_select(
+ limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) {
+ uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset);
+ }
+
+ flush = 1;
+ }
+ }
+ }
+ }
+
+ if (sync) {
+ /* flush for mesh selection */
+
+ /* before bmesh */
+#if 0
+ if (ts->selectmode != SCE_SELECT_FACE) {
+ if (flush == 1) {
+ EDBM_select_flush(em);
+ }
+ else if (flush == -1) {
+ EDBM_deselect_flush(em);
+ }
+ }
+#else
+ if (flush != 0) {
+ if (loop) {
+ /* push vertex -> edge selection */
+ if (select) {
+ EDBM_select_flush(em);
+ }
+ else {
+ EDBM_deselect_flush(em);
+ }
+ }
+ else {
+ EDBM_selectmode_flush(em);
+ }
+ }
+#endif
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obiter = objects[ob_index];
+ uv_select_tag_update_for_object(depsgraph, ts, obiter);
+ }
+
+ return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
+}
+static int uv_mouse_select(
+ bContext *C, const float co[2], const bool extend, const bool deselect_all, const bool loop)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+ int ret = uv_mouse_select_multi(C, objects, objects_len, co, extend, deselect_all, loop);
+ MEM_freeN(objects);
+ return ret;
+}
+
+static int uv_select_exec(bContext *C, wmOperator *op)
+{
+ float co[2];
+
+ RNA_float_get_array(op->ptr, "location", co);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+ const bool loop = false;
+
+ return uv_mouse_select(C, co, extend, deselect_all, loop);
+}
+
+static int uv_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const ARegion *region = CTX_wm_region(C);
+ float co[2];
+
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
+ RNA_float_set_array(op->ptr, "location", co);
+
+ return uv_select_exec(C, op);
+}
+
+void UV_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Select UV vertices";
+ ot->idname = "UV_OT_select";
+ ot->flag = OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_select_exec;
+ ot->invoke = uv_select_invoke;
+ ot->poll = ED_operator_uvedit; /* requires space image */
+
+ /* properties */
+ PropertyRNA *prop;
+ RNA_def_boolean(ot->srna,
+ "extend",
+ 0,
+ "Extend",
+ "Extend selection rather than clearing the existing selection");
+ prop = RNA_def_boolean(ot->srna,
+ "deselect_all",
+ false,
+ "Deselect On Nothing",
+ "Deselect all when nothing under the cursor");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_float_vector(
+ ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds",
+ -100.0f,
+ 100.0f);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Loop Select Operator
+ * \{ */
+
+static int uv_select_loop_exec(bContext *C, wmOperator *op)
+{
+ float co[2];
+
+ RNA_float_get_array(op->ptr, "location", co);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool deselect_all = false;
+ const bool loop = true;
+
+ return uv_mouse_select(C, co, extend, deselect_all, loop);
+}
+
+static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const ARegion *region = CTX_wm_region(C);
+ float co[2];
+
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
+ RNA_float_set_array(op->ptr, "location", co);
+
+ return uv_select_loop_exec(C, op);
+}
+
+void UV_OT_select_loop(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Loop Select";
+ ot->description = "Select a loop of connected UV vertices";
+ ot->idname = "UV_OT_select_loop";
+ ot->flag = OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_select_loop_exec;
+ ot->invoke = uv_select_loop_invoke;
+ ot->poll = ED_operator_uvedit; /* requires space image */
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ 0,
+ "Extend",
+ "Extend selection rather than clearing the existing selection");
+ RNA_def_float_vector(
+ ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds",
+ -100.0f,
+ 100.0f);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Operator
+ * \{ */
+
+static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, bool pick)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ const ToolSettings *ts = scene->toolsettings;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Image *ima = CTX_data_edit_image(C);
+ float limit[2];
+ bool extend = true;
+ bool deselect = false;
+ bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
+
+ UvNearestHit hit = UV_NEAREST_HIT_INIT;
+
+ if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Select linked only works in face select mode when sync selection is enabled");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (pick) {
+ extend = RNA_boolean_get(op->ptr, "extend");
+ deselect = RNA_boolean_get(op->ptr, "deselect");
+ }
+ uv_select_island_limit_default(sima, limit);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ if (pick) {
+ float co[2];
+
+ if (event) {
+ /* invoke */
+ const ARegion *region = CTX_wm_region(C);
+
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
+ RNA_float_set_array(op->ptr, "location", co);
+ }
+ else {
+ /* exec */
+ RNA_float_get_array(op->ptr, "location", co);
+ }
+
+ if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (!extend) {
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ }
+
+ uv_select_linked_multi(scene,
+ ima,
+ objects,
+ objects_len,
+ limit,
+ pick ? &hit : NULL,
+ extend,
+ deselect,
+ false,
+ select_faces);
+
+ /* weak!, but works */
+ Object **objects_free = objects;
+ if (pick) {
+ objects = &hit.ob;
+ objects_len = 1;
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ MEM_SAFE_FREE(objects_free);
+
+ return OPERATOR_FINISHED;
+}
+
+static int uv_select_linked_exec(bContext *C, wmOperator *op)
+{
+ return uv_select_linked_internal(C, op, NULL, false);
+}
+
+void UV_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->description = "Select all UV vertices linked to the active UV map";
+ ot->idname = "UV_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec = uv_select_linked_exec;
+ ot->poll = ED_operator_uvedit; /* requires space image */
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked (Cursor Pick) Operator
+ * \{ */
+
+static int uv_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ return uv_select_linked_internal(C, op, event, true);
+}
+
+static int uv_select_linked_pick_exec(bContext *C, wmOperator *op)
+{
+ return uv_select_linked_internal(C, op, NULL, true);
+}
+
+void UV_OT_select_linked_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked Pick";
+ ot->description = "Select all UV vertices linked under the mouse";
+ ot->idname = "UV_OT_select_linked_pick";
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = uv_select_linked_pick_invoke;
+ ot->exec = uv_select_linked_pick_exec;
+ ot->poll = ED_operator_uvedit; /* requires space image */
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ 0,
+ "Extend",
+ "Extend selection rather than clearing the existing selection");
+ RNA_def_boolean(ot->srna,
+ "deselect",
+ 0,
+ "Deselect",
+ "Deselect linked UV vertices rather than selecting them");
+ RNA_def_float_vector(
+ ot->srna,
+ "location",
+ 2,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds",
+ -100.0f,
+ 100.0f);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Split Operator
+ * \{ */
+
+/**
+ * \note This is based on similar use case to #MESH_OT_split(), which has a similar effect
+ * but in this case they are not joined to begin with (only having the behavior of being joined)
+ * so its best to call this #uv_select_split() instead of just split(), but assigned to the same
+ * key as #MESH_OT_split - Campbell.
+ */
+static int uv_select_split_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const ToolSettings *ts = scene->toolsettings;
+ Image *ima = CTX_data_edit_image(C);
+
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled");
+ return OPERATOR_CANCELLED;
+ }
+
+ bool changed_multi = false;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMesh *bm = BKE_editmesh_from_object(obedit)->bm;
+
+ bool changed = false;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ bool is_sel = false;
+ bool is_unsel = false;
+
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ /* are we all selected? */
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ is_sel = true;
+ }
+ else {
+ is_unsel = true;
+ }
+
+ /* we have mixed selection, bail out */
+ if (is_sel && is_unsel) {
+ break;
+ }
+ }
+
+ if (is_sel && is_unsel) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
+
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ changed_multi = true;
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+void UV_OT_select_split(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Split";
+ ot->description = "Select only entirely selected faces";
+ ot->idname = "UV_OT_select_split";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_select_split_exec;
+ ot->poll = ED_operator_uvedit; /* requires space image */
+}
+
+static void uv_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const short select)
+{
+ /* bmesh API handles flushing but not on de-select */
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode != SCE_SELECT_FACE) {
+ if (select == false) {
+ EDBM_deselect_flush(em);
+ }
+ else {
+ EDBM_select_flush(em);
+ }
+ }
+
+ if (select == false) {
+ BM_select_history_validate(em->bm);
+ }
+ }
+}
+
+static void uv_select_tag_update_for_object(Depsgraph *depsgraph,
+ const ToolSettings *ts,
+ Object *obedit)
+{
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data);
+ }
+ else {
+ Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
+ BKE_mesh_batch_cache_dirty_tag(obedit_eval->data, BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT);
+ /* Only for region redraw. */
+ WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select/Tag Flushing Utils
+ *
+ * Utility functions to flush the uv-selection from tags.
+ * \{ */
+
+/**
+ * helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face
+ */
+static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene,
+ BMEditMesh *em,
+ UvVertMap *vmap,
+ const uint efa_index,
+ BMLoop *l,
+ const bool select,
+ const int cd_loop_uv_offset)
+{
+ UvMapVert *start_vlist = NULL, *vlist_iter;
+ BMFace *efa_vlist;
+
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+
+ vlist_iter = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
+
+ while (vlist_iter) {
+ if (vlist_iter->separate) {
+ start_vlist = vlist_iter;
+ }
+
+ if (efa_index == vlist_iter->poly_index) {
+ break;
+ }
+
+ vlist_iter = vlist_iter->next;
+ }
+
+ vlist_iter = start_vlist;
+ while (vlist_iter) {
+
+ if (vlist_iter != start_vlist && vlist_iter->separate) {
+ break;
+ }
+
+ if (efa_index != vlist_iter->poly_index) {
+ BMLoop *l_other;
+ efa_vlist = BM_face_at_index(em->bm, vlist_iter->poly_index);
+ /* tf_vlist = BM_ELEM_CD_GET_VOID_P(efa_vlist, cd_poly_tex_offset); */ /* UNUSED */
+
+ l_other = BM_iter_at_index(
+ em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->loop_of_poly_index);
+
+ uvedit_uv_select_set(em, scene, l_other, select, false, cd_loop_uv_offset);
+ }
+ vlist_iter = vlist_iter->next;
+ }
+}
+
+/**
+ * Flush the selection from face tags based on sticky and selection modes.
+ *
+ * needed because settings the selection a face is done in a number of places but it also
+ * needs to respect the sticky modes for the UV verts, so dealing with the sticky modes
+ * is best done in a separate function.
+ *
+ * \note This function is very similar to #uv_select_flush_from_tag_loop,
+ * be sure to update both upon changing.
+ */
+static void uv_select_flush_from_tag_face(SpaceImage *sima,
+ Scene *scene,
+ Object *obedit,
+ const bool select)
+{
+ /* Selecting UV Faces with some modes requires us to change
+ * the selection in other faces (depending on the sticky mode).
+ *
+ * This only needs to be done when the Mesh is not used for
+ * selection (so for sticky modes, vertex or location based). */
+
+ const ToolSettings *ts = scene->toolsettings;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) {
+ /* Tag all verts as untouched, then touch the ones that have a face center
+ * in the loop and select all MLoopUV's that use a touched vert. */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ /* now select tagged verts */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ }
+ }
+ }
+ }
+ else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) {
+ struct UvVertMap *vmap;
+ float limit[2];
+ uint efa_index;
+
+ uv_select_island_limit_default(sima, limit);
+
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE);
+ vmap = BM_uv_vert_map_create(em->bm, limit, false, false);
+ if (vmap == NULL) {
+ return;
+ }
+
+ BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) {
+ if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+ /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ uv_select_flush_from_tag_sticky_loc_internal(
+ scene, em, vmap, efa_index, l, select, cd_loop_uv_offset);
+ }
+ }
+ }
+ BM_uv_vert_map_free(vmap);
+ }
+ else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+ uvedit_face_select_set(scene, em, efa, select, false, cd_loop_uv_offset);
+ }
+ }
+ }
+}
+
+/**
+ * Flush the selection from loop tags based on sticky and selection modes.
+ *
+ * needed because settings the selection a face is done in a number of places but it also needs
+ * to respect the sticky modes for the UV verts, so dealing with the sticky modes is best done
+ * in a separate function.
+ *
+ * \note This function is very similar to #uv_select_flush_from_tag_loop,
+ * be sure to update both upon changing.
+ */
+static void uv_select_flush_from_tag_loop(SpaceImage *sima,
+ Scene *scene,
+ Object *obedit,
+ const bool select)
+{
+ /* Selecting UV Loops with some modes requires us to change
+ * the selection in other faces (depending on the sticky mode).
+ *
+ * This only needs to be done when the Mesh is not used for
+ * selection (so for sticky modes, vertex or location based). */
+
+ const ToolSettings *ts = scene->toolsettings;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) {
+ /* Tag all verts as untouched, then touch the ones that have a face center
+ * in the loop and select all MLoopUV's that use a touched vert. */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ /* now select tagged verts */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ }
+ }
+ }
+ }
+ else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) {
+ struct UvVertMap *vmap;
+ float limit[2];
+ uint efa_index;
+
+ uv_select_island_limit_default(sima, limit);
+
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE);
+ vmap = BM_uv_vert_map_create(em->bm, limit, false, false);
+ if (vmap == NULL) {
+ return;
+ }
+
+ BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) {
+ /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
+ uv_select_flush_from_tag_sticky_loc_internal(
+ scene, em, vmap, efa_index, l, select, cd_loop_uv_offset);
+ }
+ }
+ }
+ BM_uv_vert_map_free(vmap);
+ }
+ else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ }
+ }
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Box Select Operator
+ * \{ */
+
+static int uv_box_select_exec(bContext *C, wmOperator *op)
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ const ToolSettings *ts = scene->toolsettings;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Image *ima = CTX_data_edit_image(C);
+ const ARegion *region = CTX_wm_region(C);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ rctf rectf;
+ bool pinned;
+ float limit[2];
+ const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_FACE) :
+ (ts->uv_selectmode == UV_SELECT_FACE));
+ const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_EDGE) :
+ (ts->uv_selectmode == UV_SELECT_EDGE));
+
+ /* get rectangle from operator */
+ WM_operator_properties_border_to_rctf(op, &rectf);
+ UI_view2d_region_to_view_rctf(&region->v2d, &rectf, &rectf);
+
+ const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ const bool select = (sel_op != SEL_OP_SUB);
+ const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op);
+
+ pinned = RNA_boolean_get(op->ptr, "pinned");
+
+ uv_select_island_limit_default(sima, limit);
+
+ bool changed_multi = false;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ if (use_pre_deselect) {
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ }
+
+ /* don't indent to avoid diff noise! */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ bool changed = false;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* do actual selection */
+ if (use_face_center && !pinned) {
+ /* handle face selection mode */
+ float cent[2];
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ /* assume not touched */
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
+
+ if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ uv_poly_center(efa, cent, cd_loop_uv_offset);
+ if (BLI_rctf_isect_pt_v(&rectf, cent)) {
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ changed = true;
+ }
+ }
+ }
+
+ /* (de)selects all tagged faces and deals with sticky modes */
+ if (changed) {
+ uv_select_flush_from_tag_face(sima, scene, obedit, select);
+ }
+ }
+ else if (use_edge && !pinned) {
+ changed = true;
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev;
+ MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset);
+ bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset);
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ if ((select != luv_select) || (select != luv_select_prev)) {
+ if (BLI_rctf_isect_pt_v(&rectf, luv->uv) &&
+ BLI_rctf_isect_pt_v(&rectf, luv_prev->uv)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
+ }
+ }
+ l_prev = l;
+ luv_prev = luv;
+ luv_select_prev = luv_select;
+ }
+ }
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
+ }
+ else {
+ /* other selection modes */
+ changed = true;
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+ bool has_selected = false;
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
+ if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) {
+ /* UV_SYNC_SELECTION - can't do pinned selection */
+ if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ has_selected = true;
+ }
+ }
+ else if (pinned) {
+ if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+ if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) {
+ UvNearestHit hit = {
+ .ob = obedit,
+ .efa = efa,
+ };
+ uv_select_linked_multi(
+ scene, ima, objects, objects_len, limit, &hit, true, !select, false, false);
+ }
+ }
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
+ }
+
+ if (changed || use_pre_deselect) {
+ changed_multi = true;
+
+ uv_select_sync_flush(ts, em, select);
+ uv_select_tag_update_for_object(depsgraph, ts, obedit);
+ }
+ }
+
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+void UV_OT_select_box(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Box Select";
+ ot->description = "Select UV vertices using box selection";
+ ot->idname = "UV_OT_select_box";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = uv_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->poll = ED_operator_uvedit_space_image; /* requires space image */
+ ot->cancel = WM_gesture_box_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only");
+
+ WM_operator_properties_gesture_box(ot);
+ WM_operator_properties_select_operation_simple(ot);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Circle Select Operator
+ * \{ */
+
+static int uv_circle_select_is_point_inside(const float uv[2],
+ const float offset[2],
+ const float ellipse[2])
+{
+ /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
+ const float co[2] = {
+ (uv[0] - offset[0]) * ellipse[0],
+ (uv[1] - offset[1]) * ellipse[1],
+ };
+ return len_squared_v2(co) < 1.0f;
+}
+
+static int uv_circle_select_is_edge_inside(const float uv_a[2],
+ const float uv_b[2],
+ const float offset[2],
+ const float ellipse[2])
+{
+ /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
+ const float co_a[2] = {
+ (uv_a[0] - offset[0]) * ellipse[0],
+ (uv_a[1] - offset[1]) * ellipse[1],
+ };
+ const float co_b[2] = {
+ (uv_b[0] - offset[0]) * ellipse[0],
+ (uv_b[1] - offset[1]) * ellipse[1],
+ };
+ return dist_squared_to_line_segment_v2((const float[2]){0.0f, 0.0f}, co_a, co_b) < 1.0f;
+}
+
+static int uv_circle_select_exec(bContext *C, wmOperator *op)
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const ToolSettings *ts = scene->toolsettings;
+ const ARegion *region = CTX_wm_region(C);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ int x, y, radius, width, height;
+ float zoomx, zoomy;
+ float limit[2], offset[2], ellipse[2];
+
+ const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_FACE) :
+ (ts->uv_selectmode == UV_SELECT_FACE));
+ const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_EDGE) :
+ (ts->uv_selectmode == UV_SELECT_EDGE));
+
+ /* get operator properties */
+ x = RNA_int_get(op->ptr, "x");
+ y = RNA_int_get(op->ptr, "y");
+ radius = RNA_int_get(op->ptr, "radius");
+
+ /* compute ellipse size and location, not a circle since we deal
+ * with non square image. ellipse is normalized, r = 1.0. */
+ ED_space_image_get_size(sima, &width, &height);
+ ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
+
+ ellipse[0] = width * zoomx / radius;
+ ellipse[1] = height * zoomy / radius;
+
+ UI_view2d_region_to_view(&region->v2d, x, y, &offset[0], &offset[1]);
+
+ uv_select_island_limit_default(sima, limit);
+
+ bool changed_multi = false;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
+ WM_gesture_is_modal_first(op->customdata));
+ const bool select = (sel_op != SEL_OP_SUB);
+ const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op);
+
+ if (use_pre_deselect) {
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ bool changed = false;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* do selection */
+ if (use_face_center) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ /* assume not touched */
+ if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
+ float cent[2];
+ uv_poly_center(efa, cent, cd_loop_uv_offset);
+ if (uv_circle_select_is_point_inside(cent, offset, ellipse)) {
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ changed = true;
+ }
+ }
+ }
+
+ /* (de)selects all tagged faces and deals with sticky modes */
+ if (changed) {
+ uv_select_flush_from_tag_face(sima, scene, obedit, select);
+ }
+ }
+ else if (use_edge) {
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev;
+ MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset);
+ bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset);
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ if ((select != luv_select) || (select != luv_select_prev)) {
+ if (uv_circle_select_is_edge_inside(luv->uv, luv_prev->uv, offset, ellipse)) {
+ changed = true;
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
+ }
+ }
+ l_prev = l;
+ luv_prev = luv;
+ luv_select_prev = luv_select;
+ }
+ }
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
+ }
+ else {
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+ bool has_selected = false;
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (uv_circle_select_is_point_inside(luv->uv, offset, ellipse)) {
+ changed = true;
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ has_selected = true;
+ }
+ }
+ }
+ if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) {
+ UvNearestHit hit = {
+ .ob = obedit,
+ .efa = efa,
+ };
+ uv_select_linked_multi(
+ scene, ima, objects, objects_len, limit, &hit, true, !select, false, false);
+ }
+ }
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
+ }
+
+ if (changed || use_pre_deselect) {
+ changed_multi = true;
+
+ uv_select_sync_flush(ts, em, select);
+ uv_select_tag_update_for_object(depsgraph, ts, obedit);
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+void UV_OT_select_circle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Circle Select";
+ ot->description = "Select UV vertices using circle selection";
+ ot->idname = "UV_OT_select_circle";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = uv_circle_select_exec;
+ ot->poll = ED_operator_uvedit_space_image; /* requires space image */
+ ot->cancel = WM_gesture_circle_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_gesture_circle(ot);
+ WM_operator_properties_select_operation_simple(ot);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Lasso Select Operator
+ * \{ */
+
+static bool do_lasso_select_mesh_uv_is_point_inside(const ARegion *region,
+ const rcti *clip_rect,
+ const int mcoords[][2],
+ const int mcoords_len,
+ const float co_test[2])
+{
+ int co_screen[2];
+ if (UI_view2d_view_to_region_clip(
+ &region->v2d, co_test[0], co_test[1], &co_screen[0], &co_screen[1]) &&
+ BLI_rcti_isect_pt_v(clip_rect, co_screen) &&
+ BLI_lasso_is_point_inside(
+ mcoords, mcoords_len, co_screen[0], co_screen[1], V2D_IS_CLIPPED)) {
+ return true;
+ }
+ return false;
+}
+
+static bool do_lasso_select_mesh_uv(bContext *C,
+ const int mcoords[][2],
+ const int mcoords_len,
+ const eSelectOp sel_op)
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+ const ARegion *region = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ const ToolSettings *ts = scene->toolsettings;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_FACE) :
+ (ts->uv_selectmode == UV_SELECT_FACE));
+ const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_EDGE) :
+ (ts->uv_selectmode == UV_SELECT_EDGE));
+
+ const bool select = (sel_op != SEL_OP_SUB);
+ const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op);
+
+ BMIter iter, liter;
+
+ BMFace *efa;
+ BMLoop *l;
+ float limit[2];
+ bool changed_multi = false;
+ rcti rect;
+
+ uv_select_island_limit_default(sima, limit);
+
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ if (use_pre_deselect) {
+ uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ }
+
+ /* don't indent to avoid diff noise! */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+
+ bool changed = false;
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (use_face_center) { /* Face Center Sel */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ /* assume not touched */
+ if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
+ float cent[2];
+ uv_poly_center(efa, cent, cd_loop_uv_offset);
+ if (do_lasso_select_mesh_uv_is_point_inside(region, &rect, mcoords, mcoords_len, cent)) {
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ changed = true;
+ }
+ }
+ }
+
+ /* (de)selects all tagged faces and deals with sticky modes */
+ if (changed) {
+ uv_select_flush_from_tag_face(sima, scene, obedit, select);
+ }
+ }
+ else if (use_edge) {
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev;
+ MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset);
+ bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset);
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ if ((select != luv_select) || (select != luv_select_prev)) {
+ if (do_lasso_select_mesh_uv_is_point_inside(
+ region, &rect, mcoords, mcoords_len, luv->uv) &&
+ do_lasso_select_mesh_uv_is_point_inside(
+ region, &rect, mcoords, mcoords_len, luv_prev->uv)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset);
+ changed = true;
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
+ }
+ }
+ l_prev = l;
+ luv_prev = luv;
+ luv_select_prev = luv_select;
+ }
+ }
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
+ }
+ else { /* Vert Sel */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+ bool has_selected = false;
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (do_lasso_select_mesh_uv_is_point_inside(
+ region, &rect, mcoords, mcoords_len, luv->uv)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ changed = true;
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ has_selected = true;
+ }
+ }
+ }
+ if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) {
+ UvNearestHit hit = {
+ .ob = obedit,
+ .efa = efa,
+ };
+ uv_select_linked_multi(
+ scene, ima, objects, objects_len, limit, &hit, true, !select, false, false);
+ }
+ }
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
+ }
+
+ if (changed || use_pre_deselect) {
+ changed_multi = true;
+
+ uv_select_sync_flush(ts, em, select);
+ uv_select_tag_update_for_object(depsgraph, ts, obedit);
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi;
+}
+
+static int uv_lasso_select_exec(bContext *C, wmOperator *op)
+{
+ int mcoords_len;
+ const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len);
+
+ if (mcoords) {
+ const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ bool changed = do_lasso_select_mesh_uv(C, mcoords, mcoords_len, sel_op);
+ MEM_freeN((void *)mcoords);
+
+ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+void UV_OT_select_lasso(wmOperatorType *ot)
+{
+ ot->name = "Lasso Select UV";
+ ot->description = "Select UVs using lasso selection";
+ ot->idname = "UV_OT_select_lasso";
+
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = uv_lasso_select_exec;
+ ot->poll = ED_operator_uvedit_space_image;
+ ot->cancel = WM_gesture_lasso_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_gesture_lasso(ot);
+ WM_operator_properties_select_operation_simple(ot);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Pinned UV's Operator
+ * \{ */
+
+static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ const ToolSettings *ts = scene->toolsettings;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Image *ima = CTX_data_edit_image(C);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ bool changed = false;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ continue;
+ }
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ if (luv->flag & MLOOPUV_PINNED) {
+ uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ uv_select_tag_update_for_object(depsgraph, ts, obedit);
+ }
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
+}
+
+void UV_OT_select_pinned(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Selected Pinned";
+ ot->description = "Select all pinned UV vertices";
+ ot->idname = "UV_OT_select_pinned";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_select_pinned_exec;
+ ot->poll = ED_operator_uvedit;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Overlap Operator
+ * \{ */
+
+BLI_INLINE uint overlap_hash(const void *overlap_v)
+{
+ const BVHTreeOverlap *overlap = overlap_v;
+
+ /* Designed to treat (A,B) and (B,A) as the same. */
+ int x = overlap->indexA;
+ int y = overlap->indexB;
+ if (x > y) {
+ SWAP(int, x, y);
+ }
+ return BLI_hash_int_2d(x, y);
+}
+
+BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v)
+{
+ const BVHTreeOverlap *a = a_v;
+ const BVHTreeOverlap *b = b_v;
+ return !((a->indexA == b->indexA && a->indexB == b->indexB) ||
+ (a->indexA == b->indexB && a->indexB == b->indexA));
+}
+
+struct UVOverlapData {
+ int ob_index;
+ int face_index;
+ float tri[3][2];
+};
+
+static int uv_select_overlap(bContext *C, const bool extend)
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Image *ima = CTX_data_edit_image(C);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ /* Calculate maximum number of tree nodes and prepare initial selection. */
+ uint uv_tri_len = 0;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE);
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+ if (!extend) {
+ uv_select_all_perform(scene, ima, obedit, SEL_DESELECT);
+ }
+
+ BMIter iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) {
+ continue;
+ }
+ uv_tri_len += efa->len - 2;
+ }
+ }
+
+ struct UVOverlapData *overlap_data = MEM_mallocN(sizeof(struct UVOverlapData) * uv_tri_len,
+ "UvOverlapData");
+ BVHTree *uv_tree = BLI_bvhtree_new(uv_tri_len, 0.0f, 4, 6);
+
+ /* Use a global data index when inserting into the BVH. */
+ int data_index = 0;
+
+ int face_len_alloc = 3;
+ float(*uv_verts)[2] = MEM_mallocN(sizeof(*uv_verts) * face_len_alloc, "UvOverlapCoords");
+ uint(*indices)[3] = MEM_mallocN(sizeof(*indices) * (face_len_alloc - 2), "UvOverlapTris");
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMIter iter, liter;
+ BMFace *efa;
+ BMLoop *l;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* Triangulate each UV face and store it inside the BVH. */
+ int face_index;
+ BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, face_index) {
+
+ if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) {
+ continue;
+ }
+
+ const uint face_len = efa->len;
+ const uint tri_len = face_len - 2;
+
+ if (face_len_alloc < face_len) {
+ MEM_freeN(uv_verts);
+ MEM_freeN(indices);
+ uv_verts = MEM_mallocN(sizeof(*uv_verts) * face_len, "UvOverlapCoords");
+ indices = MEM_mallocN(sizeof(*indices) * tri_len, "UvOverlapTris");
+ face_len_alloc = face_len;
+ }
+
+ int vert_index;
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, vert_index) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(uv_verts[vert_index], luv->uv);
+ }
+
+ BLI_polyfill_calc(uv_verts, face_len, 0, indices);
+
+ for (int t = 0; t < tri_len; t++) {
+ overlap_data[data_index].ob_index = ob_index;
+ overlap_data[data_index].face_index = face_index;
+
+ /* BVH needs 3D, overlap data uses 2D. */
+ const float tri[3][3] = {
+ {UNPACK2(uv_verts[indices[t][0]]), 0.0f},
+ {UNPACK2(uv_verts[indices[t][1]]), 0.0f},
+ {UNPACK2(uv_verts[indices[t][2]]), 0.0f},
+ };
+
+ copy_v2_v2(overlap_data[data_index].tri[0], tri[0]);
+ copy_v2_v2(overlap_data[data_index].tri[1], tri[1]);
+ copy_v2_v2(overlap_data[data_index].tri[2], tri[2]);
+
+ BLI_bvhtree_insert(uv_tree, data_index, &tri[0][0], 3);
+ data_index++;
+ }
+ }
+ }
+ BLI_assert(data_index == uv_tri_len);
+
+ MEM_freeN(uv_verts);
+ MEM_freeN(indices);
+
+ BLI_bvhtree_balance(uv_tree);
+
+ uint tree_overlap_len;
+ BVHTreeOverlap *overlap = BLI_bvhtree_overlap(uv_tree, uv_tree, &tree_overlap_len, NULL, NULL);
+
+ if (overlap != NULL) {
+ GSet *overlap_set = BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, tree_overlap_len);
+
+ for (int i = 0; i < tree_overlap_len; i++) {
+ /* Skip overlaps against yourself. */
+ if (overlap[i].indexA == overlap[i].indexB) {
+ continue;
+ }
+
+ /* Skip overlaps that have already been tested. */
+ if (!BLI_gset_add(overlap_set, &overlap[i])) {
+ continue;
+ }
+
+ const struct UVOverlapData *o_a = &overlap_data[overlap[i].indexA];
+ const struct UVOverlapData *o_b = &overlap_data[overlap[i].indexB];
+ Object *obedit_a = objects[o_a->ob_index];
+ Object *obedit_b = objects[o_b->ob_index];
+ BMEditMesh *em_a = BKE_editmesh_from_object(obedit_a);
+ BMEditMesh *em_b = BKE_editmesh_from_object(obedit_b);
+ BMFace *face_a = em_a->bm->ftable[o_a->face_index];
+ BMFace *face_b = em_b->bm->ftable[o_b->face_index];
+ const int cd_loop_uv_offset_a = CustomData_get_offset(&em_a->bm->ldata, CD_MLOOPUV);
+ const int cd_loop_uv_offset_b = CustomData_get_offset(&em_b->bm->ldata, CD_MLOOPUV);
+
+ /* Skip if both faces are already selected. */
+ if (uvedit_face_select_test(scene, face_a, cd_loop_uv_offset_a) &&
+ uvedit_face_select_test(scene, face_b, cd_loop_uv_offset_b)) {
+ continue;
+ }
+
+ /* Main tri-tri overlap test. */
+ const float endpoint_bias = -1e-4f;
+ const float(*t1)[2] = o_a->tri;
+ const float(*t2)[2] = o_b->tri;
+ float vi[2];
+ bool result = (
+ /* Don't use 'isect_tri_tri_v2' here
+ * because it's important to ignore overlap at end-points. */
+ isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[0], t2[1], endpoint_bias, vi) == 1 ||
+ isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[1], t2[2], endpoint_bias, vi) == 1 ||
+ isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[2], t2[0], endpoint_bias, vi) == 1 ||
+ isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[0], t2[1], endpoint_bias, vi) == 1 ||
+ isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[1], t2[2], endpoint_bias, vi) == 1 ||
+ isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[2], t2[0], endpoint_bias, vi) == 1 ||
+ isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[0], t2[1], endpoint_bias, vi) == 1 ||
+ isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[1], t2[2], endpoint_bias, vi) == 1 ||
+ isect_point_tri_v2(t1[0], t2[0], t2[1], t2[2]) != 0 ||
+ isect_point_tri_v2(t2[0], t1[0], t1[1], t1[2]) != 0);
+
+ if (result) {
+ uvedit_face_select_enable(scene, em_a, face_a, false, cd_loop_uv_offset_a);
+ uvedit_face_select_enable(scene, em_b, face_b, false, cd_loop_uv_offset_b);
+ }
+ }
+
+ BLI_gset_free(overlap_set, NULL);
+ MEM_freeN(overlap);
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ uv_select_tag_update_for_object(depsgraph, scene->toolsettings, objects[ob_index]);
+ }
+
+ BLI_bvhtree_free(uv_tree);
+
+ MEM_freeN(overlap_data);
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
+}
+
+static int uv_select_overlap_exec(bContext *C, wmOperator *op)
+{
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ return uv_select_overlap(C, extend);
+}
+
+void UV_OT_select_overlap(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Overlap";
+ ot->description = "Select all UV faces which overlap each other";
+ ot->idname = "UV_OT_select_overlap";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = uv_select_overlap_exec;
+ ot->poll = ED_operator_uvedit;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ 0,
+ "Extend",
+ "Extend selection rather than clearing the existing selection");
+}
+
+/** \} */
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 5d3d016e6c1..3a4f12acf9c 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -21,38 +21,38 @@
* \ingroup eduv
*/
+#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include "MEM_guardedalloc.h"
-#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_mesh_mapping.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
+#include "BKE_mesh_mapping.h"
#include "DEG_depsgraph.h"
#include "UI_interface.h"
#include "ED_mesh.h"
-#include "ED_uvedit.h"
#include "ED_screen.h"
#include "ED_space_api.h"
+#include "ED_uvedit.h"
#include "GPU_batch.h"
#include "GPU_state.h"
@@ -63,8 +63,8 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_view2d.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "uvedit_intern.h"
@@ -75,20 +75,20 @@ typedef struct StitchPreviewer {
/* here we'll store the preview triangle indices of the mesh */
float *preview_polys;
/* uvs per polygon. */
- unsigned int *uvs_per_polygon;
+ uint *uvs_per_polygon;
/*number of preview polygons */
- unsigned int num_polys;
+ uint num_polys;
/* preview data. These will be either the previewed vertices or edges
* depending on stitch mode settings */
float *preview_stitchable;
float *preview_unstitchable;
/* here we'll store the number of elements to be drawn */
- unsigned int num_stitchable;
- unsigned int num_unstitchable;
- unsigned int preview_uvs;
+ uint num_stitchable;
+ uint num_unstitchable;
+ uint preview_uvs;
/* ...and here we'll store the static island triangles */
float *static_tris;
- unsigned int num_static_tris;
+ uint num_static_tris;
} StitchPreviewer;
struct IslandStitchData;
@@ -119,16 +119,16 @@ typedef struct IslandStitchData {
/* just for averaging UVs */
typedef struct UVVertAverage {
float uv[2];
- unsigned short count;
+ ushort count;
} UVVertAverage;
typedef struct UvEdge {
/** index to uv buffer */
- unsigned int uv1;
- unsigned int uv2;
+ uint uv1;
+ uint uv2;
/** general use flag
* (Used to check if edge is boundary here, and propagates to adjacency elements) */
- unsigned char flag;
+ uchar flag;
/** element that guarantees element->face
* has the edge on element->tfindex and element->tfindex+1 is the second uv */
UvElement *element;
@@ -172,7 +172,7 @@ typedef struct StitchState {
int selection_size;
/* store number of primitives per face so that we can allocate the active island buffer later */
- unsigned int *tris_per_island;
+ uint *tris_per_island;
/* preview data */
StitchPreviewer *stitch_preview;
} StitchState;
@@ -299,9 +299,9 @@ static void stitch_update_header(StitchStateContainer *ssc, bContext *C)
"shift select vertices");
char msg[UI_MAX_DRAW_STR];
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- if (sa) {
+ if (area) {
BLI_snprintf(msg,
sizeof(msg),
str,
@@ -544,7 +544,7 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge,
StitchStateContainer *ssc,
StitchState *state,
UVVertAverage *uv_average,
- unsigned int *uvfinal_map,
+ uint *uvfinal_map,
IslandStitchData *island_stitch_data)
{
BMesh *bm = state->em->bm;
@@ -1032,7 +1032,7 @@ static int stitch_process_data(StitchStateContainer *ssc,
char stitch_midpoints = ssc->midpoints;
/* used to map uv indices to uvaverage indices for selection */
- unsigned int *uvfinal_map = NULL;
+ uint *uvfinal_map = NULL;
/* per face preview position in preview buffer */
PreviewPosition *preview_position = NULL;
@@ -1229,7 +1229,7 @@ static int stitch_process_data(StitchStateContainer *ssc,
BMIter liter;
BMLoop *l;
MLoopUV *luv;
- unsigned int buffer_index = 0;
+ uint buffer_index = 0;
/* initialize the preview buffers */
preview->preview_polys = MEM_mallocN(preview->preview_uvs * sizeof(float) * 2,
@@ -1575,7 +1575,7 @@ static int stitch_process_data_all(StitchStateContainer *ssc, Scene *scene, int
}
/* Stitch hash initialization functions */
-static unsigned int uv_edge_hash(const void *key)
+static uint uv_edge_hash(const void *key)
{
const UvEdge *edge = key;
return (BLI_ghashutil_uinthash(edge->uv2) + BLI_ghashutil_uinthash(edge->uv1));
@@ -1753,21 +1753,21 @@ static void stitch_draw_vbo(GPUVertBuf *vbo, GPUPrimType prim_type, const float
}
/* TODO make things pretier : store batches inside StitchPreviewer instead of the bare verts pos */
-static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
{
StitchStateContainer *ssc = (StitchStateContainer *)arg;
for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
int j, index = 0;
- unsigned int num_line = 0, num_tri, tri_idx = 0, line_idx = 0;
+ uint num_line = 0, num_tri, tri_idx = 0, line_idx = 0;
StitchState *state = ssc->states[ob_index];
StitchPreviewer *stitch_preview = state->stitch_preview;
GPUVertBuf *vbo, *vbo_line;
float col[4];
static GPUVertFormat format = {0};
- static unsigned int pos_id;
+ static uint pos_id;
if (format.attr_len == 0) {
pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
@@ -2254,8 +2254,8 @@ static bool goto_next_island(StitchStateContainer *ssc)
static int stitch_init_all(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
- if (!ar) {
+ ARegion *region = CTX_wm_region(C);
+ if (!region) {
return 0;
}
@@ -2399,7 +2399,8 @@ static int stitch_init_all(bContext *C, wmOperator *op)
stitch_update_header(ssc, C);
- ssc->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, ssc, REGION_DRAW_POST_VIEW);
+ ssc->draw_handle = ED_region_draw_cb_activate(
+ region->type, stitch_draw, ssc, REGION_DRAW_POST_VIEW);
return 1;
}
@@ -2437,7 +2438,7 @@ static void stitch_exit(bContext *C, wmOperator *op, int finished)
{
Scene *scene = CTX_data_scene(C);
SpaceImage *sima = CTX_wm_space_image(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
StitchStateContainer *ssc = (StitchStateContainer *)op->customdata;
@@ -2491,7 +2492,7 @@ static void stitch_exit(bContext *C, wmOperator *op, int finished)
MEM_freeN(objs_selection_count);
}
- if (sa) {
+ if (area) {
ED_workspace_status_text(C, NULL);
}
@@ -2548,10 +2549,10 @@ static StitchState *stitch_select(bContext *C,
/* add uv under mouse to processed uv's */
float co[2];
UvNearestHit hit = UV_NEAREST_HIT_INIT;
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
Image *ima = CTX_data_edit_image(C);
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
if (ssc->mode == STITCH_VERT) {
if (uv_find_nearest_vert_multi(scene, ima, ssc->objects, ssc->objects_len, co, 0.0f, &hit)) {
@@ -2607,13 +2608,13 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_PASS_THROUGH;
/* Cancel */
- case ESCKEY:
+ case EVT_ESCKEY:
stitch_cancel(C, op);
return OPERATOR_CANCELLED;
case LEFTMOUSE:
- case PADENTER:
- case RETKEY:
+ case EVT_PADENTER:
+ case EVT_RETKEY:
if (event->val == KM_PRESS) {
if (stitch_process_data(ssc, active_state, scene, true)) {
stitch_exit(C, op, 1);
@@ -2628,7 +2629,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_PASS_THROUGH;
}
/* Increase limit */
- case PADPLUSKEY:
+ case EVT_PADPLUSKEY:
case WHEELUPMOUSE:
if (event->val == KM_PRESS && event->alt) {
ssc->limit_dist += 0.01f;
@@ -2642,7 +2643,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_PASS_THROUGH;
}
/* Decrease limit */
- case PADMINUS:
+ case EVT_PADMINUS:
case WHEELDOWNMOUSE:
if (event->val == KM_PRESS && event->alt) {
ssc->limit_dist -= 0.01f;
@@ -2658,7 +2659,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* Use Limit (Default off) */
- case LKEY:
+ case EVT_LKEY:
if (event->val == KM_PRESS) {
ssc->use_limit = !ssc->use_limit;
if (!stitch_process_data(ssc, active_state, scene, false)) {
@@ -2669,7 +2670,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
return OPERATOR_RUNNING_MODAL;
- case IKEY:
+ case EVT_IKEY:
if (event->val == KM_PRESS) {
/* Move to next island and maybe next object */
@@ -2693,7 +2694,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
return OPERATOR_RUNNING_MODAL;
- case MKEY:
+ case EVT_MKEY:
if (event->val == KM_PRESS) {
ssc->midpoints = !ssc->midpoints;
if (!stitch_process_data(ssc, active_state, scene, false)) {
@@ -2721,7 +2722,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
/* snap islands on/off */
- case SKEY:
+ case EVT_SKEY:
if (event->val == KM_PRESS) {
ssc->snap_islands = !ssc->snap_islands;
if (!stitch_process_data(ssc, active_state, scene, false)) {
@@ -2735,7 +2736,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* switch between edge/vertex mode */
- case TABKEY:
+ case EVT_TABKEY:
if (event->val == KM_PRESS) {
stitch_switch_selection_mode_all(ssc);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 1e758771f6a..c4dcaaaa8b2 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -21,38 +21,40 @@
* \ingroup eduv
*/
-#include <string.h>
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_camera_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_modifier_types.h"
-#include "BLI_utildefines.h"
#include "BLI_alloca.h"
#include "BLI_math.h"
-#include "BLI_uvproject.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
+#include "BLI_uvproject.h"
#include "BLT_translation.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_subsurf.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_mesh.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "BKE_editmesh.h"
-#include "BKE_layer.h"
+#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
@@ -75,6 +77,10 @@
#include "uvedit_intern.h"
#include "uvedit_parametrizer.h"
+/* -------------------------------------------------------------------- */
+/** \name Utility Functions
+ * \{ */
+
static void modifier_unwrap_state(Object *obedit, const Scene *scene, bool *r_use_subsurf)
{
ModifierData *md;
@@ -131,13 +137,21 @@ static bool ED_uvedit_ensure_uvs(Object *obedit)
return 1;
}
-/****************** Parametrizer Conversion ***************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Parametrizer Conversion
+ * \{ */
typedef struct UnwrapOptions {
- bool topology_from_uvs; /* Connectivity based on UV coordinates instead of seams. */
- bool only_selected; /* Only affect selected faces. */
- bool fill_holes; /* Fill holes to better preserve shape. */
- bool correct_aspect; /* Correct for mapped image texture aspect ratio. */
+ /** Connectivity based on UV coordinates instead of seams. */
+ bool topology_from_uvs;
+ /** Only affect selected faces. */
+ bool only_selected;
+ /** Fill holes to better preserve shape. */
+ bool fill_holes;
+ /** Correct for mapped image texture aspect ratio. */
+ bool correct_aspect;
} UnwrapOptions;
static bool uvedit_have_selection(const Scene *scene, BMEditMesh *em, const UnwrapOptions *options)
@@ -197,7 +211,7 @@ static bool uvedit_have_selection_multi(const Scene *scene,
}
void ED_uvedit_get_aspect(
- const Scene *UNUSED(scene), Object *ob, BMesh *bm, float *aspx, float *aspy)
+ const Scene *UNUSED(scene), Object *ob, BMesh *bm, float *r_aspx, float *r_aspy)
{
bool sloppy = true;
bool selected = false;
@@ -209,11 +223,11 @@ void ED_uvedit_get_aspect(
if (efa) {
ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL);
- ED_image_get_uv_aspect(ima, NULL, aspx, aspy);
+ ED_image_get_uv_aspect(ima, NULL, r_aspx, r_aspy);
}
else {
- *aspx = 1.0f;
- *aspy = 1.0f;
+ *r_aspx = 1.0f;
+ *r_aspy = 1.0f;
}
}
@@ -408,21 +422,21 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene,
return handle;
}
-static void texface_from_original_index(BMFace *efa,
+static void texface_from_original_index(const Scene *scene,
+ const int cd_loop_uv_offset,
+ BMFace *efa,
int index,
- float **uv,
- ParamBool *pin,
- ParamBool *select,
- const Scene *scene,
- const int cd_loop_uv_offset)
+ float **r_uv,
+ ParamBool *r_pin,
+ ParamBool *r_select)
{
BMLoop *l;
BMIter liter;
MLoopUV *luv;
- *uv = NULL;
- *pin = 0;
- *select = 1;
+ *r_uv = NULL;
+ *r_pin = 0;
+ *r_select = 1;
if (index == ORIGINDEX_NONE) {
return;
@@ -431,9 +445,9 @@ static void texface_from_original_index(BMFace *efa,
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_index_get(l->v) == index) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- *uv = luv->uv;
- *pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0;
- *select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ *r_uv = luv->uv;
+ *r_pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0;
+ *r_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
break;
}
}
@@ -500,11 +514,15 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
smd.levels = smd_real->levels;
smd.subdivType = smd_real->subdivType;
- initialDerived = CDDM_from_editbmesh(em, false);
- derivedMesh = subsurf_make_derived_from_derived(
- initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE);
+ {
+ Mesh *me_from_em = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL, ob->data);
+ initialDerived = CDDM_from_mesh(me_from_em);
+ derivedMesh = subsurf_make_derived_from_derived(
+ initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE);
- initialDerived->release(initialDerived);
+ initialDerived->release(initialDerived);
+ BKE_id_free(NULL, me_from_em);
+ }
/* get the derived data */
subsurfedVerts = derivedMesh->getVertArray(derivedMesh);
@@ -577,34 +595,34 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
/* This is where all the magic is done.
* If the vertex exists in the, we pass the original uv pointer to the solver, thus
* flushing the solution to the edit mesh. */
- texface_from_original_index(origFace,
+ texface_from_original_index(scene,
+ cd_loop_uv_offset,
+ origFace,
origVertIndices[mloop[0].v],
&uv[0],
&pin[0],
- &select[0],
- scene,
- cd_loop_uv_offset);
- texface_from_original_index(origFace,
+ &select[0]);
+ texface_from_original_index(scene,
+ cd_loop_uv_offset,
+ origFace,
origVertIndices[mloop[1].v],
&uv[1],
&pin[1],
- &select[1],
- scene,
- cd_loop_uv_offset);
- texface_from_original_index(origFace,
+ &select[1]);
+ texface_from_original_index(scene,
+ cd_loop_uv_offset,
+ origFace,
origVertIndices[mloop[2].v],
&uv[2],
&pin[2],
- &select[2],
- scene,
- cd_loop_uv_offset);
- texface_from_original_index(origFace,
+ &select[2]);
+ texface_from_original_index(scene,
+ cd_loop_uv_offset,
+ origFace,
origVertIndices[mloop[3].v],
&uv[3],
&pin[3],
- &select[3],
- scene,
- cd_loop_uv_offset);
+ &select[3]);
param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
}
@@ -629,7 +647,11 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
return handle;
}
-/* ******************** Minimize Stretch operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Minimize Stretch Operator
+ * \{ */
typedef struct MinStretch {
const Scene *scene;
@@ -686,7 +708,7 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op)
static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interactive)
{
MinStretch *ms = op->customdata;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
const Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
@@ -702,9 +724,9 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interac
param_flush(ms->handle);
- if (sa) {
+ if (area) {
BLI_snprintf(str, sizeof(str), TIP_("Minimize Stretch. Blend %.2f"), ms->blend);
- ED_area_status_text(sa, str);
+ ED_area_status_text(area, str);
ED_workspace_status_text(C, TIP_("Press + and -, or scroll wheel to set blending"));
}
@@ -727,12 +749,12 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interac
static void minimize_stretch_exit(bContext *C, wmOperator *op, bool cancel)
{
MinStretch *ms = op->customdata;
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
const Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
- ED_area_status_text(sa, NULL);
+ ED_area_status_text(area, NULL);
ED_workspace_status_text(C, NULL);
if (ms->timer) {
@@ -805,16 +827,16 @@ static int minimize_stretch_modal(bContext *C, wmOperator *op, const wmEvent *ev
MinStretch *ms = op->customdata;
switch (event->type) {
- case ESCKEY:
+ case EVT_ESCKEY:
case RIGHTMOUSE:
minimize_stretch_exit(C, op, true);
return OPERATOR_CANCELLED;
- case RETKEY:
- case PADENTER:
+ case EVT_RETKEY:
+ case EVT_PADENTER:
case LEFTMOUSE:
minimize_stretch_exit(C, op, false);
return OPERATOR_FINISHED;
- case PADPLUSKEY:
+ case EVT_PADPLUSKEY:
case WHEELUPMOUSE:
if (event->val == KM_PRESS) {
if (ms->blend < 0.95f) {
@@ -825,7 +847,7 @@ static int minimize_stretch_modal(bContext *C, wmOperator *op, const wmEvent *ev
}
}
break;
- case PADMINUS:
+ case EVT_PADMINUS:
case WHEELDOWNMOUSE:
if (event->val == KM_PRESS) {
if (ms->blend > 0.05f) {
@@ -902,7 +924,11 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
100);
}
-/* ******************** Pack Islands operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pack UV Islands Operator
+ * \{ */
static void uvedit_pack_islands(const Scene *scene, Object *ob, BMesh *bm)
{
@@ -1000,7 +1026,11 @@ void UV_OT_pack_islands(wmOperatorType *ot)
ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
}
-/* ******************** Average Islands Scale operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Average UV Islands Scale Operator
+ * \{ */
static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1059,7 +1089,11 @@ void UV_OT_average_islands_scale(wmOperatorType *ot)
ot->poll = ED_operator_uvedit;
}
-/**************** Live Unwrap *****************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Live UV Unwrap
+ * \{ */
static struct {
ParamHandle **handles;
@@ -1138,7 +1172,11 @@ void ED_uvedit_live_unwrap_end(short cancel)
}
}
-/*************** UV Map Common Transforms *****************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name UV Map Common Transforms
+ * \{ */
#define VIEW_ON_EQUATOR 0
#define VIEW_ON_POLES 1
@@ -1421,7 +1459,18 @@ static void correct_uv_aspect(const Scene *scene, Object *ob, BMEditMesh *em)
}
}
-/******************** Map Clip & Correct ******************/
+#undef VIEW_ON_EQUATOR
+#undef VIEW_ON_POLES
+#undef ALIGN_TO_OBJECT
+
+#undef POLAR_ZX
+#undef POLAR_ZY
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name UV Map Clip & Correct
+ * \{ */
static void uv_map_clip_correct_properties(wmOperatorType *ot)
{
@@ -1491,8 +1540,7 @@ static void uv_map_clip_correct_multi(const Scene *scene,
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- CLAMP(luv->uv[0], 0.0f, 1.0f);
- CLAMP(luv->uv[1], 0.0f, 1.0f);
+ clamp_v2(luv->uv, 0.0f, 1.0f);
}
}
}
@@ -1537,7 +1585,11 @@ static void uv_map_clip_correct(const Scene *scene, Object *ob, wmOperator *op)
uv_map_clip_correct_multi(scene, &ob, 1, op);
}
-/* ******************** Unwrap operator **************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name UV Unwrap Operator
+ * \{ */
/* Assumes UV Map exists, doesn't run update funcs. */
static void uvedit_unwrap(const Scene *scene, Object *obedit, const UnwrapOptions *options)
@@ -1778,7 +1830,12 @@ void UV_OT_unwrap(wmOperatorType *ot)
ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
}
-/**************** Project From View operator **************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Project UV From View Operator
+ * \{ */
+
static int uv_from_view_exec(bContext *C, wmOperator *op);
static int uv_from_view_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
@@ -1804,7 +1861,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
const Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
@@ -1896,7 +1953,8 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- BLI_uvproject_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
+ BLI_uvproject_from_view(
+ luv->uv, l->v->co, rv3d->persmat, rotmat, region->winx, region->winy);
}
changed = true;
}
@@ -1963,7 +2021,11 @@ void UV_OT_project_from_view(wmOperatorType *ot)
uv_map_clip_correct_properties(ot);
}
-/********************** Reset operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Reset UV Operator
+ * \{ */
static int reset_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -2011,7 +2073,11 @@ void UV_OT_reset(wmOperatorType *ot)
ot->poll = ED_operator_uvmap;
}
-/****************** Sphere Project operator ***************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sphere UV Project Operator
+ * \{ */
static void uv_sphere_project(float target[2],
const float source[3],
@@ -2138,7 +2204,11 @@ void UV_OT_sphere_project(wmOperatorType *ot)
uv_map_clip_correct_properties(ot);
}
-/***************** Cylinder Project operator **************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cylinder UV Project Operator
+ * \{ */
static void uv_cylinder_project(float target[2],
const float source[3],
@@ -2232,7 +2302,9 @@ void UV_OT_cylinder_project(wmOperatorType *ot)
uv_map_clip_correct_properties(ot);
}
-/******************* Cube Project operator ****************/
+/* -------------------------------------------------------------------- */
+/** \name Cube UV Project Operator
+ * \{ */
static void uvedit_unwrap_cube_project(BMesh *bm,
float cube_size,
@@ -2361,7 +2433,11 @@ void UV_OT_cube_project(wmOperatorType *ot)
uv_map_clip_correct_properties(ot);
}
-/************************* Simple UVs for texture painting *****************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Simple UVs for Texture Painting
+ * \{ */
void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
{
@@ -2397,3 +2473,5 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
scene->toolsettings->uv_flag |= UV_SYNC_SELECTION;
}
}
+
+/** \} */